Cluster and Fork mode difference in PM2 - node.js

I've searched a lot to figure out this question, but I didn't get clear explanation. Is there only one difference thing that clustered app can be scaled out and forked app cannot be?
PM2's public site explains Cluster mode can do these feature but no one says about pros of Fork mode (maybe, it can get NODE_APP_INSTANCE variable).
I feel like Cluster might be part of Fork because Fork seems like to be used in general. So, I guess Fork means just 'forked process' from the point of PM2 and Cluster means 'forked process that is able to be scaled out'. Then, why should I use Fork mode?

The main difference between fork_mode and cluster_mode is that it orders pm2 to use either the child_process.fork api or the cluster api.
What does this means internally?
Fork mode
Take the fork mode as a basic process spawning. This allows to change the exec_interpreter, so that you can run a php or a python server with pm2. Yes, the exec_interpreter is the "command" used to start the child process. By default, pm2 will use node so that pm2 start server.js will do something like:
require('child_process').spawn('node', ['server.js'])
This mode is very useful because it enables a lot of possibilities. For example, you could launch multiple servers on pre-established ports which will then be load-balanced by HAProxy or Nginx.
Cluster mode
The cluster will only work with node as it's exec_interpreter because it will access to the nodejs cluster module (eg: isMaster, fork methods etc.). This is great for zero-configuration process management because the process will automatically be forked in multiple instances.
For example pm2 start -i 4 server.js will launch 4 instances of server.js and let the cluster module handle load balancing.

Node.js is single-thread.
That means only 1 core of your Intel quad-core CPU can execute the node application.
It called: fork_mode.
We use it for local dev.
pm2 start server.js -i 0 helps you running 1 node thread on each core of your CPU.
And auto-load-balance the stateless coming requests.
On the same port.
We call it: cluster_mode.
Which is used for the sake of performance on production.
You may also choose to do this on local dev if you want to stress test your PC :)

Documentation and sources are really misleading here.
Reading up on this in the sources, the only differences seems to be, that they use either node cluster or child_process API. Since cluster uses the latter, you are actually doing the same. There is just a lot more custom stdio passing around happening inn fork_mode. Also cluster can only be communicated with via strings, not objects.
By default you are using fork_mode. If you pass the the -i [number]-option, you're going into cluster_mode, which you generally aim for w/ pm2.
Also fork_mode instance probably can't listen on the same port due to EADDRINUSE. cluster_mode can. This way you also can structure you app to run on the same port being automatically load balanced. You have to build apps without state then though e.g. sessions, dbs.

Related

Should I use Node.js Greenlock-Express with cluster mode at the same time I'm using pm2 cluster mode?

I'm building an stateless Web application using Node.js, Express and pm2 for process management.
In production environments, I run one instance of the application for each core of the server CPU (thanks to pm2 cluster mode).
Recently I started to read about Greenlock-Express (for obtaining certificates automatically) and it also has a "cluster" property, which if I understand correctly it basically does the same thing as pm2 cluster mode.
Will there be any collisions or possible issues if I run both Greenlock-Express and pm2 in cluster mode? If they do, what's the best alternative to obtain automatically SSL certificates with Node.js in a Windows enviroment? And if they do not, is it optimal to use both of them in cluster mode?
PM2 only implements partial cluster support.
See https://git.rootprojects.org/root/greenlock-express.js/issues/26
I'd recommend just using serviceman (cross-platform) or raw systemd (linux) or Docker (cloud deploys).
If you are going to use PM2, you use Greenlock Express with it the same way that you would use it with Ruby, Python, etc - as a separate executable, not as a "built-in" app.
PM2s default optimizations for node apps are already implemented in Greenlock Express, and since PM2 only has partial cluster support, there's not a way to tell PM2 to pass control to Greenlock Express, nor to have PM2 accept control from Greenlock Express.
Also: Only use cluster mode if you actually have multiple CPU cores otherwise you'll cause thread thrashing and slow down your process.

PM2 - Is this considered a good practice

