La tarea es:
Resultado esperado: todas las líneas de todos los trabajadores se concatenan en el archivo resultante
Resultado real: en algunas máquinas el resultado es el esperado, en otras el resultado es entrelazado.
Probado en nodos 0.10.47 y 0.12.7 bajo Ubuntu OS. En dos máquinas con Ubuntu 16.04.2, el resultado es bueno. En uno bajo Ubuntu 14.04.5 está entrelazado.
Necesito ayuda para entender esta situación y arreglarla el 14.04.
clúster.js:
var cluster = require("cluster"); cluster.setupMaster({ exec: "./worker.js" }); cluster.fork(); cluster.fork();trabajador.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);Necesita dos archivos en la misma carpeta llamados data1.log y data2.log con datos para leer:
$ wc -l data* 9260 data1.log 111636 data2.log 120896 totalLa tubería siempre da buen resultado:
$ node cluster.js | wc -l 120896La redirección al archivo da buenos resultados solo en Ubuntu 16.04 pero nunca en Ubuntu 14.04. Aún más en Ubuntu 14.04 da cada vez resultados diferentes:
$ 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 120896La redirección al archivo de adición siempre da buenos resultados:
$ rm result.log $ node cluster.js >>result.log; wc -l result.log 120896Tenga en cuenta que el archivo resultante es menor que el original. Tiene menos líneas e incluso menos bytes. Entonces supongo que las líneas de diferentes trabajadores se están reescribiendo entre sí.
En general, debe evitar llamar a process.exit() debido a los problemas que puede causar cuando tiene datos almacenados en búfer para enviarlos a alguna parte. process.exit() finaliza el proceso casi inmediatamente.
En este caso particular, bien podría ser que process.stdout no haya vaciado completamente su búfer interno (para cuando las escrituras de process.stdout son asíncronas ) antes de que finalice el proceso.
Mi sugerencia sería permitir que el proceso de trabajo salga naturalmente simplemente desconectando el canal IPC (no utilizado) en el trabajador a través de process.disconnect() y eliminando el process.exit() en el trabajador. Esto debería permitir que process.stdout se drene/vacíe por completo antes de que finalice el proceso.
Para solucionar el problema, se debe establecer explícitamente el modo de canalización en el código maestro:
var cluster = require("cluster"); cluster.setupMaster({ exec: "./worker.js", => silent: true }); for (var i = 0; i < 2; i++) { var worker = cluster.fork(); => worker.process.stdout.pipe(process.stdout); => worker.process.stderr.pipe(process.stderr); }Creo que la razón de tales diferencias en el comportamiento del mismo código en diferentes versiones de ubuntu está en las implementaciones del búfer de manejo del archivo del kernel de Linux.