Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

When is better using clustering or worker_threads?

I have been reading about multi-processing on NodeJS to get the best understanding and try to get a good performance in heavy environments with my code.

Although I understand the basic purpose and concept for the different ways to take profit of the resources to handle the load, some questions arise as I go deeper and it seems I can't find the particular answers in the documentation.

NodeJS in a single thread:

NodeJS runs a single thread that we call event loop, despite in background OS and Libuv are handling the default worker pool for I/O asynchronous tasks.

We are supossed to use a single core for the event-loop, despite the workers might be using different cores. I guess they are sorted in the end by OS scheduler.

NodeJS as multi-threaded:

When using "worker_threads" library, in the same single process, different instances of v8/Libuv are running for each thread. Thus, they share the same context and communicate among threads with "message port" and the rest of the API.

Each worker thread runs its Event loop thread. Threads are supposed to be wisely balanced among CPU cores, improving the performance. I guess they are sorted in the end by OS scheduler.

Question 1: When a worker uses I/O default worker pool, are the very same threads as other workers' pool being shared somehow? or each worker has its own default worker pool?

NodeJS in multi-processing:

When using "cluster" library, we are splitting the work among different processes. Each process is set on a different core to balance the load... well, the main event loop is what in the end is set in a different core, so it doesn't share core with another heavy event loop. Sounds smart to do it that way.

Here I would communicate with some IPC tactic.

Question 2: And the default worker pool for this NodeJS process? where are they? balanced among the rest of cores as expected in the first case? Then they might be on the same cores as the other worker pools of the cluster I guess. Shouldn't it be better to say that we are balancing main threads (event loops) rather than "the process"?

Being all this said, the main question:

Question 3: Whether is better using clustering or worker_threads? If both are being used in the same code, how can both libraries agree the best performance? or they just can simply get in conflict? or at the end is the OS who takes control?

like image 733
jaume Avatar asked Apr 20 '20 17:04

jaume


People also ask

What is the difference between cluster and Worker_threads packages in node JS?

Clusters of Node. js processes can be used to run multiple instances of Node. js that can distribute workloads among their application threads. When process isolation is not needed, use the worker_threads module instead, which allows running multiple application threads within a single Node.

How does PM2 cluster work?

PM2 is a Production Process Manager for Node. js applications with a built-in Load Balancer. When properly configured, PM2 will automatically run your app in cluster mode, spawn workers for you, and take care of spawning new workers when a worker dies.

What is worker pool in Nodejs?

The Worker Pool of Node. js is implemented in libuv (docs), which exposes a general task submission API. Node. js uses the Worker Pool to handle "expensive" tasks. This includes I/O for which an operating system does not provide a non-blocking version, as well as particularly CPU-intensive tasks.


1 Answers

Each worker thread has its own main loop (libuv etc). So does each cloned nodejs process when you use clustering.

Clustering is a way to load-balance incoming requests to your nodejs server over several copies of that server.

Worker threads are a way for a single nodejs process to offload long-running functions to a separate thread, to avoid blocking its own main loop.

Which is better? It depends on the problem you're solving. Worker threads are for long-running functions. Clustering makes a server able to handle more requests, by handling them in parallel. You can use both if you need to: have each nodejs cluster process use a worker thread for long-running functions.

As a first approximation for your decision-making: only use worker threads when you know you have long-running functions.

The node processes (whether from clustering or worker threads) don't get tied to specific cores (or Intel processor threads) on the host machine; the host's OS scheduling assigns cores as needed. The host OS scheduler minimize context-switch overhead when assigning cores to runnable processes. If you have too many active Javascript instances (cluster instances + worker threads) the host OS will give them timeslices according to its scheduling algorithms. Other than avoiding too many Javascript instances, there's very little point in trying second-guess the OS scheduler.

Edit Each nodejs instance, with any worker threads, uses a single libuv thread pool. A main nodejs process shares a single libuv thread pool with all its worker threads. If your nodejs program uses many worker threads, you may, or may not, need to set the UV_THREADPOOL_SIZE environment variable to a value greater than the default 4.

Nodejs's cluster functionality uses the underlying OS's fork/exec scheme to create a new OS process for each cluster instance. So, each cluster instance has its own libuv pool.

If you're running stuff at scale, lets say with more than ten host machines running your nodejs server, then you can spend time optimizing Javascript instances.

Don't forget nginx if you use it as a reverse proxy to handle your https work. It needs some processor time too, but it uses fine-grain multithreading so you won't have to worry about it unless you have huge traffic.

like image 149
O. Jones Avatar answered Oct 18 '22 11:10

O. Jones