In my project I have several servers which run NodeJS applications using PM2, those were not created by me. I am not that familiar with the PM2. Now I need to start a new server, which is simply a CRON process that queries an ElasticSearch instance.
There are no routes or anything in it, just a CRON with some logging.
Here is my dilemma. I have played with PM2 and I become somewhat familiar with what is it, and what it does. But the question is how shall I run it?
The previous projects do have PM2 config.json with many parameters, and they are started in cluster mode (handled with Nginx), and when I start them I see all process's becoming daemons. But in my case I don't need that. I just need it to run as a single service.
In other words if I use the configuration file to run the PM2, I see it spawned in cluster mode, and it creates chaos as my CRON is fired many times. I don't need that. If I start it in Fork mode, it also spawns instances, but all of them die, except one (due to which they are using same port). I also don't need that.
I just need single service.
I managed to run the my CRON app.js with the singe line, simple as:
PM2 start app.js. It runs in single thread, and I can see it's info with PM2 status. All fine.
If I run it with the single line(as in my case), is it considered ok? Based in my knowledge if I use config.json, it will always run it in fork or cluster.
Is it ok to run it in single line, or do I need still to use a config.json file.
If you only need one process to be run, as is the case, you're doing the right thing.

How to achieve zero downtime redeployment in Node.js

What is the easiest way to achieve zero downtime for my Node.js application?
I have an app that requires the following steps for redeployment:
npm install
node_modules/.bin/bower install
node_modules/.bin/gulp
The result of these operations is the ready-to-run application in the generated by the gulpfile.js directory named build. In this directory I have a currently-running instance of the same application (currently launched via forever like this -- forever start server.js).
As far as I know, it is not possible to achieve zero downtime via forever module, so I decided to choose another way to do it.
I saw pm2 but I found it very complex tbh (prove me wrong if you don't feel the same).
I also saw naught but I can't even start my application via naught start server.js -- it doesn't even print anything in stdout / stderr.
I also saw up-time but I didn't get the idea -- how will it handle situation when I run gulp that should replace files in the directory where currently-running instance work at the moment?
Regarding of handling replaced files during build: if these files is used by Node.js app then all changes will be applied upon process restart (since these files are loaded into memory), browser frontend files could also be cached in application memory to achieve similar behavior (changes applied only upon restart or/and cache invalidation).
We're using pm2 in cluster mode.
pm2 start app.js -i
The above command starts app.js in cluster mode on all available CPU cores.
zero downtime restart:
pm2 gracefulReload all
this command restarts all processes sequentially, so if you have more than one process up and running there is always at least one process that servers requests during restart.
If you have only one process of app.js you can start it in cluster mode and run pm2 scale app.js 2 (starts one more process) then pm2 gracefulReload all and then pm2 scale app.js 1 (removes previously started process).
Though I think app restarting is not main problem of zero downtime deployment, we've not managed to handle DB migrations, so full app shutdown is needed to apply DB changes. Also there could be an issue with browser frontend files when during deploy user obtained the new version of them, but AJAX request is processed by old version of server process, in this case sticky sessions and API versioning came to the rescue.

Is it possible to run sails.js on a node cluster?

I am currently running an express server using the node js vanilla cluster setup as demonstrated over here:
http://rowanmanning.com/posts/node-cluster-and-express/
I'd like to move the server over to sails.js and I am wondering if anyone knows how to configure sails to support the node cluster (no proxies, just simple cluster).
TX,
Sean.
First thing - if You want to use sessions, You need to use session store. Otherwise session will be not shared between instances of Your app.
Then, The easiest way is to use something like PM2, which can be found here: https://github.com/Unitech/pm2
You dont need to do changes in Your app.js files - it should be written as standard non-clustered sails app. PM2 will do the job.
Just start the app with pm2 start app.js -i x where x is number of instances or use pm2 start app.js -i max which will start instances that are equal to numbers of processors, or processor threads.
PM2 is great and very stable, it has many features to run it smoothly in producation, however it has some flaws in development. If You will ever have a problem with "port already in use" after stopping or even deleting app that was using it - You will have to use pm2 kill which will kill ALL Your apps.
Other than that - its just great - with some additional monitoring tools.
You can use PM2 Library a create different instances like cluster.
For do it you have to use app.js file, like:
pm2 start app.js
If you want to run the max number of instances availables:
pm2 start app.js -i max
check the documentation for more: https://github.com/Unitech/pm2

Run at startup and monitor redis and node.js processes

I want to deploy node.js app which depends on redis. Both processes will run on the same VPS. There are plenty of examples on how to daemonize and monitor node and I've also found some uncommented configuration for redis. How do I put it together? Can I just combine these two snippets in one monitrc file?
You could use Supervisord to orchestrate the launch of Redis and your NodeJS apps (use the priority parameter to start Redis before your apps). Supervisord will automatically restart your NodeJS app if they crash.
You can then setup monit over it to be alerted when something wrong happens and to restart your NodeJS processes if they use too much memory/cpu or if they are not accessible anymore from a specific port.

Resources