docs: 移动蓝绿部署指南到 troubleshooting 目录

This commit is contained in:
Simon
2026-07-05 17:03:36 +08:00
parent ab90db3d3d
commit ca7c6d937a
91 changed files with 4841 additions and 406 deletions
@@ -212,7 +212,7 @@ curl https://<生产域名>/api/mfa/status
## 🟡 部署后 必做(用户/QA 验收)
`docs/E2E-CHECKLIST-v0.7.0.md` 35 项,逐项打勾。
`docs/06-测试质量/testing-测试/E2E-CHECKLIST-v0.7.0.md` 35 项,逐项打勾。
**关键项**:
- [ ] 浏览器扫码登录全流程(5 子项)
@@ -37,14 +37,14 @@ python scripts/jms_ops.py batch -f commands.txt
### 3. 文件上传
```bash
# 本地 → 堡垒机 → 目标服务器
# 通过 elFinder Web UI 上传到目标服务器
python scripts/jms_ops.py upload 本地文件.conf /tmp/远程路径.conf
```
### 4. 文件下载
```bash
# 目标服务器 → 堡垒机 → 本地
# 通过 base64 通道从目标服务器下载
python scripts/jms_ops.py download /远程路径.conf ./本地文件.conf
```
@@ -52,10 +52,11 @@ python scripts/jms_ops.py download /远程路径.conf ./本地文件.conf
| 需求 | 推荐方案 | 速度 |
|------|----------|------|
| 执行命令获取文本结果 | v16 REST API + plink PTY | ~15s |
| 执行命令获取文本结果 | v16 REST API + plink PTY | 首次 ~13s,复用 ~2-3s |
| 执行命令看界面效果 | v10 Web CLI(截图) | ~60s |
| 文件传 (<100KB) | upload/download | - |
| 文件传输 | elFinder Web UI | - |
| 文件传 (< 100KB) | base64 通道 | |
| 文件上传 (>= 100KB 或 > 15s) | elFinder Web UI | 稳定 |
| 文件下载 | base64 通道 | - |
## 目标服务器配置
@@ -0,0 +1,156 @@
# 智能IT支持服务台 - 问题修复记录
**日期**2026-07-05
**负责人**:宋献
**状态**:✅ 已完成
---
## 一、问题概述
### 1.1 当日问题汇总
| 序号 | 问题 | 影响范围 | 严重程度 | 状态 |
|------|------|---------|---------|------|
| #1 | 坐席端消息列表 500 错误 | 坐席端 | 🔴 高 | ✅ 已修复 |
| #2 | 页面短暂无法访问 | 全端 | 🟡 中 | ✅ 已自愈 |
| #3 | 坐席端消息发送失败 | 坐席端 | 🔴 高 | ✅ 已修复 |
| #4 | 文档缺失 wordfilter 依赖说明 | 文档 | 🟢 低 | ✅ 已补充 |
---
## 二、问题详情
### 2.1 #1 坐席端消息列表 500 错误
**发现时间**03:27
**问题现象**
- 坐席端报错:`获取消息列表失败: Error: 服务器内部错误,请稍后重试或联系管理员`
- WebSocket 连接失败:`wss://itsupport.servyou.com.cn/ws/sxn`
**根因分析**
- 后端日志:`TypeError: list_messages() got an unexpected keyword argument 'current_user'`
- 原因:`/api/conversations/{id}/messages` 端点使用了 `@require_permission` 装饰器,但函数签名缺少 `current_agent` 参数
**修复步骤**
1.`backend/app/api/messages.py``list_messages` 函数中添加参数:
```python
current_agent: Agent = Depends(get_current_agent),
```
2. 使用 sed 命令在容器中直接插入行:
```bash
sudo docker exec wecom_it_backend sed -i '63i\ current_agent: Agent = Depends(get_current_agent),' /app/app/api/messages.py
```
3. 重启后端容器:
```bash
sudo docker restart wecom_it_backend
```
**验证结果**
```bash
curl "https://itsupport.servyou.com.cn/api/conversations/xxx/messages" -H "Authorization: Bearer xxx"
# 返回 200 OK,消息列表正常
```
---
### 2.2 #2 页面短暂无法访问
**发现时间**10:29
**问题现象**
- 用户报告坐席端和员工端页面打不开
**根因分析**
- 可能是之前容器重启导致的服务波动
**修复步骤**
- 服务自动恢复(无需人工干预)
**验证结果**
- H5 端:`/itdesk/` → 200 OK
- 坐席端:`/itagent/` → 200 OK
- API`/api/health` → 200 OK
---
### 2.3 #3 坐席端消息发送失败
**发现时间**10:44
**问题现象**
- 坐席端发送消息失败:`{"code":1005,"message":"服务器内部错误,请稍后重试或联系管理员"}`
**根因分析**
- 后端日志:`ModuleNotFoundError: No module named 'wordfilter'`
- `content_moderation_service.py` (v0.6.0 内容审核功能) 依赖 `wordfilter` 库,但 `requirements.txt` 中未声明
**修复步骤**
1. 在 `backend/requirements.txt` 中添加依赖:
```
wordfilter==0.2.7
```
2. 在容器中手动安装(临时修复):
```bash
sudo docker exec wecom_it_backend pip install wordfilter
```
**验证结果**
```bash
curl -X POST "https://itsupport.servyou.com.cn/api/conversations/xxx/messages" \
-H "Authorization: Bearer xxx" \
-H "Content-Type: application/json" \
-d '{"content":"测试","msg_type":"text"}'
# 返回 {"code":0,"message":"success"}
```
---
### 2.4 #4 文档缺失 wordfilter 依赖说明
**发现时间**10:50
**问题现象**
- 部署文档中未说明 Python 依赖管理流程
- `requirements.txt` 未包含 `wordfilter` 依赖
**修复步骤**
1. 更新 `backend/requirements.txt`,添加 `wordfilter==0.2.7`
2. 更新 `docs/09-部署运维/deploy/服务器部署手册.md`,新增"六、Python 依赖管理"章节:
- 依赖说明
- 新增依赖处理流程
- 常见依赖问题及解决方法
**验证结果**
- ✅ requirements.txt 已更新
- ✅ 部署文档已补充
---
## 三、后续建议
1. **依赖管理流程化**
- 每次新增 Python 依赖,必须同步更新 `requirements.txt`
- 部署前确保依赖已包含在 requirements.txt 中
2. **监控告警**
- 建议配置后端错误监控(如 Sentry),及时发现生产环境异常
3. **文档同步**
- 重要修复完成后,同步更新相关文档
---
## 四、相关文件
| 文件 | 说明 |
|------|------|
| `backend/requirements.txt` | Python 依赖声明 |
| `backend/app/api/messages.py` | 消息 API |
| `backend/app/services/content_moderation_service.py` | 内容审核服务 |
| `docs/09-部署运维/deploy/服务器部署手册.md` | 部署手册 |
---
*最后更新:2026-07-05 10:52*
@@ -43,65 +43,63 @@
```
> **OpenSSH `ssh -J` 方式不再使用**(用户已确认用 PuTTY,2026-06-15)
# 登录成功后:
ssh sxn@10.90.5.110
```
### 2.3 配置 SSH 快捷方式(推荐)
### 2.3 jumpserver-ops 工具(推荐)
在开发机上编辑 `~/.ssh/config`,添加以下内容,以后只需要 `ssh itdesk` 即可:
推荐使用 jumpserver-ops 工具进行远程命令执行和文件传输。该工具自动化完成 JumpServer 登录、OTP 验证、资产连接等全流程。
```
# 堡垒机
Host bastion
HostName 10.212.189.210
Port 2222
User sxn
# 智能IT支持服务台服务器
Host itdesk
HostName 10.90.5.110
User sxn
ProxyJump bastion
```
> **堡垒机用户名为 `sxn`,已填入下方命令中**
之后只需:
```bash
ssh itdesk # 自动通过堡垒机跳转
scp file itdesk:/opt/ # 文件传输也会自动走堡垒机
# 进入 skill 目录
cd C:\Users\simon\.workbuddy\skills\jumpserver-ops\scripts
# 远程执行命令(首次登录约 13s,后续复用约 2-3s)
python jms_ops.py exec -c "hostname"
python jms_ops.py exec -c "uptime" -c "docker ps"
# 文件上传(自动选择最优方式:<100KB 用 base64>=100KB 或 >15s 用 elFinder
python jms_ops.py upload local_file.txt /tmp/remote_file.txt
# 文件下载(base64 通道)
python jms_ops.py download /tmp/server_file.txt ./local_file.txt
```
> **注意**:首次使用会弹出浏览器完成 JumpServer 登录和 OTP 验证,后续调用会自动复用会话(30分钟内有效)。
### 2.4 为什么不能直接用 SSH/SCP
| 方式 | 支持情况 | 原因 |
|------|---------|------|
| SSH ProxyJump | ❌ 不支持 | JumpServer 不兼容标准 SSH 代理协议 |
| SCP 直连堡垒机 | ❌ 不支持 | 需要 OTP 验证码,SCP 不支持交互式输入 |
| SSH 直连目标服务器 | ❌ 不支持 | 目标服务器仅对 JumpServer 开放 SSH 访问 |
| jumpserver-ops | ✅ 推荐 | 自动化处理 OTP 和 Connection Token |
---
## 三、文件传输(通过堡垒机)
### 3.1 SCP 传输(推荐小文件/单次传输
### 3.1 jumpserver-ops 上传(推荐
```bash
# 上传单个文件
scp -o "ProxyJump=sxn@10.212.189.210:2222" \
it-smart-desk-server-deploy.zip \
sxn@10.90.5.110:/opt/
# 上传文件到目标服务器 /tmp 目录
# 自动选择最优方式:<100KB 用 base64(快),>=100KB 或 >15s 用 elFinder(稳定)
python jms_ops.py upload deploy.zip /tmp/deploy.zip
# 如果已配置 ~/.ssh/config
scp it-smart-desk-server-deploy.zip itdesk:/opt/
# 上传到其他目录
python jms_ops.py upload config.conf /opt/wecom-it-desk/config.conf
```
### 3.2 大文件传输优化
### 3.2 备用方案
部署包可能较大(含后端源码 + 前端产物),如果 SCP 速度慢,可以先传到堡垒机再转
如果 jumpserver-ops 不可用,可以考虑
```bash
# 步骤1:传到堡垒机
scp -P 2222 it-smart-desk-server-deploy.zip sxn@10.212.189.210:/tmp/
# 方式A:通过互联网可访问的存储服务(推荐)
# - 先把文件传到能通过互联网访问的存储(如:对象存储、临时文件分享服务)
# - 目标服务器通过 curl/wget 下载
# 步骤2SSH 到堡垒机
ssh -p 2222 sxn@10.212.189.210
# 步骤3:从堡垒机传到目标服务器
scp /tmp/it-smart-desk-server-deploy.zip sxn@10.90.5.110:/opt/
# 方式B:通过堡垒机手动中转
# - 使用 jumpserver-ops 手动执行分步操作
```
---
@@ -276,28 +274,86 @@ DNS 生效后(或配置了本地 hosts),在浏览器中访问:
## 五、部署文件结构
### 5.1 服务器目录结构
```
/opt/wecom-it-desk/
├── docker-compose.yml # Docker Compose 配置(4容器)
├── .env # 环境变量(已配置)
├── .env.example # 环境变量模板
├── deploy.sh # 一键部署脚本
├── README.md # 本手册
/opt/wecom-it-desk/ # 项目根目录(服务器)
├── docker-compose.yml # Docker Compose 配置(4容器)
├── .env # 环境变量(已配置)
├── .env.example # 环境变量模板
├── deploy.sh # 一键部署脚本
├── nginx/
── nginx.conf # Nginx 配置(反代 + 静态文件)
├── backend/
│ ├── Dockerfile # 后端镜像构建文件
│ ├── requirements.txt # Python 依赖
── app/ # 后端源代码
├── frontend-h5/
│ └── dist/ # H5 员工端构建产物
└── frontend-agent/
└── dist/ # 坐席工作台构建产物
── nginx.conf # Nginx 配置(反代 + 静态文件)
│ └── ssl/ # SSL 证书
├── html/ # 前端静态文件(Nginx 挂载点)
│ ├── itdesk/ # H5 员工端 (/itdesk/)
── itagent/ # 坐席工作台 (/itagent/)
│ ├── itadmin/ # 管理后台 (/itadmin/)
│ └── itportal/ # 统一入口 (/itportal/)
└── backend/ # 后端源码(不用于生产,仅开发参考)
```
### 5.2 前端部署位置说明
| 端 | URL 路径 | 服务器目录 | Nginx 容器挂载点 |
|----|---------|-----------|----------------|
| 员工端 H5 | `/itdesk/` | `/opt/wecom-it-desk/html/itdesk/` | `/usr/share/nginx/html/itdesk` |
| 坐席工作台 | `/itagent/` | `/opt/wecom-it-desk/html/itagent/` | `/usr/share/nginx/html/itagent` |
| 管理后台 | `/itadmin/` | `/opt/wecom-it-desk/html/itadmin/` | `/usr/share/nginx/html/itadmin` |
| 统一入口 | `/itportal/` | `/opt/wecom-it-desk/html/itportal/` | `/usr/share/nginx/html/itportal` |
### 5.3 前端部署步骤
```bash
# 1. 本地构建
cd frontend-agent
npm run build
# 2. 打包(排除 node_modules
cd dist
zip -r ../agent-v1.x.zip *
# 3. 上传到服务器 /tmp/
# 4. SSH 到服务器解压
sudo rm -rf /opt/wecom-it-desk/html/itagent
sudo mkdir -p /opt/wecom-it-desk/html/itagent
sudo unzip -o /tmp/agent-v1.x.zip -d /opt/wecom-it-desk/html/itagent
# 5. 重启 Nginx 容器
docker restart wecom_it_nginx
```
---
## 六、常用运维命令
## 六、Python 依赖管理
### 6.1 依赖说明
后端 Python 依赖在 `backend/requirements.txt` 中声明,构建 Docker 镜像时会自动安装。
**新增依赖处理流程:**
1. **开发环境**:更新 `backend/requirements.txt`
2. **打包部署**:确保 `requirements.txt` 已包含新依赖
3. **生产环境**:重建后端镜像
```bash
# 重建后端镜像(会自动安装 requirements.txt 中的所有依赖)
cd /opt/wecom-it-desk
docker compose build backend
docker compose up -d backend
```
### 6.2 常见依赖问题
| 问题 | 症状 | 解决方法 |
|------|------|---------|
| 缺少依赖 | `ModuleNotFoundError` | 重建后端镜像:`docker compose build backend` |
| 手动安装 | 容器内临时安装 | `docker exec wecom_it_backend pip install <package>` |
---
## 七、常用运维命令
在服务器上 `/opt/wecom-it-desk` 目录下执行:
@@ -318,7 +374,7 @@ DNS 生效后(或配置了本地 hosts),在浏览器中访问:
---
## 、升级前端
## 、升级前端
当有新的前端版本需要部署时:
@@ -344,7 +400,7 @@ docker exec wecom_it_nginx nginx -s reload
---
## 、升级后端
## 、升级后端
```bash
# 1. 上传新代码到服务器
@@ -360,7 +416,7 @@ cd /opt/wecom-it-desk
---
## 、故障排查
## 、故障排查
### 后端容器一直重启
@@ -427,7 +483,7 @@ curl -X POST http://localhost/api/h5/mock-login \
---
## 十、HTTPS 配置(可选)
## 十、HTTPS 配置(可选)
如果公司要求 HTTPS,有两种方式:
@@ -445,7 +501,7 @@ curl -X POST http://localhost/api/h5/mock-login \
---
## 十、部署说明
## 十、部署说明
> ⚠️ NAS部署方案(itdesk.amanzac.com)已于2026年6月15日下线,现统一使用公司内网服务器部署。
@@ -461,7 +517,7 @@ curl -X POST http://localhost/api/h5/mock-login \
---
## 十、相关文档
## 十、相关文档
| 文档 | 说明 |
|------|------|
@@ -0,0 +1,120 @@
# 502 Bad Gateway - 后端启动失败
> 日期:2026-07-05
> 问题:坐席端登录失败,返回 502 Bad Gateway
---
## 一、问题现象
用户访问 `https://itsupport.servyou.com.cn/itagent/` 时提示登录失败:
```
Failed to load resource: the server responded with a status of 502 (Bad Gateway)
AxiosError: Request failed with status code 502
```
---
## 二、诊断过程
### 2.1 检查容器状态
```bash
docker ps -a
```
发现后端容器状态为 `unhealthy`
```
CONTAINER ID IMAGE STATUS
656f7696d4e5 wecom-it-desk-backend:latest Up 8 minutes (unhealthy)
```
### 2.2 检查后端日志
```bash
docker logs 656f7696d4e5 --tail 30
```
发现错误:
```
ModuleNotFoundError: No module named 'aioredis'
```
### 2.3 原因分析
- 旧版镜像中代码使用 `import aioredis`
-`aioredis` 包与 Python 3.12 不兼容
- 报错:`TypeError: duplicate base class TimeoutError`
---
## 三、解决方案
### 3.1 尝试修复(失败)
尝试在容器内安装 `aioredis` 包,但发现:
- `aioredis` 与 Python 3.12 不兼容
- 安装后仍报错:`TypeError: duplicate base class TimeoutError`
### 3.2 最终方案
删除旧容器,使用正确的环境变量重新启动:
```bash
# 1. 删除旧容器
docker stop 656f7696d4e5
docker rm 656f7696d4e5
# 2. 使用正确的 PYTHONPATH 重新启动
cd /opt/wecom-it-desk
PYTHONPATH=/app docker compose up -d backend
```
关键点:**必须设置 `PYTHONPATH=/app`**,否则会报错 `ModuleNotFoundError: No module named 'app.core'`
---
## 四、验证结果
```bash
# 检查容器状态
docker ps
# 输出:
# 2ec80dee024c wecom-it-desk-backend:latest Up 5 minutes (healthy)
# e147524342fa redis:7-alpine Up 11 hours (healthy)
# 8a2265864f34 nginx:1.27-alpine Up 11 hours
# 433ef922c8d8 postgres:16-alpine Up 11 hours (healthy)
# 测试 API
curl http://localhost:8000/health
# 输出:{"status":"ok"}
# 测试页面
curl -sk https://localhost/itdesk/
# 输出:HTML 页面正常返回
```
---
## 五、根因总结
| 问题 | 原因 |
|------|------|
| 后端容器 unhealthy | 旧镜像使用 `import aioredis`,与 Python 3.12 不兼容 |
| 启动失败 | 需要设置 `PYTHONPATH=/app` 环境变量 |
---
## 六、预防措施
1. **更新镜像**:在 Dockerfile 中将所有 `import aioredis` 改为 `import redis.asyncio as aioredis`
2. **环境变量**:确保 docker-compose.yml 中设置 `PYTHONPATH=/app`
3. **健康检查**:定期检查容器健康状态
---
## 七、相关文件
- 部署配置:`/opt/wecom-it-desk/docker-compose.yml`
- Nginx 配置:`/opt/wecom-it-desk/nginx/nginx.conf`
- 后端代码:`/opt/wecom-it-desk/backend/`
@@ -0,0 +1,136 @@
# 蓝绿部署指南
## 概述
蓝绿部署是一种零停机部署策略,通过维护两套完全相同的运行环境(Blue 和 Green),实现快速切换和回滚。
## 架构
```
┌─────────────────┐
│ Nginx │
│ (流量入口) │
└────────┬────────┘
┌──────────────┴──────────────┐
│ │
▼ ▼
┌────────────────┐ ┌────────────────┐
│ Blue 环境 │ │ Green 环境 │
│ (当前活动) │ │ (待验证) │
│ backend:8000 │ │ backend_green: │
│ │ │ 5002 │
└────────────────┘ └────────────────┘
│ │
└──────────────┬──────────────┘
┌──────────────┴──────────────┐
│ │
▼ ▼
┌────────────────┐ ┌────────────────┐
│ PostgreSQL │ ←──→ │ Redis │
│ (共享) │ │ (共享) │
└────────────────┘ └────────────────┘
```
## 文件说明
| 文件 | 位置 | 说明 |
|------|------|------|
| docker-compose-green.yml | /opt/wecom-it-desk/ | Green 环境配置 |
| switch-blue-green.sh | /opt/wecom-it-desk/ | 切换脚本 |
| nginx.conf | /opt/wecom-it-desk/nginx/ | Nginx 配置(包含 upstream |
## 部署步骤
### 1. 部署 Green 环境
```bash
cd /opt/wecom-it-desk
# 构建并启动 Green 环境
docker-compose -f docker-compose-green.yml up -d
# 验证 Green 环境健康
curl http://localhost:5002/health
```
### 2. 测试 Green 环境
通过端口 5080 访问 Green 环境进行测试:
- H5: http://服务器IP:5080/itdesk/
- 坐席: http://服务器IP:5080/itagent/
- 管理后台: http://服务器IP:5080/itadmin/
### 3. 切换流量到 Green
```bash
# 方法一:使用切换脚本
./switch-blue-green.sh to-green
# 方法二:手动修改 Nginx 配置
sed -i 's/wecom_it_backend:8000/wecom_it_backend_green:8000/' /opt/wecom-it-desk/nginx/nginx.conf
docker restart wecom_it_nginx
```
### 4. 验证切换
```bash
# 检查 Nginx upstream 配置
grep -A1 'upstream backend_api' /opt/wecom-it-desk/nginx/nginx.conf
# 测试 API
curl https://itsupport.servyou.com.cn/api/v1/system/health
```
### 5. 回滚(如有问题)
```bash
# 方法一:使用切换脚本
./switch-blue-green.sh to-blue
# 方法二:手动修改
sed -i 's/wecom_it_backend_green:8000/wecom_it_backend:8000/' /opt/wecom-it-desk/nginx/nginx.conf
docker restart wecom_it_nginx
```
## 端口说明
| 端口 | 服务 | 说明 |
|------|------|------|
| 80/443 | Nginx (Blue) | 生产入口 |
| 5002 | Backend (Green) | Green 后端 API |
| 5080 | Nginx (Green) | Green 测试入口 |
| 5443 | Nginx (Green) | Green HTTPS |
## 注意事项
1. **数据库共享**Blue 和 Green 共用同一个 PostgreSQL 和 Redis
2. **文件上传**:上传的文件保存在挂载目录,不受切换影响
3. **会话影响**:切换后用户可能需要重新登录
4. **WebSocket**:切换后现有 WebSocket 连接会断开
## 快速命令汇总
```bash
# 查看状态
docker ps
# 查看 Green 日志
docker logs wecom_it_backend_green
# 切换到 Green
sed -i 's/wecom_it_backend:8000/wecom_it_backend_green:8000/' /opt/wecom-it-desk/nginx/nginx.conf
docker restart wecom_it_nginx
# 切换回 Blue
sed -i 's/wecom_it_backend_green:8000/wecom_it_backend:8000/' /opt/wecom-it-desk/nginx/nginx.conf
docker restart wecom_it_nginx
# 停止 Green 环境
docker-compose -f docker-compose-green.yml down
```
## 更新日志
- 2026-07-05: 初始版本