I need to make a server app that listens to several TCP connections. This app must be lightweight and the TCP connections will come from GPS devices ( not from browsers, so I can't use WebSockets for example ).
To make sure this scales properly to thousands of devices I need to take full advantage of all the machines CPUs. According to my research I found 2 ways of doing it:
net
server and use the native cluster
API Node.js providesAccording to my understanding, these options are mutually exclusive. If I choose option 1, I can't use PM2, and vice-versa.
My team uses PM2 everywhere, so for consistency sake I would like to use PM2 as well. The problem here is that PM2 has issues with Node.js socket applications. I know for instance that to use socket.io
we need to install extra modules ( sticky-session
) but since I am using the native API there is no information
on what adaptations I need to do whatsoever.
Using the Native net
API I have no idea if PM2 will distribute the connections evenly among the CPUs nor can I find any information if the data will go to the right worker when the time comes.
To demonstrate my objective I made a small app using the cluster
native Node.js API:
const cluster = require("cluster");
const net = require("net");
const numCPUs = require("os").cpus().length;
if (cluster.isMaster) {
console.log(`Master ${process.pid} is running`);
// Fork workers.
for (let i = 0; i < numCPUs; i++) {
cluster.fork();
}
cluster.on("exit", (worker, code, signal) => {
console.log(`worker ${worker.process.pid} died`);
});
} else {
// Workers can share any TCP connection
const server = net.createServer( connection => {
console.log(`Client connected to ${process.pid}`);
connection.on( "end", () => console.log( `Client disconnected from ${process.pid}` ) );
connection.on( "data", data =>console.log(`${process.pid} received ${data.toString("ascii")}`) );
connection.on( "close", () => console.log(`Client closed connection with ${process.pid}`) );
} );
server.listen( 8124, () => console.log(`Worker ${process.pid} Bound`) );
console.log(`Worker ${process.pid} started`);
}
According to what I understand of the documentation, this sever balances load through all the CPUs and redirects the connections as well.
You can try this example using telnet: telnet localhost 8124
So, the answer here is tricky ...
So, PM2 cluster mode actually uses the Node.js native API. This means that using the net
and cluster
native APIs from Node would pretty much just be replicating work already done by PM2, unless you want to do it in a radically different way.
PM2 will scale correctly using the cluster
functionality ( what I refer to as "fork" the app using PM2 ) provided that your application is stateless.
If it is not, PM2 cannot guarantee anything.
http://pm2.keymetrics.io/docs/usage/cluster-mode/#statelessify-your-application
Yes, but your app needs to be stateless.
You need to save your socket connections and what be in Redis or MongoDB or something else.