13 KiB
00 · 标准故障排查手册
版本: v1.0 | 日期: 2026-07-07 | 维护人: 宋献 / 助理 定位: 所有故障排查前首先查看本手册。本手册整合了原先散落的快速诊断、服务器端诊断、故障排查指南、4 份修复记录、通讯链路诊断、deploy/02 手册、调试验证指南。 前置阅读: 运维手册(部署/回滚/备份/应急) · SOP-04 应急响应
0 文档说明与版本
0.1 为什么要有这本手册
原先"故障排查"主题散落在 9 份文档中(500 诊断、服务器端诊断、故障排查指南、4 份修复记录、通讯链路、deploy/02 手册、调试验证指南),内容重复且存在断链。任何故障都应先翻这一本,按决策树定位,再查案例库。
0.2 ⛔ 验证完成硬规则(最重要)
宣布"已修复 / 已完成"之前,必须提供真实可验证证据,不得仅凭 curl / 日志 / "我认为":
- 前端 / 登录类问题:真实浏览器登录或操作截图(用真实 Chromium / Playwright 打开页面、输入凭据、完成动作、进入目标页的截图)。
- API / 后端类问题:端到端调用证据(curl 真实返回 + 必要时代码层拦截响应体)。
- 禁止:只因
docker logs无报错就断言修复;只因"我认为应该好了"就宣布完成。
0.3 版本历史
| 版本 | 日期 | 变更 |
|---|---|---|
| v1.0 | 2026-07-07 | 整合 9 份散落文档 + 新增 CASE-20260707-01(Redis urlparse 挂起) |
1 快速诊断决策树
1.1 三步隔离法(通用)
任何"页面打不开 / 网络连接失败 / 接口无响应 / 422"都先用三步隔离,定位是 nginx、后端、还是依赖(DB / Redis)的问题:
# 第1步:nginx 层可达性(在服务器执行;浏览器走 HTTPS,故用 https 而非 localhost)
curl -ksI https://itsupport.servyou.com.cn/itadmin/ | head -5
curl -ksI https://itsupport.servyou.com.cn/api/health | head -5
# 第2步:直连后端(绕过 nginx,确认后端本身)
docker compose exec backend curl -s http://localhost:8000/health
# 或容器外:
docker exec wecom_it_backend curl localhost:8000/health
# 第3步:依赖可达性
docker compose exec redis redis-cli ping # 期望 PONG
docker compose exec postgres pg_isready -U wecom # 期望 accepting
判定矩阵:
| 现象 | 第1步 | 第2步 | 第3步 | 定位 |
|---|---|---|---|---|
| 浏览器"网络连接失败"、curl 永远不返回 | ✅200 | ✅200 | ❌挂起 | 依赖挂起(如 Redis 连到错误 host) |
| 全站 500 | ❌500 | ✅/❌ | — | 后端异常,看 backend 日志 |
| 某端点 502 | ❌502 | ❌后端 down | — | 后端未起 / 缺 PYTHONPATH=/app |
| /itdesk/ 200 但 /api/... 404 | ✅ | — | — | nginx 代理路径不匹配 |
| 422 | ✅ | API 校验失败 | — | 请求体缺字段(见 §2) |
1.2 关键陷阱:URL 特殊字符导致依赖"静默挂起"
详见案例 CASE-20260707-01。密码含 @ # 时,urlparse 把它们当 URL 分隔符,连到不存在的 host,连接无限挂起(浏览器表现为"网络连接失败",curl 永远等不到返回)。这是最隐蔽的一类故障——容器全 Up、nginx 全 200、唯独业务接口卡死。
1.3 在服务器跑诊断的 3 种方式(经堡垒机)
公司服务器只能经堡垒机(sxn@10.212.189.210:2222 → ssh sxn@10.90.5.110)操作,无法本地 scp。推荐用 jumpserver-ops 工具自动执行:
# 本地(Windows)用 jumpserver-ops 跑(自动复用会话,~2-3s/条):
python jms_ops.py exec -c "docker compose ps" -c "curl -ksI https://itsupport.servyou.com.cn/api/health" --reuse
原"服务器端跑诊断"的 3 种手工方式(PuTTY 跳堡垒机 / scp 上传 / 服务器下载)已不推荐,统一用上述 jumpserver-ops 自动化。
2 常见错误码速查(E5xx)
| 错误码 | 含义 | 首选排查 |
|---|---|---|
| E500 | 后端未捕获异常 / 缺列 / 缺依赖 | docker compose logs backend --tail=200 | grep -i error;查数据库缺列 / 缺 Python 依赖 |
| E502 | nginx 连不到后端 | 后端容器 unhealthy?docker logs wecom_it_backend;是否缺 PYTHONPATH=/app |
| E503 | 服务过载 / 维护 | docker stats;docker inspect ... Health |
| E403 | IP 白名单 / 无权限 | grep allow /opt/wecom-it-desk/nginx/nginx.conf;admin 角色不足 |
| E422 | 请求体校验失败(Pydantic) | 确认必填字段齐全(如登录需 user_id+name) |
| 网络失败 / 连接挂起 | 依赖不可达(最常见 Redis 配置错) | 见 §1.2 / CASE-20260707-01 |
2.1 E500 常见根因速查
- 数据库缺列 →
ALTER TABLE ... ADD COLUMN IF NOT EXISTS ... - 缺 Python 依赖 →
requirements.txt补依赖后重构建(如wordfilter) - 代码签名不匹配(如缺
current_agent参数)→ 修函数签名 import aioredis与 Python 3.12 冲突 → 改redis.asyncio,设PYTHONPATH=/app
2.2 E422 登录场景
登录端点 /api/agents/login 要求 user_id(必填) + name(必填);缺字段直接 422。前端 admin.ts 用 name: inputUserId 发送。
3 诊断脚本与命令
3.1 一键系统状态
#!/bin/bash
echo "==== 容器状态 ===="; docker compose ps
echo "==== 端口 ===="; netstat -tlnp | grep -E "80|443|5432|6379|8000"
echo "==== 前端文件 ===="; ls -la /opt/wecom-it-desk/html/itdesk/ 2>/dev/null | head
echo "==== backend 错误 ===="; docker compose logs --tail=20 backend 2>&1 | grep -i error
echo "==== Redis ===="; docker compose exec redis redis-cli ping
echo "==== PG ===="; docker compose exec postgres pg_isready -U wecom
3.2 500 错误快速对照
| 现象 | 诊断 |
|---|---|
ls .../frontend-h5/dist/ No such file |
部署包未含 dist |
nginx 容器内 ls /usr/share/nginx/html/itdesk/ 失败 |
挂载路径错 |
| curl /itdesk/ 返回 500 | 后端代理或 SPA 内部错 |
| /itportal/ 200 但 /itdesk/ 500 | H5 端特定问题 |
nginx 日志有 proxy_pass 错 |
后端未起 / 端口不通 |
nginx 日志 rewrite ... cycle |
try_files 死循环,修 nginx 配置 |
3.3 通讯链路检查点(用户 ↔ 坐席 ↔ 企微)
- 用户→系统:企微回调
/wecom/callback→message_router→ 消息入库 → 坐席 WS / 轮询 - 系统→用户:坐席 POST
/conversations/{id}/messages→wecom_service.send_text_message()(errcode=0)→ 用户收到 - 已知风险:非文本消息(图片/文件)不推送;
dev_mode跳过企微推送;企微 API 失败静默(仅日志) - 检查点文件:
wecom_callback.py/message_router.py/messages.py/wecom_service.py/ws_manager.py
3.4 WebSocket 失败
grep -r 'websocket' /opt/wecom-it-desk/nginx/nginx.conf # 需 proxy_http_version 1.1 + Upgrade/Connection
docker logs wecom_it_backend | grep -i websocket
4 案例库(倒序,编号 CASE-YYYYMMDD-序号)
CASE-20260707-01 · 管理后台登录"网络连接失败"(Redis 密码 URL 解析挂起)⭐
- 现象:浏览器登录
/itadmin/一直转圈 / "网络连接失败";API 永远不返回;curl 超时。 - 根因:
REDIS_URL=redis://:R3d!s@2026#Secure@redis:6379/0,密码含@和#。urlparse()把#当 fragment、@当 host 分隔符 → 解析出 host=2026、password=R3d!s→ 连到不存在的 host → 无限挂起。后端token_service.create_token()调redis.setex时卡死。 - 修复:
docker-compose.yml后端REDIS_URL改为 URL-encoded:redis://:R3d%21s%402026%23Secure@redis:6379/0backend/app/config.py的create_redis_client增加unquote()解码 +socket_connect_timeout=5/socket_timeout=5- redis 服务
--requirepass与 healthcheck 保持明文R3d!s@2026#Secure(与后端解码后的明文一致) - 重建 backend + redis 容器
- 验证:Redis
PING→PONG;curl登录/api/agents/login返回HTTP 200, 0.64s, role:admin;真实浏览器登录截图进入 dashboard 成功(见 §5)。 - ⚠️ 同类复发防护:本项目 Redis 密码含特殊字符,改 docker-compose 密码时两处必须一致(后端
REDIS_URL用 encoded,redis--requirepass用明文);且config.py必须unquote。
CASE-20260705-01 · 502 Bad Gateway(后端启动失败 / aioredis + PYTHONPATH)
- 现象:坐席端登录失败
502,后端容器unhealthy。 - 根因:旧镜像
import aioredis与 Python 3.12 冲突(TypeError: duplicate base class TimeoutError);且未设PYTHONPATH=/app致ModuleNotFoundError: No module named 'app.core'。 - 修复:Dockerfile 改
import redis.asyncio as aioredis;docker-compose.yml设PYTHONPATH=/app;重建后端。
CASE-20260705-02 · 坐席端 4 个问题(消息列表 500 / 页面抖动 / 发送失败 / 文档缺失)
- #1 消息列表 500:
list_messages()缺current_agent: Agent = Depends(get_current_agent)参数。修messages.py+ 重启。 - #2 页面短暂不可用:容器重启波动,自愈。
- #3 发送失败
ModuleNotFoundError: wordfilter:requirements.txt缺wordfilter==0.2.7,容器内pip install临时修 + 同步 requirements。 - #4 文档补"Python 依赖管理"章节(服务器部署手册)。
CASE-20260613-01 · H5 消息 500(缺列 + AIHandler 签名)
- 现象:
POST /api/h5/.../messages500:column conversations.impact_scope does not exist+AIHandler.__init__() missing 'ai_service'。 - 根因:DB 缺 4 列(
impact_scope/is_blocking/emotion_state/dify_conversation_id);dependencies.py两处AIHandler()未传ai_service。 - 修复:
ALTER TABLE补列;dependencies.py改AIHandler(ai_service=AIService())。
附:企微工作台"加载失败 / 无限加载"(2026-07-04)
- 根因1:nginx 未正确挂载
nginx.conf→ API 404,重建 nginx 容器。 - 根因2:后端
h5.py存在NameError: _require_wework_ua→ 代码未同步最新,复制最新h5.py+ 重启。
5 端到端验证完成标准(原《调试验证指南》整合)
宣布完成前,按 §0.2 提供真实证据。
5.1 管理后台验证(最常见)
| 步骤 | 操作 | 预期 |
|---|---|---|
| 1 | 浏览器开 https://itsupport.servyou.com.cn/itadmin/ |
登录页 |
| 2 | 输入 sxn / test123 登录 |
进入 dashboard,右上角显示"宋" |
| 3 | 仪表盘数据渲染 | 在线坐席 / 今日会话 / 平均响应 / AI 命中率 有值 |
| 4 | API 拦截 POST /api/agents/login |
HTTP 200 + role:admin + token |
5.2 通用验证清单(P0 必须通过)
- H5 登录流程正常(企微 OAuth 跳转 → 回跳 → 欢迎)
- 坐席登录正常,可接单
- 消息收发双向正常(文本 / 图片 / 文件)
- 邀请功能闭环
- 管理后台可访问且数据正常
5.3 真实浏览器证据获取(推荐 Playwright)
本机 Windows 可直接访问服务器(TCP 443 通)。用 playwright-core 驱动已安装的 Chromium(路径 ~/.agent-browser/browsers/chrome-*/chrome.exe),拦截 API 响应作为证据,避免 CLI 工具 IPC 不稳。
6 升级与应急(交叉引用,不重复)
- 回滚方案 → 见 运维手册·第六章
- 备份恢复 → 见 运维手册·第七章
- 应急响应(P0/P1 分级、止血、通知) → 见 SOP-04 应急响应
- 本手册只负责"定位 + 修复",变更管理与事故流程以上述文档为准。
7 参考文档索引
| 文档 | 说明 |
|---|---|
01-项目总览/01-智能IT服务系统运维手册-20260704.md |
部署 / 回滚 / 备份 / 应急(故障排查章已并入本手册) |
10-项目管理/SOPs-标准流程/SOP-04-应急响应.md |
应急响应 SOP |
09-部署运维/deploy/01-部署指南.md |
部署操作 |
09-部署运维/deploy/03-版本记录.md |
版本与修复记录索引 |
09-部署运维/deploy/服务器部署手册.md |
服务器部署细节 |
06-测试质量/testing-测试/E2E-CHECKLIST-v0.7.0.md |
E2E 验收清单 |
维护说明: 本手册为故障排查唯一入口。新增案例请按
CASE-YYYYMMDD-序号倒序追加到 §4;改动需同步本文件版本号与日期。