terminationGracePeriodSeconds需按最慢事务耗时配置,如42秒则设50~60秒;preStop须提前摘流,主进程须显式处理SIGTERM并等待事务完成;需通过日志、监控、请求链路验证真正平滑退出。

要让高并发、大事务的容器体面退出,terminationGracePeriodSeconds不能只设个默认值,得结合业务实际耗时来配置——它本质是给“正在跑的大事务”留出安全收尾的时间窗口。
先摸清你最慢事务的真实耗时
别凭经验猜。查生产日志里耗时最长的请求(比如支付结算、批量导出、跨库同步),看从收到请求到完成写库/发消息/关连接的完整链路耗时。若最大值是42秒,那 grace period 至少设为 50~60 秒,留出缓冲。
- 用 Prometheus + duration_seconds_bucket 监控 P99.9 请求延迟
- 在应用日志中加 traceId 标记“start graceful shutdown”,对比最后一条业务日志时间戳与容器终止时间差
- 避免设成 30 秒这种通用值——对大事务来说,30 秒大概率不够,会触发 SIGKILL 强杀
配合 preStop 预热摘流,不等 terminationGracePeriodSeconds 才开始行动
优雅退出 ≠ 等着被杀。preStop 是主动控制的第一道闸门:它要在 SIGTERM 发出前,就让服务“对外不可用”,但“对内仍可处理完手头活”。
- 推荐做法:preStop 执行 curl -X POST http://localhost:8080/actuator/health/readiness?down=true(Spring Boot)或类似就绪探针降级接口
- 确保 readinessProbe 的 failureThreshold × periodSeconds ≤ 5 秒,让 endpoints controller 快速摘除实例
- preStop 里不要放耗时操作(如 sleep 10s),它只是“通知下线”,真正清理交给 SIGTERM 后的主逻辑
让容器进程真正响应 SIGTERM,而非忽略或立即退出
很多 Java/Node.js 应用默认不处理 SIGTERM,一收信号就直接 exit(0),大事务全丢。必须显式注册钩子:
- Java:用 Spring Boot 2.3+ 的
server.shutdown=graceful+spring.lifecycle.timeout-per-shutdown-phase=60s - Go:监听 os.Signal syscall.SIGTERM,调用 http.Server.Shutdown() 等待活跃连接关闭
- Node.js:process.on('SIGTERM', () => { server.close(); db.close(); })
- 关键检查点:容器日志里必须出现 “graceful shutdown started” 和 “all connections closed” 类似语句
验证是否真平滑,只看 Pod 状态没用
容器 ExitCode 0 不代表平滑;Pod 变 Terminating 也不代表流量已切走。必须观测真实请求流:
- 负载均衡器(如 ALB/Nginx)日志:下线窗口内不应出现 502/503 或 “Connection refused”
- 应用侧监控:确认最后一条请求完成时间早于容器终止时间(可用容器 terminationTimestamp 减去最后 log timestamp)
- 客户端重试日志:幂等接口可容忍短时重试,但非幂等操作(如下单)绝不能因下线失败而重复提交










