sticky-cluster v0.3.5
sticky-cluster
What is it
In cluster environment socket.io requires you to use sticky sessions, to ensure that a given client hits the same process every time, otherwise its handshake mechanism won't work properly. To accomplish that, manuals suggest the sticky-session module.
My module is based on the same principles as sticky-session, but utilizes a more efficient hash function and also works asynchronously out of the box.
Advantages
- up to 10x faster than
sticky-session - much better scattering over the worker processes than that of
sticky-session - asynchronous out of the box, just run a callback when you're done initializing everything else
- works correctly with
ipv6
More alternatives
- sticky-session -- worse perfomance, not async
- throng -- plain cluster, not sticky
- node-cluster-socket.io -- doesn't work with
ipv6
Get started
As usual
npm install sticky-cluster --savethen
require('sticky-cluster')(
// server initialization function
function (callback) {
var http = require('http');
var app = require('express')();
var server = http.createServer(app);
// configure an app
// do some async stuff if needed
// don't do server.listen(), just pass the server instance into the callback
callback(server);
},
// options
{
concurrency: 10,
port: 3000,
debug: true,
env: function (index) { return { stickycluster_worker_index: index }; }
}
);Accepted options
Here's the full list of accepted options:
| key | meaning | default |
|---|---|---|
concurrency | number of workers to be forked | number of CPUs on the host system |
port | http port number to listen | 8080 |
debug | log actions to console | false |
prefix | prefix in names of IPC messages | sticky-cluster: |
env | function (workerIndex => workerEnv) to provide additional worker configuration through the environment variables | sets stickycluster_worker_index (be aware that worker's index stays the same through its death and resurrection, but worker's id, which is used in debug messages, changes) |
hardShutdownDelay | delay(ms) to trigger the hard shutdown if the graceful shutdown doesn't complete | 60 * 1000 ms |
errorHandler | callback function for the net.Server.error event on the serverInstance created in master.js. | function (err) { console.log(err); process.exit(1); } |
Example
Open terminal at the ./example directory and sequentially run npm install and npm start. Navigate to http://localhost:8080. Have a look at the source.
Benchmarking
There's a script you can run to test various hashing functions. It generates a bunch of random IP addresses (both v4 and v6) and then hashes them using different algorithms aiming to get a consistent {IP address -> array index} mapping.
For every hash function the script outputs execution time in milliseconds (less is better) and distribution of IP addresses over the clients' ids (more even distribution is better).
$ cd ./benchmark
$ npm install
$ npm start -- <num_workers> <num_ip_addresses>An output from my laptop:
$ npm start
generating random ips...
benchmarking...
int31
time (ms): 188
scatter: [ 25788, 8378, 7768, 9438, 7280, 6649, 9648, 8061, 10287, 6703 ]
djb2
time (ms): 20
scatter: [ 9957, 9809, 9853, 10075, 10077, 9957, 9982, 10068, 10179, 10043 ]The algorithm used in the sticky-session module is int31 and the local one is djb2. As might be seen, the djb2 algorithm provides significant time advantage and clearly more even scattering over the worker processes.
Changelog
0.3.2 -> 0.3.3
- Allow the caller to specify a callback function for the
net.Server.errorevent on theserverInstancecreated inmaster.js.
0.3.1 -> 0.3.2
- Close alive connections before exiting to achieve
graceful shutdown. - Add
hardShutdownDelayoption to triggerhard shutdownif thegraceful shutdowndoesn't complete in the amount of delay.
0.2.1 -> 0.3.0
- Allow to set individual worker environment variables through the
options.envfunction.
0.2.0 -> 0.2.1
- Handle empty IP addresses.
0.1.2 -> 0.2.0
- Removed a
SIGTERMlistener on the master process. - Replaced
.on('SIGINT', ...)with.once('SIGINT', ...). - Improved debug logs.
- Moved unnecessary dependencies from the main package to the
./exampleand./benchmarkapps. - Fixed a few minor issues in the mentioned apps.
0.1.1 -> 0.1.2
- Updated the example.
0.1.0 -> 0.1.1
- Published to NPM.