You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

NestJS基于ws库的WebSocket服务关闭后进程未退出,端口占用求助

问题描述

我在WSL2环境下使用NestJS结合ws库搭建WebSocket服务器,遇到以下异常情况:

  • 执行nest start启动HTTP服务器
  • 使用Postman连接WebSocket实例
  • 在终端按下Ctrl + C关闭服务进程后,Postman仍显示处于连接状态
  • 再次启动服务时出现错误:Error: listen EADDRINUSE: address already in use :::3000,必须手动杀死占用端口的进程才能重启

若先断开Postman的连接再关闭服务,则能正常重启。之前使用普通Express+ws搭建的服务器不会出现此问题,我原本以为关闭服务器时会自动终止所有客户端连接,但实际并未生效。

补充信息:构建NestJS应用后,在/dist目录执行node main.js运行服务,关闭时能正常断开所有客户端连接,问题似乎与Nest CLI的启动方式有关?

问题分析与解决

核心原因

Nest CLI的nest start命令默认启用热重载功能(基于ts-node-dev实现),热重载模式下主进程会fork子进程运行应用代码。当按下Ctrl + C时,主进程被终止,但子进程可能未正确捕获终止信号,导致WebSocket服务器的子进程仍持有端口,且未主动关闭客户端连接。

而直接运行node main.js属于单进程模式,收到SIGINT信号后,Nest的生命周期钩子会正常触发,主动关闭所有WebSocket连接并释放端口。

可行解决方案

  1. 禁用热重载启动服务
    启动时添加--watch false参数关闭热重载,此时服务以单进程模式运行,Ctrl + C会正常触发Nest的 shutdown 流程,主动关闭所有WebSocket连接:

    nest start --watch false
    
  2. 手动监听终止信号(推荐)
    在Nest根模块中手动监听进程终止信号,主动关闭WebSocket服务器及所有客户端连接,确保无论启动模式如何都能正常清理:

    import { Module, OnModuleDestroy } from '@nestjs/common';
    import { WebSocketServer } from '@nestjs/websockets';
    import { Server } from 'ws';
    
    @Module({})
    export class AppModule implements OnModuleDestroy {
      @WebSocketServer()
      private wss: Server;
    
      async onModuleDestroy() {
        this.wss.close(() => {
          console.log('所有WebSocket连接已关闭');
        });
      }
    
      constructor() {
        // 监听SIGINT(Ctrl+C)和SIGTERM信号
        ['SIGINT', 'SIGTERM'].forEach(signal => {
          process.on(signal, () => {
            this.wss.close(() => {
              process.exit(0);
            });
          });
        });
      }
    }
    
  3. 使用生产模式启动
    执行nest start --prod命令,该模式会先构建应用再以单进程方式运行,与直接执行node main.js的行为一致,能正常处理连接关闭:

    nest start --prod
    

内容的提问来源于stack exchange,提问作者Brother Bill

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.18 13:00:55