K8s 滚动更新时每个 Pod 都卡满 terminationGracePeriodSeconds 才结束,日志最后一行是收到 SIGTERM,之后再没有输出。发布一轮多花四分钟。乍看像缓存或者权限的锅,追下去往往不是。
process.on('SIGTERM', () => {
server.close(() => process.exit(0));
setTimeout(() => process.exit(1), 10000).unref();
});
追下去是这么回事:进程收到 SIGTERM 后没有注册处理函数,Node 直接退出,正在处理的请求被掐断,socket 也没有主动关闭。编排系统只能等到宽限期结束再补一个 SIGKILL。
「SIGTERM 优雅退出」相关的验证我通常做两遍,改完一次、隔天再看一次,确认不是临时生效。验证用真实数据走一遍,测试数据太干净,边界情况根本碰不到。
能分两步做的操作就别合成一步,中间看一眼返回值,出问题好判断。报错里带路径的,先去看那个路径在不在、权限对不对。
同一份配置存在多处的,先确认改的是被加载的那一份。
具体做法是,监听 SIGTERM 停止接收新连接;等 server.close 的回调 确认在途请求跑完;给排空加一个超时 到点强制退出;先把 readiness 置为失败 让流量提前摘走。
验收就看一点,发布时 Pod 终止耗时从 30 秒降到 2 秒 日志里能看到请求处理完的收尾记录。
