◆ cluster 使ってみた

Node.js でファイルの変換処理みたいな時間かかる処理をやっていて CPU リソース的に 100% まで行ってなくて結構時間はかかってます
同時に複数実行したほうがよさそうなので コマンドプロンプトいっぱい開いて並列にしようかなと考えてたのですが 毎回やるなら自動でプロセスを複数作るようにしておいたほうが楽そうです

あるのは知ってるけど使ったことはない cluster というちょうどいいものがあるので使ってみました

cluster

cluster では fork メソッドを使ってプロセスを作ります
child_process では何を実行するか選べますが cluster では実行対象は自分自身のプロセスと同じです
実行中のプロセスの process.argv のコマンドが実行されます

最初に起動するマスタープロセスも マスターが作るワーカープロセスも同じスクリプトの実行なので cluster.isMaster で今がどっちかを判断して処理を分岐させます
メッセージのやりとりは child_process.fork と同じような感じです
ワーカープロセスでは process に対して send したり on で message イベントをリッスンします
マスタープロセスでは fork で作ったインスタンスに対して send したり on で message イベントをリッスンします

ワーカープロセスはコマンドライン引数も引き継ぐので 3 つのワーカーを作るなら 引数の番号を 3 で割った余りの番目のワーカーが処理するとすれば簡単に分散処理することができます
処理対象のファイル名が列挙してるだけならこれで単純にマルチプロセスに分散できます
複雑な条件で分散させたい場合は マスタープロセスがそれぞれのワーカーに処理内容を送って ワーカープロセスでは送られてきたメッセージで処理内容を決めたほうがいいです

また fork メソッドの引数を使って 起動時にマスタープロセスがワーカープロセスに環境変数を設定できます
簡単な情報ならメッセージ送信よりここで指定してしまうほうが楽です

3 つのプロセスを起動して 引数をそれぞれのプロセスが処理します
特にすることはないのでただマスタープロセスにメッセージを送るだけにしてます

const cluster = require("cluster")

if (cluster.isMaster) {
for (let i = 0; i < 3; i++) {
cluster.fork({ id: i }).on("message", msg => console.log(msg))
}
} else {
const id = ~~process.env.id
const targets = process.argv.slice(2).filter((e, i) => i % 3 === id)
for (const value of targets) {
process.send(`id: ${id}, value: ${value}`)
}
process.exit()
}

C:\data\tmp1\node-cluster>node test.js 0 1 2 3 4 5 6 7
id: 0, value: 0
id: 2, value: 2
id: 2, value: 5
id: 0, value: 3
id: 0, value: 6
id: 1, value: 1
id: 1, value: 4
id: 1, value: 7