I'm working on a IOT project where the Node.js application perform following tasks:
1. Reading stream of messages using asynchronous messaging library (IO bound)
2. Sending the messages to web service where machine learning happens based on the messages that were sent by Node.js application (IO bound as only API call is involved)
3. Receive the pattern generated as a result of machine learning from web service (using REST API)
4. Compare the pattern against the real-time streaming messages (CPU intensive as complex algorithms are involved for pattern matching).
5. Logging stack traces (IO bound)
A node.js application is going to be developed to have these functionalities as separate tasks running under a single-thread by default. Being the fact that, spawning the child process will be useful only for CPU intensive tasks, how to to do clustering for node.js process doint both IO and CPU bound tasks? Do we need to partially perform clustering on this node.js application?
Can anyone please suggest the effective architecture for this node.js application?
If you have ANY CPU-intensive tasks, then use clustering for all requests.
The fact that a clustered process is also doing some I/O intensive stuff won't hurt you, but you will want the clustered process for the CPU intensive stuff. So, just make your server clustered and let each cluster handle the whole load of a request (both the I/O and the CPU stuff).
In a nutshell, CPU-intensive stuff is the primary driver for clustering. It doesn't hurt anything if the clustered processes are also doing non-blocking I/O. In fact, clustering up to the number of CPUs available can even help I/O bound processes some too in high load situations (though not nearly as much help as with CPU-intensive processes).
An alternative, though it may be a more complicated implementation, is to use child processes or the new Worker threads only for the CPU-intensive parts of your request handling. In that case, you'd create some sort of work queue and a set of child processes or Worker threads for performing operations in the queue and your master process would distribute tasks to each child process from the queue. Using this scheme, you can decide exactly which code is executed via the work queue and which code stays in the main process, though you now have to coordinate between the two using some sort of interprocess communication.