← All incidents

[Eval][v3][zh] Order service OOM crashloop following v3.7 deploy

service: order-svccreated: 6/2/2026, 11:55:04 PM

Raw incident context

Time: 09:15 UTC. order-svc pods entering CrashLoopBackOff with OOMKilled exit reason.

Kubernetes:
- Pods: 12 total, 3 currently OOMKilled, 9 running
- Memory limit: 512Mi, requests: 256Mi
- Recent restarts/hour: 18 (up from baseline of 0–1)
- HPA scaling has hit max replicas (12)

Memory trend (last 24h):
- Steady linear growth from 180Mi at 04:00 UTC to 500Mi at 09:00 UTC, then crash
- Pre-deploy baseline: stable at 200Mi indefinitely

Deploy history:
- 04:00 UTC — order-svc v3.7 deployed (rolling, 100% complete by 04:08)
- Changelog: "switched JSON parser to fast-json-stringify; added in-process request cache (Map-based, no eviction)"

Logs:
- No FATAL/ERROR pattern; pods exit silently
- Heap profile from one captured pod shows: ~340Mi held by Map keyed on request ID, never cleared

On-call:
- 09:12 — first OOMKilled pod
- 09:14 — pager
- 09:16 — service still serving most traffic via remaining pods; checkout success rate dipped from 99.7% → 96.8%

Summary

SEV1

order-svc 自 09:12 UTC 起出现 Pod OOMKilled 重启循环,p99 延迟升高,约 3% 请求超时。根因是 v3.7 部署引入的内存泄漏:一个基于 Map 的请求缓存未设置淘汰策略,导致内存线性增长直至 OOM。当前 12 个 Pod 中 3 个已 OOMKilled,HPA 已达最大副本数。

Severity reasoning: 用户可见的故障:结账成功率从 99.7% 降至 96.8%(>1% 错误率超过 5 分钟),且影响收入路径。符合 SEV1 定义。

deepseek-chat·prompt v3·output: zh·10458ms·2418↑ / 1564↓ tok·$0.00237

Root cause hypotheses

  • highv3.7 部署引入的请求缓存 Map 未设置淘汰策略,导致内存泄漏

    Evidence: 堆分析显示约 340Mi 内存被以请求 ID 为键的 Map 持有,且从未清理。部署后内存从 180Mi 线性增长至 500Mi 后 OOM。

  • lowfast-json-stringify 库存在内存泄漏

    Evidence: 无直接证据;堆分析未显示序列化相关对象异常增长。

  • low外部依赖(如数据库连接池)未正确释放资源

    Evidence: 日志无数据库相关错误,且内存增长模式与请求缓存一致。

Investigation checklist

  1. 确认内存泄漏源:检查堆中 Map 对象大小
    kubectl exec -n prod $(kubectl get pod -n prod -l app=order-svc -o jsonpath='{.items[0].metadata.name}') -- jcmd 1 GC.heap_dump /tmp/heap.hprof && kubectl cp -n prod $(kubectl get pod -n prod -l app=order-svc -o jsonpath='{.items[0].metadata.name}'):/tmp/heap.hprof ./heap.hprof

    Expected: heap.hprof 中显示大量 com.example.OrderCache 实例,每个持有请求 ID 字符串

  2. 验证缓存未设置淘汰策略:检查代码中 Map 声明
    kubectl exec -n prod $(kubectl get pod -n prod -l app=order-svc -o jsonpath='{.items[0].metadata.name}') -- cat /app/app.jar | strings | grep -i 'new HashMap'

    Expected: 输出显示无大小限制或淘汰策略的 HashMap 实例化

  3. 确认内存增长趋势与请求速率相关
    kubectl exec -n prod $(kubectl get pod -n prod -l app=order-svc -o jsonpath='{.items[0].metadata.name}') -- curl -s localhost:8080/metrics | grep -E 'http_requests_total|process_resident_memory_bytes'

    Expected: 内存使用量随请求总数线性增长

  4. 检查 HPA 是否已到上限
    kubectl get hpa -n prod order-svc-hpa

    Expected: 当前副本数 12/12,已达最大

Mitigation plan

  • 回滚 order-svc 至 v3.6(上一个稳定版本)

    Risk: 回滚期间服务短暂不可用(约 30 秒),但可恢复。

    Rollback: 再次执行 kubectl rollout undo deployment/order-svc -n prod 可回到 v3.7

  • 若回滚不可行,临时增加 Pod 内存限制至 1Gi 并重启所有 Pod

    Risk: 仅缓解症状,不解决泄漏;可能耗尽节点资源。

    Rollback: 将内存限制改回 512Mi 并重启 Pod

  • 在 v3.7 中为缓存添加 TTL 淘汰策略(如 5 分钟)并重新部署

    Risk: 代码修改需时间,且可能引入新 bug。

    Rollback: 回滚至 v3.6

Customer impact

部分用户在下单时遇到超时或错误,结账成功率从 99.7% 下降至 96.8%。影响持续约 15 分钟,预计回滚后恢复。

Postmortem draft

摘要

order-svc 因 v3.7 部署引入的内存泄漏导致 Pod OOM 重启,影响结账成功率。

时间线 (UTC)

  • 04:00 - v3.7 部署完成
  • 09:12 - 首个 Pod OOMKilled
  • 09:14 - 分页告警
  • 09:16 - 确认影响,开始调查
  • [FILL IN] - 回滚完成

影响

  • 结账成功率 99.7% → 96.8%
  • p99 延迟升高
  • 3 个 Pod OOMKilled

根因

v3.7 新增的请求缓存 Map 未设置淘汰策略,导致内存线性增长直至 OOM。

检测

告警延迟约 12 分钟(从部署到首次 OOM)。

响应

回滚至 v3.6 恢复。

做得好的

  • 快速定位到内存泄漏
  • 回滚流程顺利

做得不好的

  • 代码审查未发现缓存无淘汰策略
  • 无内存使用告警

行动项

  • [ ] 为缓存添加 TTL 淘汰
  • [ ] 设置内存使用率告警
  • [ ] 增加预发布环境内存压力测试

Follow-ups

  • P0为 order-svc 的请求缓存添加 TTL 淘汰策略,并设置最大条目数service owner
  • P1配置 Pod 内存使用率告警(>80% limit 持续 5 分钟)platform team
  • P1在预发布环境中增加内存泄漏检测(如 heap dump 对比)QA team
  • P2审查 v3.7 代码变更,确保无其他类似问题service owner