任务是:
- 集群创建工作线程
- 每个worker逐行加载一些远程数据并将其输出到自己的process.stdout
- 整个集群的输出被重定向到文件
预期结果:所有工作人员的所有行都连接到结果文件
实际结果:在某些机器上,结果与预期一致,在其他机器上,结果是交错的。
在 Ubuntu 操作系统下的 0.10.47 和 0.12.7 Node 上进行了测试。在 Ubuntu 16.04.2 下的两台机器上,结果很好。在 Ubuntu 14.04.5 下的一个上是交错的。
我需要帮助来了解这种情况并在 14.04 上修复它。
集群.js:
var cluster = require("cluster");
cluster.setupMaster({
exec: "./worker.js"
});
cluster.fork();
cluster.fork();
worker.js:
var cluster = require("cluster");
var fs = require("fs");
var workerId = cluster.worker && cluster.worker.id || 1;
var stream = fs.createReadStream("./data" + workerId + ".log");
stream.on("end", function () {
process.exit();
});
stream.pipe(process.stdout);
您需要在同一文件夹中包含两个名为 data1.log 和 data2.log 的文件来读取数据:
$ wc -l data*
9260 data1.log
111636 data2.log
120896 total
管道总是给出良好的结果:
$ node cluster.js | wc -l
120896
重定向到文件仅在 Ubuntu 16.04 上给出了良好的结果,但在 Ubuntu 14.04 上却没有。在 Ubuntu 14.04 上更是如此,它每次都会给出不同的结果:
$ node cluster.js >result.log; wc -l result.log
114135 <= MUST BE 120896
$ node cluster.js >result.log; wc -l result.log
110136 <= MUST BE 120896
重定向到文件进行添加总是给出良好的结果:
$ rm result.log
$ node cluster.js >>result.log; wc -l result.log
120896
请注意,生成的文件小于原始文件。它的行数更少,字节更少。所以我认为来自不同 worker 的线路正在互相重写。
最佳答案
一般来说,您应该避免调用process.exit()
,因为当您将数据缓冲发送到某个地方时,它可能会导致问题。 process.exit()
几乎立即结束进程。
在这种特殊情况下,很可能在进程退出之前 process.stdout
尚未完全刷新其内部缓冲区(当 process.stdout
写入是异步时)。
我的建议是允许工作进程自然退出,只需通过 process.disconnect()
断开工作进程中的(未使用的)IPC channel 并删除工作进程中的 process.exit()
即可。这应该允许 process.stdout 在进程退出之前完全耗尽/刷新。
关于node.js 集群,将子级标准输出重定向到文件中断数据,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/43663065/