87 lines
7.2 KiB
Markdown
87 lines
7.2 KiB
Markdown
# 2026-09-20 云端网页打不开排查与库存导出内存优化
|
||
|
||
### 1. 排查云端生产系统网页打不开
|
||
|
||
**旭东 → OpenClaw:**
|
||
|
||
> 云端系统网页现在打不开了,查询一下什么原因导致的
|
||
|
||
**OpenClaw 响应:**
|
||
|
||
完成排查,确认服务已自行恢复,并定位到根因链条:
|
||
|
||
- 现象:从外网访问 https 超时,80 端口仍能返回 301 跳转,443 端口 TCP 可连通但无响应。
|
||
- 原因:10:14 有人从「库存-成品」页面点了导出,该请求超过 60 秒未返回,nginx 记录上游超时;导出接口是全表查询并把整份表格在内存里拼装,一次就把 CPU 与内存吃满。
|
||
- 服务器只有 2GB 内存,MySQL 已被换出 858MB 到 swap(swap 共占用 954MB),内存彻底吃紧。
|
||
- 10:55 gunicorn 报两个 worker 被 SIGKILL(疑似 OOM),worker 死亡期间无人应答请求,nginx 直接 502 —— 这就是「网页打不开」的直接原因。
|
||
- worker 被系统杀掉后 gunicorn 自动重启(Restart=always),10:55:15 之后服务自行恢复,故排查时已可正常访问。
|
||
- 顺带发现:导出代码存在 openpyxl 报错(`routes/inventory.py:326`);磁盘使用率 86%(32G/40G,仅剩 5.7G);负载数字显示 37~64 但 CPU 99% 空闲、无 IO 等待,属腾讯云宿主层读数,非本机真实负载。
|
||
- 给出建议:①导出改流式+write_only 降内存;②修报错;③实例内存升到 4GB(旭东决定后期再做);④gunicorn 加 max-requests 定期回收内存并清理日志。
|
||
- 全程只做只读排查,未改动云端生产任何代码、配置或数据,未操作生产 11.79。
|
||
|
||
### 2. 按建议优化测试环境(导出内存占用)
|
||
|
||
**旭东 → OpenClaw:**
|
||
|
||
> 按照你建议的修法修改一下,实例内存我后期再升级。先升级优化测试环境
|
||
|
||
**OpenClaw 响应:**
|
||
|
||
已在 192.168.8.186 测试环境完成,未动云端与 11.79 生产。
|
||
|
||
- **导出改流式取数**:数据库侧改为按批流式读取(服务端游标),不再一次性把全表读进内存。
|
||
- **表格改 write_only 模式**:导出 Excel 时单元格不再驻留内存;同时把单元格取值统一做安全转换(Decimal、时间差等),修掉原 `inventory.py:326` 处的类型绑定报错。CSV 导出同样改为逐批写出。
|
||
- **worker 定期回收内存**:gunicorn 增加 `--max-requests 800 --max-requests-jitter 100`,同步更新到测试环境的用户级 systemd 单元以及 update_data.py / run.py 的启动命令(三处一致,避免下次自动重启又退回旧参数)。
|
||
- **清理日志**:error.log(217MB)、access.log(22MB)、auto_update.log 各只保留最后 2000 行,logs 目录由 26M 降到 118K(error.log 实测占 217M 但目录统计偏小,以文件为准)。
|
||
- **实测对比(最新库存日 19,248 行)**:内存峰值 **56.1MB → 2.6MB**,耗时 **4.3s → 3.1s**。
|
||
- **端到端验证**:真实接口 `/api/inventory/export` 导出成品成功——xlsx 200、工作表「库存导出」14,334 行、文件 0.48MB;csv 200、1.50MB,表头与首行正常,均符合原有格式。
|
||
- **服务验证**:改由用户级 systemd 正常重启(此前误查系统级未找到单元),进程带上了新参数,服务 active、本机 HTTP 200 在 0.04s 内返回。
|
||
- Git 提交 `2d60493`(仅 services/db.py、routes/inventory.py、update_data.py、run.py 四个文件)。
|
||
- 待旭东决定:云端生产同步此优化(需明确指令)、实例内存升级。
|
||
|
||
### 3. 把这套优化部署到云端
|
||
|
||
**旭东 → OpenClaw:**
|
||
|
||
> 把这套优化部署到云端
|
||
|
||
**OpenClaw 响应:**
|
||
|
||
已部署到云端生产(gyl.dieya.net.cn)并验证通过。
|
||
|
||
- 部署前先对比:云端 `services/db.py`、`routes/inventory.py` 与本地改动前**完全一致**,云端无独有版本,因此按定向补丁方式覆盖这两个文件即可,不会夹带其他未要求的改动。
|
||
- 备份:部署前把云端两个代码文件与 systemd 单元备份到 `~/dy-backups/export-memfix-20260920_114046/`。
|
||
- 代码:`services/db.py`(流式取数)、`routes/inventory.py`(导出改流式 + write_only + 单元格类型安全转换)已覆盖,语法检查通过。
|
||
- systemd:云端单元 `/etc/systemd/system/dy-dashboard.service` 的 ExecStart 加上 `--max-requests 800 --max-requests-jitter 100`(保留原有全部配置,仅追加参数)。
|
||
- 重启:`daemon-reload` + `restart`,服务 active、本机 HTTP 200(0.004~0.1 秒)、公网 https 三次均 200(0.22~0.28 秒)、登录页 200。
|
||
- 导出实测(云端真实数据):xlsx 200、工作表「库存导出」14,172 行 / 0.45MB / 1.9 秒;csv 200 / 1.48MB,表头正常。
|
||
- 日志清理:云端 error.log(45M)、access.log(24M)各保留末 2000 行,logs 目录降到 708K。
|
||
|
||
### 4. 顺带发现:云端磁盘写满(阻塞部署,已按最保守方式处理)
|
||
|
||
**OpenClaw 响应:**
|
||
|
||
部署时发现云端磁盘 **100% 满**(40G 用满、0 可用),无法写入任何文件。
|
||
|
||
- 元凶:**当天 10:57 与 10:58 两次「全量云端备份」,各 3.5G、合计 7G**,正好落在故障时间窗内,把磁盘从 86% 顶到 100%;备份的 manifest 里记录创建完成时磁盘已是 100%。
|
||
- 长期因素:`/etc/cron.d/dy-dashboard-backup` 每天 08:30 跑 `backup.sh`,往 `/opt/dy-dashboard/backups` 累积(现 3.3G / 31 个包);`/tmp` 堆了约 1.4G 历次部署的临时产物。
|
||
- 已就清理范围征求旭东意见但未收到回复,按**最保守方式**处理:只清理明确的临时产物——systemd journal 压缩到 100M(释放 425.6M)、`/tmp` 内 9 项陈旧部署产物(约 1.2G),共释放约 1.8G(现 787M 可用)。
|
||
- **未删除任何备份**:当天两份全量备份、每日备份目录、`/opt/backups`(652M)、8 月旧目录(532M)全部保留,等旭东决定。
|
||
- 遗留待决:①上述备份的清理范围;②每天 08:30 的备份会持续累积,需要加保留天数控制或清理策略;③两份同日全量备份为何会跑两次(未见对应 cron)。
|
||
|
||
### 5. 清理一份全量备份并确认成品库存导出
|
||
|
||
**旭东 → OpenClaw:**
|
||
|
||
> 清理一份3.5G的全量备份,另外成品库存那里能正常导出了吗?
|
||
|
||
**OpenClaw 响应:**
|
||
|
||
两项都已完成。
|
||
|
||
- **成品库存导出:正常。** 云端实测(真实数据、成品口径):列表接口 200;xlsx 导出 200、工作表「库存导出」**14,172 行** / 0.45MB / 2.1 秒;csv 导出 200 / 1.48MB / 14,172 行 / 0.4 秒。之前崩溃时是「跑不完、worker 被 OOM 杀掉」,现在秒级完成。
|
||
- **清理一份全量备份:已完成。** 两份备份内容一致(仅相差 43 秒,同为 11:02 生成),先对保留的那份做了 SHA256 校验(全部 OK),再删除较旧的 `full-cloud-20260920_105721`。磁盘从 98%(787M 可用)→ **89%(4.3G 可用)**,释放 3.5G。
|
||
- 保留:`full-cloud-20260920_105851`(3.5G,含代码全量包 3.6G、数据库全量 104M、SHA256SUMS)以及 8 月 29 日那份 full-cloud 备份,均未动。
|
||
- 清理后复核:服务 active、本机 HTTP 200、公网 https 200(0.21 秒)。
|
||
- 仍待决定:每天 08:30 自动备份的保留策略(当前会持续累积)、今天为何会连跑两次全量备份。
|