把 TCP 句柄转移到其他线程
🌐 Transferring TCP handles to other threads
一个已连接的 TCP net.Socket 可以通过在 worker_threads postMessage() 调用的 transferList 中列出它来移动到另一个线程。传输完成后,源套接字会在发送线程上被销毁(进一步使用会返回 ERR_STREAM_DESTROYED 而不是静默丢弃数据),而套接字会继续在接收线程上工作。这使得可以在一个线程上接受连接,并将它们分配到一组工作线程中,例如在工作线程之上构建类似 node:cluster 的模型。
🌐 A connected TCP net.Socket can be moved to another thread by listing it in the
transferList of a worker_threads postMessage() call. After the
transfer, the source socket is destroyed on the sending thread (further use
fails with ERR_STREAM_DESTROYED rather than silently dropping data), and the
socket continues to work on the receiving thread. This makes it possible to
accept connections on one thread and distribute them across a pool of worker
threads, for example to build a node:cluster-like model on top of worker
threads.
这个套接字必须是新接收或新创建的 TCP 连接:它必须仍然绑定到一个活跃的句柄上,不能正在连接或已被销毁,也不能已经开始读取或有缓冲的数据。否则 postMessage() 会抛出 ERR_WORKER_HANDLE_NOT_TRANSFERABLE。只支持 TCP 套接字。
🌐 The socket must be a freshly accepted or created TCP connection: it must still
be attached to a live handle, must not be connecting or destroyed, and must not
have started reading or have buffered data. Otherwise postMessage() throws
ERR_WORKER_HANDLE_NOT_TRANSFERABLE. Only TCP sockets are supported.
const net = require('node:net');
const { Worker } = require('node:worker_threads');
// worker.js receives `{ socket }` messages and handles each connection.
const worker = new Worker('./worker.js');
const server = net.createServer((socket) => {
// Hand the freshly accepted connection off to the worker thread.
worker.postMessage({ socket }, [socket]);
});
server.listen(8000); 一个监听 net.Server 也可以用同样的方式转移,这会把监听套接字本身(以及它的待接受队列)移动到接收线程。
🌐 A listening net.Server can be transferred the same way, which moves the
listening socket itself (and its pending accept queue) to the receiving thread.
一个未被采纳的 TCP BoundSocket 也可以被转移,这会移动已绑定(但尚未监听或连接)的套接字。这允许一个线程同步保留一个端口,而另一个线程由服务器或外部连接采用。管道绑定是不可转移的。转移后,源 BoundSocket 的行为就像它已经被采纳一样:address()、fd() 和 close() 会抛出 ERR_SOCKET_HANDLE_ADOPTED。
🌐 An un-adopted TCP BoundSocket can also be transferred, which moves the
bound (but not yet listening or connected) socket. This allows a port to be
reserved synchronously on one thread and adopted by a server or outgoing
connection on another. Pipe binds are not transferable. After the transfer, the
source BoundSocket behaves as if it had been adopted: address(), fd() and
close() throw ERR_SOCKET_HANDLE_ADOPTED.