node.jsnode-worker-threads

Can I use node http server in worker threads


I know about cluster module, but question about worker_threads.

Code example

const { Worker, isMainThread, threadId } = require('worker_threads')
const { createServer } = require('http')

if (isMainThread) {
  let w1 = new Worker(__filename)
  let w2 = new Worker(__filename)
} else {
  const server = createServer((req, res) => {
    res.end(`response from thread ${threadId}`)
  })
  server.listen(8080, () => {
    console.log(`Thread ${threadId} is listening ${server.address().port}`)
  })
}

When I run this code on Windows, I get obvious error

Error: listen EADDRINUSE: address already in use :::8080

But it works without errors on WSL

$ node ./index.js
Thread 2 is listening 8080
Thread 1 is listening 8080

But in browser I always get response only from single worker, depends on order they started

Can I listen single http port in worker threads or not? If yes, how can I make load balancing on this port? Why nodejs allows to listen same port on WSL?


Solution

  • No, you cannot listen on the same port in worker threads. On Linux (Debian 10), your code fails with the expected error Error: listen EADDRINUSE: address already in use :::8080 as well. Expect it to fail in production environments.

    The reason for this is that, even though Linux does support port sharing via SO_REUSEPORT, it's a fairly new feature and libuv does not implement the flag (not for tcp, at least). I have no idea why WSL is not producing an error for you, but as you can see, it does not do load balancing.

    Here's how you can implement load balancing: use the cluster module instead, since that's what it is designed for. Or, listen on different ports and use a separate load balancer - though, if the processing is totally independent, you may be better off spawning separate, independent processes, instead of using the worker_threads module.