Skip to content

webchat2api 偶发首页卡死:/health 和 /version 正常,但 / 与 /index.html 超时,重启容器后恢复 #28

Description

@QLHazyCoder

问题概述

线上遇到一个偶发问题:webchat2api 容器仍然处于运行状态,轻量健康接口也正常,但首页和前端静态页面无法打开,直到重启容器后才恢复。

这看起来不像是 Caddy、证书、域名或容器退出导致的问题,更像是应用本身进入了一种“部分存活但前端静态返回链卡死”的状态。


现象表现

问题发生时:

  • 容器仍在运行
  • GET /health 返回 200 {"status":"ok"}
  • GET /version 返回 200
  • GET / 超时
  • GET /index.html 也超时
  • 容器内 /app/web_dist/index.html 文件实际存在
  • 重启容器后,首页立即恢复正常

重启后验证:

  • /health => 200
  • /version => 200
  • / => 200
  • 首页 HTML 正常返回

为什么判断更像项目层面的问题

排查时已确认:

  • 反向代理 Caddy 配置正常
  • HTTPS 证书正常
  • 容器没有退出
  • 容器没有 OOMKilled
  • 静态文件没有丢失
  • API 轻接口仍然能正常响应

也就是说,不是整站都挂了,而是应用进入了这样一种异常状态:

  • JSON 健康接口还能回
  • 但前端首页和静态文件返回链卡住

这更像是项目内部的应用层问题,而不是纯部署问题。


运行环境

  • 镜像:ghcr.io/zqbxdev/webchat2api:latest
  • GET /version 返回:0.0.11
  • 启动方式:
    • uv run python main.py
    • uvicorn
    • entrypoint 中还会启动 Browser Bridge
  • 反向代理:Caddy
  • 容器端口:83
  • 公网域名:webchat2api.ai-api.20021108.xyz

相关代码位置

首页和静态前端回退逻辑看起来主要在这里:

  • api/app.py
  • api/support.py

当前逻辑大致是:

  • /health 直接返回 JSON
  • /{full_path:path} 使用 resolve_web_asset(...)
  • 找到文件后通过 FileResponse(...) 返回

从现象看,问题更像出在这条静态页面返回链,而不是整体路由不可用。


额外观察

排查过程中还观察到:

  • /_next/_index.txt 可以快速返回 404
  • / 和 /index.html 会持续超时
  • 容器内 /app/web_dist/index.html 文件存在且可读
  • 容器资源没有明显异常
    • 没有 OOM
    • CPU/内存也不高
  • 重启后服务立即恢复

这说明问题并不是静态文件缺失,而更像是运行时某种卡死/阻塞状态。


期望行为

如果服务还能正常返回 {"status":"ok"},那么首页静态页面也应该保持可访问。

至少不应该出现这种状态:

  • 健康检查显示正常
  • 但首页和前端页面完全打不开

怀疑方向

目前比较怀疑这些方向之一:

  • FastAPI 静态页面回退路由在某些情况下卡住
  • FileResponse(...) 返回链偶发阻塞
  • 单进程运行下,某些同步任务/线程池占用影响了静态页面响应
  • Browser Bridge 或后台 watcher 对主服务造成副作用
  • 应用进入“部分可用但静态页面不可用”的异常状态

影响

这个问题会导致:

  • 前端页面、后台界面看起来像“站点挂了”
  • 但简单健康检查仍然显示正常
  • 运维层面不容易第一时间发现真实故障

临时解决办法

当前临时处理方式是:

  • 重启 webchat2api 容器

重启后可立即恢复,但这只是临时 workaround,并不能解决根因。

Activity

github-actions commented on Jun 7, 2026

@github-actions

AI issue labeler summary (classification based on trusted dev branch evidence): Labels: none The issue could not be labeled automatically because AI analysis failed or returned an invalid response.

added
bugSomething is not working
performancePerformance or responsiveness issue
on Jun 7, 2026

zqbxdev commented on Jun 7, 2026

@zqbxdev
Owner

已做本地排查和一个低风险缓解修复,尚未 push。

结论

本地现有容器暂未复现该问题:

  • webchat2api-dev:/health、/version、/、/index.html 均快速返回;/_next/_index.txt 快速 404
  • webchat2api v0.0.11:同样未复现,/ 和 /index.html 均约 2ms 返回 200

因此该问题更像是偶发/状态型/环境相关问题,而不是当前本地容器稳定复现问题。

代码路径判断

/health 和 /version 是轻量 JSON 路由,不访问静态文件;而 / 和 /index.html 走 catch-all 静态路由并返回 FileResponse(index.html)。这能解释为什么健康检查正常但首页静态响应可能卡住。

本地修复

已在本地 dev 分支提交一个低风险缓解修复:

  • b09504c fix: cache frontend static asset lookup

主要变化:

  • 缓存 web_dist 基础路径
  • 缓存 index.html 路径
  • / 和 /index.html 避免每次重复执行同步文件系统解析/stat
  • SPA fallback 使用缓存后的 index
  • 保持 _next/... 缺失资源快速 404
  • 加入路径穿越防护测试

相关测试:

  • test/test_static_serving.py

验证

已通过:

python3 -m unittest test.test_static_serving
python3 -m py_compile api/support.py api/app.py test/test_static_serving.py

并构建独立临时镜像 webchat2api-issue28-test:local,启动临时容器绑定 8084:83 验证:

/health             200  ~0.002s
/version            200  ~0.002s
/                   200  ~0.030s
/index.html         200  ~0.003s
/_next/_index.txt   404  ~0.006s

临时容器已删除,未影响现有容器。

说明

由于本地没有复现超时,当前修复不能声称已经根治,只能作为针对最可疑静态文件路径的防御性缓解。后续如果线上再次出现,需要在故障时抓取:

  • Caddy access/error log
  • 容器内 curl http://127.0.0.1:83/ 与外部域名对比
  • Python 线程栈/进程状态
  • /app/web_dist/index.html stat/read 耗时

zqbxdev commented on Jun 7, 2026

@zqbxdev
Owner

补充一下:相关改动已经推到 dev 分支了。

提交:

  • b09504c fix: cache frontend static asset lookup
  • 1ed97f2 chore: update AI action model

前面那条评论里的“尚未 push”是当时本地验证阶段的状态,现在已更新。

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething is not workingneeds reproductionNeeds reproduction or verificationperformancePerformance or responsiveness issuepriority: highHigh priority

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions