dy-dashboard/vault/知识库/工作指南/训练记录/2026-09-20-云端网页打不开排查与库存导出内存优化.md
2026-10-28 11:14:17 +08:00

87 lines
7.2 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# 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 自动备份的保留策略(当前会持续累积)、今天为何会连跑两次全量备份。