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

Node.js uWS.js多线程服务器仅单一路径可连接问题

问题根源
  • Windows的TCP端口绑定机制和类Unix系统不同,默认不允许多个线程/进程同时抢占同一个端口。即便你看到两个线程都输出“监听成功”,实际上只有第一个完成端口绑定的线程能接收所有请求,它只配置了对应自身threadId的WebSocket路径,所以其他路径的连接请求会被直接拒绝。
  • uWS在Windows下不支持SO_REUSEPORT(类Unix系统的端口复用特性),因此多线程绑定同端口的写法在Windows上本质是无效的。
可行解决方案

方案1:主进程统一监听,分发请求到子线程

把端口监听逻辑放在主进程,在主进程中配置所有WebSocket路径,再将对应路径的请求转发给子线程处理:

主进程代码:

const uWS = require('uWebSockets.js');
const port = 3000;
const { Worker } = require('worker_threads');

// 创建两个子线程,传递线程ID
const workerMap = {
  1: new Worker('./worker.js', { workerData: { threadId: 1 } }),
  2: new Worker('./worker.js', { workerData: { threadId: 2 } })
};

// 主进程监听端口,配置全路径WebSocket路由
uWS.App()
  .ws('/1', {
    open: (ws) => {
      console.log('将/1路径的连接交给线程1处理');
      // 注意:uWS的ws对象无法直接序列化传给子线程,需在主进程做消息转发
      ws.on('message', (msg) => {
        workerMap[1].postMessage({ type: 'message', data: msg });
      });
    }
  })
  .ws('/2', {
    open: (ws) => {
      console.log('将/2路径的连接交给线程2处理');
      ws.on('message', (msg) => {
        workerMap[2].postMessage({ type: 'message', data: msg });
      });
    }
  })
  .listen(port, (token) => {
    token ? console.log(`主进程监听端口${port}成功`) : console.log(`主进程监听端口${port}失败`);
  });

子线程文件worker.js:

const { parentPort, workerData } = require('worker_threads');

parentPort.on('message', (msg) => {
  if (msg.type === 'message') {
    console.log(`线程${workerData.threadId}收到消息:${msg.data}`);
    // 此处编写具体业务处理逻辑
  }
});

方案2:子线程监听不同端口(Windows快速验证用)

给每个子线程分配不同的端口,客户端直接连接对应端口的路径:

const uWS = require('uWebSockets.js');
const { Worker, isMainThread, workerData } = require('worker_threads');

if (isMainThread) {
  // 启动两个子线程,分别监听3001、3002端口
  [1,2].forEach(id => new Worker(__filename, { workerData: { port: 3000 + id, threadId: id } }));
} else {
  const { port, threadId } = workerData;
  const wsPath = `/${threadId}`;

  uWS.App().ws(wsPath, {
    open: () => console.log(`线程${threadId}的WebSocket连接建立成功`),
  }).listen(port, (token) => {
    token ? console.log(`线程${threadId}监听端口${port}成功`) : console.log(`线程${threadId}监听端口${port}失败`);
  });
}

客户端分别连接localhost:3001/1和localhost:3002/2即可。

方案3:切换到类Unix系统(Linux/macOS)

如果可以切换到Linux或macOS,uWS原生支持SO_REUSEPORT,直接用内置多线程模式即可:

const uWS = require('uWebSockets.js');
const port = 3000;
const os = require('os');

uWS.App()
  .ws('/1', { open: () => console.log(`连接到线程:${process.pid}`) })
  .ws('/2', { open: () => console.log(`连接到线程:${process.pid}`) })
  // 指定线程数,uWS自动创建多线程监听同端口
  .listen(port, os.cpus().length, (token) => {
    token ? console.log(`监听端口${port}成功`) : console.log(`监听端口${port}失败`);
  });

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.04 19:43:27