Node.js v0.10.18 手册 & 文档
目录
集群#
稳定度: 1 - 实验性
A single instance of Node runs in a single thread. To take advantage of multi-core systems the user will sometimes want to launch a cluster of Node processes to handle the load.
单个 Node 实例运行在单个线程中。要发挥多核系统的能力,用户有时候需要启动一个 Node 进程集群来处理负载。
The cluster module allows you to easily create a network of processes that all share server ports.
集群模块允许你方便地创建一个共享服务器端口的进程网络。
cluster.on('exit', function(worker, code, signal) {
console.log('工作进程 ' + worker.process.pid + ' 被终止');
});
} else {
// 工作进程可以共享任意 TCP 连接
// 本例中为 HTTP 服务器
http.createServer(function(req, res) {
res.writeHead(200);
res.end("你好,操蛋的世界\n");
}).listen(8000);
}
Running node will now share port 8000 between the workers:
现在,运行 node 将会在所有工作进程间共享 8000 端口:
% NODE_DEBUG=cluster node server.js
23521,Master Worker 23524 online
23521,Master Worker 23526 online
23521,Master Worker 23523 online
23521,Master Worker 23528 online
This feature was introduced recently, and may change in future versions. Please try it out and provide feedback.
这是一个近期推出的功能,在未来版本中可能会有所改变。请尝试并提供反馈。
Also note that, on Windows, it is not yet possible to set up a named pipe server in a worker.
还要注意的是,在 Windows 中尚不能在工作进程中建立一个被命名的管道服务器。
它是如何工作的#
The worker processes are spawned using the child_process.fork
method,
so that they can communicate with the parent via IPC and pass server
handles back and forth.
工作进程是通过使用 child_process.fork
方法派生的,因此它们可以通过 IPC(进程间通讯)与父进程通讯并互相传递服务器句柄。
The cluster module supports two methods of distributing incoming connections.
集群模块支持两种分配传入连接的方式。
The first one (and the default one on all platforms except Windows), is the round-robin approach, where the master process listens on a port, accepts new connections and distributes them across the workers in a round-robin fashion, with some built-in smarts to avoid overloading a worker process.
第一种(同时也是除 Windows 外所有平台的缺省方式)为循环式:主进程监听一个端口,接受新连接,并以轮流的方式分配给工作进程,并以一些内建机制来避免单个工作进程的超载。
The second approach is where the master process creates the listen socket and sends it to interested workers. The workers then accept incoming connections directly.
第二种方式是,主进程建立监听嵌套字,并将它发送给感兴趣的工作进程,由工作进程直接接受传入连接。
The second approach should, in theory, give the best performance. In practice however, distribution tends to be very unbalanced due to operating system scheduler vagaries. Loads have been observed where over 70% of all connections ended up in just two processes, out of a total of eight.
第二种方式理论上有最好的性能。然而在实践中,由于操作系统的调度变幻莫测,分配往往十分不平衡。负载曾被观测到超过 70% 的连接结束于总共八个进程中的两个。
Because server.listen()
hands off most of the work to the master
process, there are three cases where the behavior between a normal
node.js process and a cluster worker differs:
因为 server.listen()
将大部分工作交给了主进程,所以一个普通的node.js进程和一个集群工作进程会在三种情况下有所区别:
server.listen({fd: 7})
Because the message is passed to the master, file descriptor 7 in the parent will be listened on, and the handle passed to the worker, rather than listening to the worker's idea of what the number 7 file descriptor references.server.listen(handle)
Listening on handles explicitly will cause the worker to use the supplied handle, rather than talk to the master process. If the worker already has the handle, then it's presumed that you know what you are doing.server.listen(0)
Normally, this will cause servers to listen on a random port. However, in a cluster, each worker will receive the same "random" port each time they dolisten(0)
. In essence, the port is random the first time, but predictable thereafter. If you want to listen on a unique port, generate a port number based on the cluster worker ID.
server.listen({fd: 7})
由于消息被传递到主进程,父进程中的文件描述符 7 会被监听,并且句柄会被传递给工作进程,而不是监听工作进程中文件描述符 7 所引用的东西。server.listen(handle)
明确地监听一个句柄会使得工作进程使用所给句柄,而不是与主进程通讯。如果工作进程已经拥有了该句柄,则假定您知道您在做什么。server.listen(0)
通常,这会让服务器监听一个随机端口。然而,在集群中,各个工作进程每次listen(0)
都会得到一样的“随机”端口。实际上,端口在第一次时是随机的,但在那之后却是可预知的。如果您想要监听一个唯一的端口,则请根据集群工作进程 ID 来生成端口号。
There is no routing logic in Node.js, or in your program, and no shared state between the workers. Therefore, it is important to design your program such that it does not rely too heavily on in-memory data objects for things like sessions and login.
由于在 Node.js 或您的程序中并没有路由逻辑,工作进程之间也没有共享的状态,因此在您的程序中,诸如会话和登录等功能应当被设计成不能太过依赖于内存中的数据对象。
Because workers are all separate processes, they can be killed or re-spawned depending on your program's needs, without affecting other workers. As long as there are some workers still alive, the server will continue to accept connections. Node does not automatically manage the number of workers for you, however. It is your responsibility to manage the worker pool for your application's needs.
由于工作进程都是独立的进程,因此它们会根据您的程序的需要被终止或重新派生,并且不会影响到其它工作进程。只要还有工作进程存在,服务器就会继续接受连接。但是,Node 不会自动为您管理工作进程的数量,根据您的程序所需管理工作进程池是您的责任。
cluster.schedulingPolicy#
The scheduling policy, either cluster.SCHED_RR
for round-robin or
cluster.SCHED_NONE
to leave it to the operating system. This is a
global setting and effectively frozen once you spawn the first worker
or call cluster.setupMaster()
, whatever comes first.
调度策略 cluster.SCHED_RR
表示轮流制,cluster.SCHED_NONE
表示由操作系统处理。这是一个全局设定,并且一旦您派生了第一个工作进程或调用了 cluster.setupMaster()
后便不可更改。
SCHED_RR
is the default on all operating systems except Windows.
Windows will change to SCHED_RR
once libuv is able to effectively
distribute IOCP handles without incurring a large performance hit.
SCHED_RR
是除 Windows 外所有操作系统上的缺省方式。只要 libuv 能够有效地分配 IOCP 句柄并且不产生巨大的性能损失,Windows 也将会更改为 SCHED_RR
方式。
cluster.schedulingPolicy
can also be set through the
NODE_CLUSTER_SCHED_POLICY
environment variable. Valid
values are "rr"
and "none"
.
cluster.schedulingPolicy
也可以通过环境变量 NODE_CLUSTER_SCHED_POLICY
设定。有效值为 "rr"
和 "none"
。
cluster.settings#
Object
exec
String file path to worker file. (Default=__filename
)args
Array string arguments passed to worker. (Default=process.argv.slice(2)
)silent
Boolean whether or not to send output to parent's stdio. (Default=false
)
Object
exec
String 工作进程文件的路径。(缺省为__filename
)args
Array 传递给工作进程的字符串参数。(缺省为process.argv.slice(2)
)silent
Boolean 是否将输出发送到父进程的 stdio。(缺省为false
)
All settings set by the .setupMaster
is stored in this settings object.
This object is not supposed to be changed or set manually, by you.
所有由 .setupMaster
设定的设置都会储存在此设置对象中。这个对象不应由您手动更改或设定。
集群的主进程(判断当前进程是否是主进程)#
Boolean
Boolean
True if the process is a master. This is determined
by the process.env.NODE_UNIQUE_ID
. If process.env.NODE_UNIQUE_ID
is
undefined, then isMaster
is true
.
如果进程为主进程则为 true
。这是由 process.env.NODE_UNIQUE_ID
判断的,如果 process.env.NODE_UNIQUE_ID
为 undefined,则 isMaster
为 true
。
集群的主线程(判断当前线程是否是主线程)#
Boolean
Boolean
This boolean flag is true if the process is a worker forked from a master.
If the process.env.NODE_UNIQUE_ID
is set to a value, then
isWorker
is true
.
如果当前进程是分支自主进程的工作进程,则该布尔标识的值为 true
。如果 process.env.NODE_UNIQUE_ID
被设定为一个值,则 isWorker
为 true
。
事件: 'fork'#
worker
Worker objectworker
Worker object
When a new worker is forked the cluster module will emit a 'fork' event. This can be used to log worker activity, and create you own timeout.
当一个新的工作进程被分支出来,cluster 模块会产生一个 'fork' 事件。这可被用于记录工作进程活动,以及创建您自己的超时判断。
cluster.on('fork', function(worker) {
timeouts[worker.id] = setTimeout(errorMsg, 2000);
});
cluster.on('listening', function(worker, address) {
clearTimeout(timeouts[worker.id]);
});
cluster.on('exit', function(worker, code, signal) {
clearTimeout(timeouts[worker.id]);
errorMsg();
});
事件: 'online'#
worker
Worker objectworker
Worker object
After forking a new worker, the worker should respond with a online message. When the master receives a online message it will emit such event. The difference between 'fork' and 'online' is that fork is emitted when the master tries to fork a worker, and 'online' is emitted when the worker is being executed.
分支出一个新的工作进程后,工作进程会响应一个在线消息。当主进程收到一个在线消息后,它会触发该事件。'fork' 和 'online' 的区别在于前者发生于主进程尝试分支出工作进程时,而后者发生于工作进程被执行时。
cluster.on('online', function(worker) {
console.log("嘿嘿,工作进程完成分支并发出回应了");
});
事件: 'listening'#
worker
Worker objectaddress
Objectworker
Worker objectaddress
Object
When calling listen()
from a worker, a 'listening' event is automatically assigned
to the server instance. When the server is listening a message is send to the master
where the 'listening' event is emitted.
当工作进程调用 listen()
时,一个 listening
事件会被自动分配到服务器实例中。当服务器处于监听时,一个消息会被发送到那个'listening'事件被分发的主进程。
The event handler is executed with two arguments, the worker
contains the worker
object and the address
object contains the following connection properties:
address
, port
and addressType
. This is very useful if the worker is listening
on more than one address.
事件处理器被执行时会带上两个参数。其中 worker
包含了工作进程对象,address
对象包含了下列连接属性:地址 address
、端口号 port
和地址类型 addressType
。如果工作进程监听多个地址,那么这些信息将十分有用。
cluster.on('listening', function(worker, address) {
console.log("一个工作进程刚刚连接到 " + address.address + ":" + address.port);
});
事件: 'disconnect'#
worker
Worker objectworker
Worker object
When a workers IPC channel has disconnected this event is emitted.
This will happen when the worker dies, usually after calling
.kill()
.
当一个工作进程的 IPC 通道断开时此事件会发生。这发生于工作进程结束时,通常是调用 .kill()
之后。
When calling .disconnect()
, there may be a delay between the
disconnect
and exit
events. This event can be used to detect if
the process is stuck in a cleanup or if there are long-living
connections.
当调用 .disconnect()
后,disconnect
和 exit
事件之间可能存在延迟。该事件可被用于检测进程是否被卡在清理过程或存在长连接。
cluster.on('disconnect', function(worker) {
console.log('工作进程 #' + worker.id + ' 断开了连接');
});
事件: 'exit'#
worker
Worker objectcode
Number the exit code, if it exited normally.signal
String the name of the signal (eg.'SIGHUP'
) that caused the process to be killed.worker
Worker objectcode
Number 如果是正常退出则为退出代码。signal
String 使得进程被终止的信号的名称(比如'SIGHUP'
)。
When any of the workers die the cluster module will emit the 'exit' event.
This can be used to restart the worker by calling fork()
again.
当任意工作进程被结束时,集群模块会分发exit
事件。通过再次调用fork()
函数,可以使用这个事件来重启工作进程。
cluster.on('exit', function(worker, code, signal) {
var exitCode = worker.process.exitCode;
console.log('工作进程 ' + worker.process.pid + ' 被结束('+exitCode+')。正在重启...');
cluster.fork();
});
事件: 'setup'#
worker
Worker objectworker
Worker object
When the .setupMaster()
function has been executed this event emits.
If .setupMaster()
was not executed before fork()
this function will
call .setupMaster()
with no arguments.
当 .setupMaster()
函数被执行时触发此事件。如果 .setupMaster()
在 fork()
之前没被执行,那么它会不带参数调用 .setupMaster()
。
cluster.setupMaster([settings])#
settings
Objectexec
String file path to worker file. (Default=__filename
)args
Array string arguments passed to worker. (Default=process.argv.slice(2)
)silent
Boolean whether or not to send output to parent's stdio. (Default=false
)
settings
Objectexec
String 工作进程文件的路径。(缺省为__filename
)args
Array 传给工作进程的字符串参数。(缺省为process.argv.slice(2)
)silent
Boolean 是否将输出发送到父进程的 stdio。(缺省为false
)
setupMaster
is used to change the default 'fork' behavior. The new settings
are effective immediately and permanently, they cannot be changed later on.
setupMaster
被用于更改缺省的 fork
行为。新的设置会立即永久生效,并且在之后不能被更改。
Example:
示例:
var cluster = require("cluster");
cluster.setupMaster({
exec : "worker.js",
args : ["--use", "https"],
silent : true
});
cluster.fork();
cluster.fork([env])#
env
Object Key/value pairs to add to child process environment.return Worker object
env
Object 添加到子进程环境变量中的键值对。- 返回 Worker object
Spawn a new worker process. This can only be called from the master process.
派生一个新的工作进程。这个函数只能在主进程中被调用。
cluster.disconnect([callback])#
callback
Function called when all workers are disconnected and handlers are closedcallback
Function 当所有工作进程都断开连接并且句柄被关闭时被调用
When calling this method, all workers will commit a graceful suicide. When they are disconnected all internal handlers will be closed, allowing the master process to die graceful if no other event is waiting.
调用此方法时,所有的工作进程都会优雅地将自己结束掉。当它们都断开连接时,所有的内部处理器都会被关闭,使得主进程可以可以在没有其它事件等待时优雅地结束。
The method takes an optional callback argument which will be called when finished.
该方法带有一个可选的回调参数,会在完成时被调用。
cluster.worker#
Object
Object
A reference to the current worker object. Not available in the master process.
对当前工作进程对象的引用。在主进程中不可用。
if (cluster.isMaster) {
console.log('我是主进程');
cluster.fork();
cluster.fork();
} else if (cluster.isWorker) {
console.log('我是工作进程 #' + cluster.worker.id);
}
cluster.workers#
Object
Object
A hash that stores the active worker objects, keyed by id
field. Makes it
easy to loop through all the workers. It is only available in the master
process.
一个储存活动工作进程对象的哈希表,以 id
字段作为主键。它能被用作遍历所有工作进程,仅在主进程中可用。
// 遍历所有工作进程
function eachWorker(callback) {
for (var id in cluster.workers) {
callback(cluster.workers[id]);
}
}
eachWorker(function(worker) {
worker.send('向一线工作者们致以亲切问候!');
});
Should you wish to reference a worker over a communication channel, using the worker's unique id is the easiest way to find the worker.
如果您希望通过通讯通道引用一个工作进程,那么使用工作进程的唯一标识是找到那个工作进程的最简单的办法。
socket.on('data', function(id) {
var worker = cluster.workers[id];
});
类: Worker#
A Worker object contains all public information and method about a worker.
In the master it can be obtained using cluster.workers
. In a worker
it can be obtained using cluster.worker
.
一个 Worker 对象包含了工作进程的所有公开信息和方法。可通过主进程中的 cluster.workers
或工作进程中的 cluster.worker
取得。
worker.id#
String
String
Each new worker is given its own unique id, this id is stored in the
id
.
每个新的工作进程都被赋予一个唯一的标识,这个标识被储存在 id
中。
While a worker is alive, this is the key that indexes it in cluster.workers
当一个工作进程可用时,这就是它被索引在 cluster.workers 中的主键。
worker.process#
ChildProcess object
ChildProcess object
All workers are created using child_process.fork()
, the returned object
from this function is stored in process.
所有工作进程都是使用 child_process.fork()
创建的,该函数返回的对象被储存在 process 中。
See: Child Process module
worker.suicide#
Boolean
Boolean
This property is a boolean. It is set when a worker dies after calling
.kill()
or immediately after calling the .disconnect()
method.
Until then it is undefined
.
该属性是一个布尔值。它会在工作进程调用 .kill()
后终止时或调用 .disconnect()
方法时被设置。在此之前它的值是 undefined
。
worker.send(message, [sendHandle])#
message
ObjectsendHandle
Handle objectmessage
ObjectsendHandle
Handle object
This function is equal to the send methods provided by
child_process.fork()
. In the master you should use this function to
send a message to a specific worker. However in a worker you can also use
process.send(message)
, since this is the same function.
该函数等同于 child_process.fork()
提供的 send 方法。在主进程中您可以用该函数向特定工作进程发送消息。当然,在工作进程中您也能使用 process.send(message)
,因为它们是同一个函数。
This example will echo back all messages from the master:
这个例子会回应来自主进程的所有消息:
} else if (cluster.isWorker) {
process.on('message', function(msg) {
process.send(msg);
});
}
worker.kill([signal='SIGTERM'])#
signal
String Name of the kill signal to send to the worker process.signal
String 发送给工作进程的终止信号的名称
This function will kill the worker, and inform the master to not spawn a
new worker. The boolean suicide
lets you distinguish between voluntary
and accidental exit.
该函数会终止工作进程,并告知主进程不要派生一个新工作进程。布尔值 suicide
让您区分自行退出和意外退出。
// 终止工作进程
worker.kill();
This method is aliased as worker.destroy()
for backwards
compatibility.
该方法的别名是 worker.destroy()
,以保持向后兼容。
worker.disconnect()#
When calling this function the worker will no longer accept new connections, but
they will be handled by any other listening worker. Existing connection will be
allowed to exit as usual. When no more connections exist, the IPC channel to the worker
will close allowing it to die graceful. When the IPC channel is closed the disconnect
event will emit, this is then followed by the exit
event, there is emitted when
the worker finally die.
调用该函数后工作进程将不再接受新连接,但新连接仍会被其它正在监听的工作进程处理。已存在的连接允许正常退出。当没有连接存在,连接到工作进程的 IPC 通道会被关闭,以便工作进程安全地结束。当 IPC 通道关闭时 disconnect
事件会被触发,然后则是工作进程最终结束时触发的 exit
事件。
Because there might be long living connections, it is useful to implement a timeout.
This example ask the worker to disconnect and after 2 seconds it will destroy the
server. An alternative would be to execute worker.kill()
after 2 seconds, but
that would normally not allow the worker to do any cleanup if needed.
由于可能存在长连接,通常会实现一个超时机制。这个例子会告知工作进程断开连接,并且在 2 秒后销毁服务器。另一个备选方案是 2 秒后执行 worker.kill()
,但那样通常会使得工作进程没有机会进行必要的清理。
process.on('message', function(msg) {
if (msg === 'force kill') {
server.close();
}
});
}
事件: 'message'#
message
Objectmessage
Object
This event is the same as the one provided by child_process.fork()
.
In the master you should use this event, however in a worker you can also use
process.on('message')
该事件和 child_process.fork()
所提供的一样。在主进程中您应当使用该事件,而在工作进程中您也可以使用 process.on('message')
。
As an example, here is a cluster that keeps count of the number of requests in the master process using the message system:
举个例子,这里有一个集群,使用消息系统在主进程中统计请求的数量:
// 将请求通知主进程
process.send({ cmd: 'notifyRequest' });
}).listen(8000);
}
事件: 'online'#
Same as the cluster.on('online')
event, but emits only when the state change
on the specified worker.
和 cluster.on('online')
事件一样,但仅当特定工作进程的状态改变时发生。
cluster.fork().on('online', function() {
// 工作进程在线
});
事件: 'listening'#
address
Objectaddress
Object
Same as the cluster.on('listening')
event, but emits only when the state change
on the specified worker.
和 cluster.on('listening')
事件一样,但仅当特定工作进程的状态改变时发生。
cluster.fork().on('listening', function(address) {
// 工作进程正在监听
});
事件: 'disconnect'#
Same as the cluster.on('disconnect')
event, but emits only when the state change
on the specified worker.
和 cluster.on('disconnect')
事件一样,但仅当特定工作进程的状态改变时发生。
cluster.fork().on('disconnect', function() {
// 工作进程断开了连接
});
事件: 'exit'#
code
Number the exit code, if it exited normally.signal
String the name of the signal (eg.'SIGHUP'
) that caused the process to be killed.code
Number 如果是正常退出则为退出代码。signal
String 使得进程被终止的信号的名称(比如'SIGHUP'
)。
Emitted by the individual worker instance, when the underlying child process is terminated. See child_process event: 'exit'.
由单个工作进程实例在底层子进程被结束时触发。详见子进程事件: 'exit'。
var worker = cluster.fork();
worker.on('exit', function(code, signal) {
if( signal ) {
console.log("worker was killed by signal: "+signal);
} else if( code !== 0 ) {
console.log("worker exited with error code: "+code);
} else {
console.log("worker success!");
}
});
var worker = cluster.fork();
worker.on('exit', function(code, signal) {
if( signal ) {
console.log("工人被信号 " + signal + " 杀掉了");
} else if( code !== 0 ) {
console.log("工作进程退出,错误码:" + code);
} else {
console.log("劳动者的胜利!");
}
});