node.js clusterでHTTPサーバをマルチプロセス化する
node.jsのclusterを使用してHTTPサーバ(ウェブサーバ)を並列化し、パフォーマンスを上げられます。
読み方
- cluster
- くらすた
概要
node.jsの問題点として、シングルプロセスで処理をしていて、あるリクエストの処理が長くかかる場合、ほかのすべてのリクエストをブロックする可能性があります。httpモジュールで、ウェブサーバを起動したとき、同時に処理できるアクセスは、1つだけなので、処理がつまると、後ろに並んでいるリクエストの待ち行列は、ブロックされた状態になります。
そのような問題を解決するために、並行サーバ(並列)、マルチスレッドモデルなどがあるわけです。 node.jsでは、この問題に対処するいくつかの方法がありますが、ここでは、clusterを用いた例を示します。
clusterは、マルチコアを活かすためのものです。並行サーバは、コア数以上は実際に動作しないようで、コアが合計2個しかなければ、コア数より多くfork()したとしても、2個分のプロセスしか仕事をしません。
clusterの考え方は、伝統的なUnixプログラミングのforkモデルと同じと捉えて差し支えありません。
cluster.js で示すコードでは、node で起動されたプログラム(親)は、コア数だけ fork を行い、子プロセスがHTTPサーバを起動し、リクエストを処理します。
Unixのfork()と異なるのは、Unixのforkは、forkを呼び出した直後のプログラムが親プロセスと子プロセスで実行されますが、node.jsのclusterの場合は、forkを実行すると、同じプログラムが最初から起動されます。
親プロセスかどうかの判断は、 cluster.isMaster を参照し、真であれば、親と判断します。
ソースコード
cluster.js
/* * cluster.js * Copyright (C) 2014 kaoru <kaoru@bsd> */ var cluster = require('cluster'); var http = require('http'); var numCPUs = require('os').cpus().length; var port = 8080; var max_server = numCPUs; // max server if (cluster.isMaster) { console.log ('master'); for ( var i = 0 ; i < max_server ; ++i) { cluster.fork(); } cluster.on('exit', function(worker, code, signal) { console.log('worker ' + worker.process.pid + ' died'); }); } else { console.log("worker"); var server = http.createServer(function(req, res){ res.writeHead(200); res.end('Hello World'); }).listen(port); }
実行例
node cluster.js
ベンチマーク
node.jsによるHTTPサーバの作り方の簡単なHTTPサーバとcluster.jsを ab でベンチマークしました。 Hello World レベルのプログラムのベンチマークです。10000 リクエストを並列30でベンチマークした場合です。
ab -n 10000 -c 30 http://localhost:8080/
ベンチマークの結果は、平行サーバは、 2.3 秒、非平行サーバは 3.1秒と、ほんのすこしだけ、パフォーマンスが上がっていることが確認できました。
コア数 2 の並行サーバ
Document Path: / Document Length: 12 bytes Concurrency Level: 30 Time taken for tests: 2.323 seconds Complete requests: 10000 Failed requests: 0 Total transferred: 870000 bytes HTML transferred: 120000 bytes Requests per second: 4304.82 [#/sec] (mean) Time per request: 6.969 [ms] (mean) Time per request: 0.232 [ms] (mean, across all concurrent requests) Transfer rate: 365.74 [Kbytes/sec] received
非平行サーバ
Document Path: / Document Length: 12 bytes Concurrency Level: 30 Time taken for tests: 3.175 seconds Complete requests: 10000 Failed requests: 0 Total transferred: 1130000 bytes HTML transferred: 120000 bytes Requests per second: 3150.08 [#/sec] (mean) Time per request: 9.524 [ms] (mean) Time per request: 0.317 [ms] (mean, across all concurrent requests) Transfer rate: 347.62 [Kbytes/sec] received
関連項目
- node.jsによるHTTPサーバの作り方
- node.jsによるHTTPSサーバの作り方
- node.jsでSPDY対応ウェブサーバ
- node.js foreverでHTTPサーバをデーモン化する
- node.js HTTPサーバでApacheライクなログを記録する
- node.js HTTPサーバでレスポンスをgzipやdeflateで圧縮する
- node.js clusterでHTTPサーバをマルチプロセス化する
ツイート