plex-web-downloader/node_modules/cluster/docs/api.md

217 lines
6.5 KiB
Markdown
Raw Permalink Normal View History

2015-10-13 15:47:32 -04:00
## API
The Cluster API at its core is extremely simple, all we need to do is pass
our tcp or http `server` to `cluster()`, then call `listen()` as we would on the `http.Server` itself.
var cluster = require('../')
, http = require('http');
var server = http.createServer(function(req, res){
res.writeHead(200);
res.end('Hello World');
});
cluster(server)
.listen(3000);
Alternatively (and recommended) is to export your server instance via `module.exports`, and supply a path to `cluster()`. For example _app.js_:
module.exports = http.createServer(....);
and _server.js_ with our cluster logic, allowing our server to be `require()`ed within tests, and preventing potential issues by having open database connections etc within the master processes, as only the workers need access to the `server` instance.
cluster('app')
.listen(3000);
A good example if this, is a long-lived database connection. Our _app.js_ may have this initialized at the top, which although will work fine stand-alone, may cause cluster's master processes to hang when restarting or closing due to the connection remaining active in the event loop.
var db = redis.createClient();
### Abstract Clusters
Cluster is not bound to servers, cluster can be used to manage processes for processing job queues etc. Below is a minimalist example of this, simply invokes `cluster()` with no object, spawning a worker per cpu:
var cluster = require('cluster');
var proc = cluster().start();
if (proc.isWorker) {
// do things within the worker processes
} else {
// do something within the master
}
### Plugins
A plugin simple a function that accepts the `master` process. Most plugin functions _return_ another anonymous function, allowing them to accept options, for example:
function myPlugin(path){
return function(master) {
// do stuff
}
}
To use them, all we need to do is pass it to the `use()` method:
cluster(server)
.use(myPlugin('/some/path'))
.listen(3000);
To use a plugin that is bundled with Cluster simply grab it from the `cluster` object:
cluster(server)
.use(cluster.logger())
.listen(3000);
### Settings
Below are the settings available:
- `workers` Number of workers to spawn, defaults to the number of CPUs or `1`
- `working directory` Working directory defaulting to the script's dir
- `backlog` Connection backlog, defaulting to 128
- `socket port` Master socket port defaulting to `8989`
- `timeout` Worker shutdown timeout in milliseconds, defaulting to `60000`
- `title` master process title defaulting to "cluster"
- `worker title` worker process title defaulting to "cluster worker"
- `user` User id / name
- `group` Group id / name
We can take what we have now, and go on to apply settings using the `set(option, value)` method. For example:
cluster(server)
.set('working directory', '/')
.set('workers', 5)
.listen(3000);
### Signals
Cluster performs the following actions when handling signals:
- `SIGINT` hard shutdown
- `SIGTERM` hard shutdown
- `SIGQUIT` graceful shutdown
- `SIGUSR2` restart workers
### Events
The following events are emitted, useful for plugins or general purpose logging etc.
- `start`. When the IPC server is prepped
- `worker`. When a worker is spawned, passing the `worker`
- `listening`. When the server is listening for connections
- `closing`. When master is shutting down
- `close`. When master has completed shutting down
- `worker killed`. When a worker has died
- `worker exception`. Worker uncaughtException. Receives the worker and exception object
- `kill`. When a `signal` is being sent to all workers
- `restarting`. Restart requested by REPL or signal. Receives an object
which can be patched in order to preserve plugin state.
- `restart`. Restart complete, new master established, previous killed.
Receives an object with state preserved by the `restarting` even,
patched in the previous master.
### Master#state
Current state of the master process, one of:
- `active`
- `hard shutdown`
- `graceful shutdown`
### Master#isWorker
`true` when the script is executed as a worker.
cluster = cluster(server).listen(3000);
if (cluster.isWorker) {
// do something
}
Alternatively we can use the __CLUSTER_WORKER__ env var, populated with
the worker's id.
### Master#isMaster
`true` when the script is executed as master.
cluster = cluster(server).listen(3000);
if (cluster.isMaster) {
// do something
}
### Master#set(option, value)
Set `option` to `value`.
### Master#use(plugin)
Register a `plugin` for use.
### Master#in(env)
Conditionally perform the following action, if
__NODE_ENV__ matches `env`.
cluster(server)
.in('development').use(cluster.debug())
.in('development').listen(3000)
.in('production').listen(80);
The environment conditionals may be applied to several calls:
cluster(server)
.set('working directory', '/')
.in('development')
.set('workers', 1)
.use(cluster.logger('logs', 'debug'))
.use(cluster.debug())
.listen(3000)
.in('production')
.set('workers', 4)
.use(cluster.logger())
.use(cluster.pidfiles())
.listen(80);
If we perform the same action for environments, set them before
the first `in()` call, or use `in('all')`.
cluster(server)
.set('working directory', '/')
.do(function(){
console.log('some arbitrary action');
})
.in('development')
.set('workers', 1)
.use(cluster.logger('logs', 'debug'))
.use(cluster.debug())
.in('production')
.set('workers', 4)
.use(cluster.logger())
.use(cluster.pidfiles())
.in('all')
.listen(80);
### Master#spawn(n)
Spawn `n` additional workers.
### Master#close()
Graceful shutdown, waits for all workers to reply before exiting.
### Master#destroy()
Hard shutdown, immediately kill all workers.
### Master#restart([signal])
Defaults to a graceful restart, spawning a new master process, and sending __SIGQUIT__ to the previous master process. Alternatively a custom `signal` may be passed.
### Master#kill([signal])
Sends __SIGTERM__ or `signal` to all worker processes. This method is used by `Master#restart()`, `Master#close()` etc.