process.on('SIGTERM', async () => {
  await redis.quit();
  server.close(() => process.exit(0));
});

开发环境每保存一次代码就新建一个 Redis 连接,跑两小时 Redis 的 client list 里有 200 多个连接。nodemon 显示重启成功,业务日志没有报错。先别急着动参数,把报错原文和时间点记下来,顺序反了容易白折腾。

原因不复杂,nodemon 杀掉的是子进程,挂在 global 上的句柄和定时器不一定跟着结束。模块重新加载会再执行一遍注册逻辑,旧的那份还活着。

「热重启全局变量残留」排查到最后往往是很小的一处差异,前面那些复杂猜测可以先放一放。改完隔一天再看一次,当场正常不代表能稳住。

测试环境和线上的差别,往往就在版本号和那几行被忽略的配置上。线上出问题先对时间点,跟发布、备份、任务执行的时刻排一排,能省掉一半功夫。

处理上按这个顺序:连接和定时器挂在模块作用域 不要挂 global;在 SIGTERM 和 beforeExit 里逐个 close;开发环境的监听用 once 避免重复注册;用 process._getActiveHandles 看还有哪些句柄没关。

改完只确认一件事:连续保存二十次 client list 里的连接数稳定在一个 不再随重启次数增长。

作者 9823189