农场 
以 über- simple API 和自定义耐用和自定义货币选项向子进程分配处理任务 . 以npm计 工农。 。 。 .
示例
鉴于一个文件, 孩子们.js数字 :
module.exports = function (inp, callback) {
callback(null, inp + ' BAR (' + process.pid + ')')
}
还有一个主文件 :
var workerFarm = require('worker-farm')
, workers = workerFarm(require.resolve('./child'))
, ret = 0
for (var i = 0; i < 10; i++) {
workers('#' + i + ' FOO', function (err, outp) {
console.log(outp)
if (++ret == 10)
workerFarm.end(workers)
})
}
我们会得到一个输出 类似如下:
#1 FOO BAR (8546)
#0 FOO BAR (8545)
#8 FOO BAR (8545)
#9 FOO BAR (8546)
#2 FOO BAR (8548)
#4 FOO BAR (8551)
#3 FOO BAR (8549)
#6 FOO BAR (8555)
#5 FOO BAR (8553)
#7 FOO BAR (8557)
这个例子载于 实例/基础 目录.
例1:估计使用童工的情况
您也会在 实例/pi 估计 页:1 通过使用蒙特卡洛 曲线下的区域 使用童工来完成单独的部分.
运行 node examples/pi 将给你一些像:
Doing it the slow (single-process) way...
π ≈ 3.1416269360000006 (0.0000342824102075312 away from actual!)
took 8341 milliseconds
Doing it the fast (multi-process) way...
π ≈ 3.1416233600000036 (0.00003070641021052367 away from actual!)
took 1985 milliseconds
重复性
工人农场的一个重要特点是 调用耐用性如果儿童程序在执行电话时因任何理由而死亡,这些电话将重新排队,并由其他儿童程序处理。 这样,当你要求做一些事情, 除非有事情 说真的 做错什么,你应该得到一个结果 你的回调功能.
我用过的箱子
还有其他图书馆可用于管理工人流程,但我的使用情况相当具体:我需要大量使用 节点-java 库与 JVM 代码交互。 不幸的是,由于JVM垃圾收集器如此难以与它互动,它容易在GC重载下踢出后杀死你的节点过程. 为了安全起见,我需要一个持久的方式打电话,以便(1) 它不会杀死我的主要过程和(2) 没有成功的电话会被重新提交处理.
工人农场允许我旋转多个JVM, 由节点控制, 并且有一个单一的,不复杂的API, 其行为与进程内API相同.
不过,不要认为"工人农场"是特指这个使用案例,它的设计非常通俗而简单,可以适应任何需要使用儿童节点过程的事物.
API 密码
农场出口主要职能和 end() 方法。 主要功能设置了由协调的儿童加工工人组成的"农场",可用于即兴经营多家农场,所有农场都独立经营.
工人标签( [选项,] path ToModule [,导出的方法])
以最基本的形式,你叫 workerFarm() ,并使用儿童进程引用的模块文件路径。 你应该用一个 绝对路径 到模块文件,获取路径的最佳方式是 require.resolve('./path/to/module'),该函数可以完全与 require('./path/to/module') 但它返回绝对路径.
exportedMethods
如果您的模块导出单个函数 module.exports 那你应该省略最后参数。 但是,如果您正在将多个函数导出到 module.exports 然后,你应该把它们列在弦乐阵列中:
var workers = workerFarm(require.resolve('./mod'), [ 'doSomething', 'doSomethingElse' ])
workers.doSomething(function () {})
workers.doSomethingElse(function () {})
列出可用的方法将指示工人农场在返回的对象上提供什么API。 如果你不列出一个 exportedMethods 组合,然后你会得到一个单一的可调用函数来使用;但是如果你列出可用的方法,那么你会得到一个具有可调用函数的物体,用这些名字来使用.
假设您在孩子模块中调用的每个功能将使用 callback 函数作为最后一个参数.
options
如果你不提供 options 对象然后使用下列默认值:
{
maxCallsPerWorker : Infinity
, maxConcurrentWorkers : require('os').cpus().length
, maxConcurrentCallsPerWorker : 10
, maxConcurrentCalls : Infinity
, maxCallTime : Infinity
, maxRetries : Infinity
, autoStart : false
}
-
maxCallsPerWorker允许您控制孩子的寿命。 肯定的数字将显示您只希望每个孩子在终止之前接受许多电话。 如果您需要控制孩子过程中的内存泄漏或类似情况,这可能是有益的. -
maxConcurrentWorkers将设定要同时维护的儿童流程数量。 默认情况下,它设定为当前系统中可用的CPU数量,但它可以是任何合理的数量,包括1。 。 。 . -
maxConcurrentCallsPerWorker允许您控制 货币 儿童个人过程。 电话被排入排队,并按允许他们同时接听的电话数量,被养成儿童程序。 默认情况下,它被任意设定为10个,这样,电话在工人之间相对平均地共享,但是,如果你的电话预计需要类似的时间,那么你可以设定为:Infinity工人农场不会排队接听任何电话,而是将电话平均分布在孩子身上,让他们去接听。 如果你的电话不是I/O绑定的,那么你在这里使用的价值就不重要了,因为个别工人一次不能执行一个以上的电话. -
maxConcurrentCalls允许您控制队列中的最大拨打次数—— 或正在积极处理, 或等待工人处理 .Infinity表示没有限制,但如果您具备可能无休止地排队工作的条件,并且您需要设定限制,请提供>0值和任何推动限制的呼叫都会以MaxConcurrentCallsError错误( 请检查err.type == 'MaxConcurrentCallsError') (中文(简体) ). -
maxCallTime在你使用它之前,先了解它的作用 何时!== Infinity时,以毫秒计 任何一次通话 可以在工人身上行刑。 如果只用一个电话就超过这个时限,那么负责打这个电话的工人就会被杀死,任何打着这个工人的电话都会带着一个电话返回TimeoutError(检查)err.type == 'TimeoutError') (中文(简体) ). 如果你正在运行maxConcurrentCallsPerWorker值大于1接下来 所有正在执行的呼叫 将失败,并将自动重新提交 unless you've changed themaxRetries选项。 使用这个,如果您有工作, 可能会在无限循环中结束, 您无法编程结束您的孩子代码 。 最好用一个maxConcurrentCallsPerWorker所以你不中断其他电话 当你有超时。 这种暂停是按电话进行,但会打断整个工人. -
maxRetries允许您在员工终止(意外或超时)后控制最多次数的调用。 默认情况下,此选项将设定为Infinity也就是说每个被解职的工人的每次通话都会被自动重排. 当重复次数超过时maxRetries值,将使用ProcessTerminatedError。请注意,如果运行时有限度maxCallTime财务报告和审定财务报表maxConcurrentCallsPerWorkers大于1然后是任意TimeoutError将会增加复读计数器 每个 被解聘的工人同时打电话. -
autoStart设定为true将尽早发动工人。 当工人要做昂贵的初始化时使用这个. 这样一来,他们就会准备好 当第一个请求通过.
farm.end(农场)
儿童过程会无限期地活着等待工作,你的农场经理会活着管理它的工人,所以如果你需要它来阻止的话,你就必须明确地这样做。 如果你把农场API送到 workerFarm.end() 然后它会干净结束你的工人过程。 注意,虽然这是一个 软 结束所以它会等待孩子的过程 完成他们的工作 然后再要求他们死.
任何被排队和尚未由儿童程序处理的电话都将被放弃. end() 仅等待目前进行中的项目.
一旦你结束一个农场, 它不会处理 任何更多的电话,所以不要尝试!
许可证
(c) 2014年罗德瓦格 @rvagg( 维基百科) 并持有麻省理工学院许可证。 麻省理工学院许可证中未明确授予的所有权利均予保留。 详见包含的LICENSE.md文件.

