fix(生产): 主进程堆上限 4G→8G —— 每 4 小时崩一次,三天没跑成过一次全量 plans
【症状】容器 exitCode=139 自动重启,08-23~08-26 共 **11 次**,间隔约 4 小时。
页面无感(自动重启 + health 200),所以一直没人发现。
【根因】每轮增量同步结束会在**主进程内**跑一次 runAllForHost 全量召回。补摄把患者
灌到 111 万、召回池 54 万之后,selectHits 一次出 **96 万条命中**,连同 prefetch 的
latest/snoozed/persona 全在堆里 —— 而主进程启动命令
`node --enable-source-maps dist/main.js` **没带 max-old-space-size**,
取 Node 默认 **4144 MB**,装不下:
Mark-Compact 3985.6 → 3953.5 MB (mu = 0.008) ← GC 已经回收不动
FATAL ERROR: Reached heap limit — JavaScript heap out of memory
【代价】那三天 `Result(ruier-grp)` 在日志里出现 **0 次** —— 一次完整的全量 plans
都没跑成过。每轮崩在 selectHits 之后、写库之前:
✔ 增量导入成功落库 ✔ persona 重算成功落库 ✖ plans 整轮作废
数据不丢,丢的是"召回池的定时刷新"。另外每次崩溃留一个僵尸 sync 锁(重启后被回收),
且会带走同容器里正在跑的 docker exec —— bj04 第一次尝试就是这么死的(白跑 1h27m,
靠 batch.sh 的 3 次重试救回)。
【为什么现在才发现】补摄期间增量被 sync 并发锁挡下(00:15/08:15/10:15 全是 skip),
不跑全量 plans 就不崩 —— 实测连续 12 小时零崩溃。补摄一停,下一轮就会再崩。
⚠ ️ 排查时别往"容器内存不够"上找:容器**没有内存上限**(HostConfig.Memory=0),
宿主 15.36G 一直有 7-11G 空闲。撑爆的是 V8 自己的堆,与宿主余量无关。
⚠ ️ 同一容器里 CLI 那条路(cold-import / recompute-plans)一直是 8192,
**两条路配置不一致**,崩的一直是没配的这条。这次补齐。
⚠ ️ 宿主内存账写进注释了:8G(服务) + 8G(CLI) = 16G > 15.36G。实测两者不会同时顶到
上限(max-old-space 是天花板不是预留;实测峰值 服务 4G / CLI 4.9G),但
⛔ 别手工并发跑全量 `recompute-plans`(它不走 sync 锁)。
⚠ ️ **这是止血不是根治**:池子还在涨,8G 迟早也会到顶。根治是「增量之后别跑全量」——
recompute-plans 已经有 --clinics 收窄能力,同样的思路搬到
SyncIncrementalSchedulerService 那一处即可。另开分支做。
改动只有一行环境变量(docker-compose.prod.yml 的 pac-service),不动代码不动数据。
YAML 已校验;managed overlay 只合并 DATABASE_URL/REDIS_URL(非 !override),不影响本项。
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Showing
Please
register
or
sign in
to comment