nodejs多核処理
17175 ワード
はじめに、nodejsは単一プロセスの単一スレッドのサーバーエンジンであることをみんなは知っています.どんなに強力なハードウェアがあっても、単一のCPUでしか計算できません.そこで、第三者のclusterを開発し、nodeがマルチコアCPUを利用して並行して実現できるようにしました.
nodejsの発展に従って、nodejsに環境を生産させて、多プロセスの多核処理を支持しなければなりません.V 0.0.6バージョンでは、Nodejsにclusterの特性が内蔵されています.これにより、Nodejsはついに独立したアプリケーション開発ソリューションとして目に映るようになりました.
目次 cluster紹介 clusterの簡単な使用 clusterの動作原理 clusterのAPI マスターとウォーカーの通信 clusterで負荷の均衡を実現します.win 7失敗 .clusterで負荷の均衡を実現するために-uuntu成功 cluster負荷バランスポリシーの試験 1.clusterの紹介
clusterはnodejs内蔵のモジュールで、nodejs多核処理に用いられます.clusterモジュールは、多プロセス並列化プログラムの開発難易度を簡略化し、負荷バランスのためのクラスタを容易に構築することができます.
2.clusterの簡単な使用
私のシステム環境 win 7 64 bit Nodejs:v 0.0.5 Npm:1.2.19 winの環境の中で、私達はclusterを通じて多核のnodeをスタートさせてウェブサービスを提供します.
新しいプロジェクトディレクトリ:
3.clusterの動作原理
各ワーカープロセスはchild_を使うことによってprocess.fork関数は、IPC(Inter-Parocess Communication、プロセス間通信)に基づいて、masterプロセスとの間の通信を実現します.
workerがserver.listen(...)関数を使用するとパラメータシーケンスをmasterプロセスに伝えます.マスタープロセスがworkersにマッチしたら、最後の文を労働者に伝えます.マスターがワーカーにマッチしていない場合は、ワーカーを作成して、文を伝えてワーカーに伝えます.
境界条件では、3つの面白い行動があります.注:下のserver.listenは、下の「http.Server-」net.Server類への呼び出しです. 1.server.listen({fd:7}:masterとworkerの通信過程で、ファイルを転送することによって、masterは「ファイル記述は7」であって、「ファイル記述は7」の参照を転送するのではなく、「ファイル記述は7」を傍受します. .server.listen(handle):masterとworkerの通信プロセスは、handle関数を介して通信し、プロセス連絡なしに に通信する..server.listen(0):masterとworkerの通信プロセスでは、クラスタ内のworkerはランダムポートを開いて共有し、socket通信によって、上記の例の57132 のように通信する.
複数のプロセスが同じリソースにある場合、オペレーティングシステムの負荷バランスは非常に効率的である.Node.jsにはルーティングロジックがありません.worker間に共有状態がありません.したがって、プログラムはメモリベースのsessionなど、簡単に設計する必要があります.
ワーカーは独力で運行していますので、プログラムの必要に応じて独立して削除または再起動できます.ワーカーは互いに影響しません.ウォーカーが生きている限り、マスタは接続を受信し続けます.Nodeは自動的にworkersの数を維持しません.私たちは自分の接続池を作ることができます.
4.clusterのAPI
公式サイトのアドレス:http://nodejs.org/api/cluster.html#cluster_cluster
clusterオブジェクトの各種属性と関数 cluster.settings:クラスタパラメータオブジェクト を構成する. cluster.isMaster:マスターノード ではないかと判断する. cluster.isWorker:ワーカーノード であるかどうかを判定する. Event:'fork':workプロセス作成イベントを傍受する Event:'online':ウォーカーを待ち受けて成功イベントを作成しました. Event:'listening':モニターワーカーがmaster状態イベント に向かう. Event:'disconnect':ウォーカー切断イベントを傍受する Event:'exit':worker退出イベントを傍受する Event:'setup':setupMasterイベントを傍受する cluster.setupMaster(settings):クラスタパラメータを設定する cluster.fork(env):workプロセス を作成する. cluster.disconnect(calback):worketプロセスを閉じる cluster.worker:現在のworkerオブジェクト を取得する. cluster.workers:クラスタ内で生存している全てのウォーカーオブジェクト を取得する.
workerオブジェクトの各種属性と関数:cluster.workersを通じて、cluster.worketが得られます. worker.id:プロセスID番号 worker.process:ChildProcessオブジェクト worker.suicide:disconnect()後、workerが自殺したかどうかを判断する worker.send:masterはworkerにメッセージを送ります.注:workerがmasterにメッセージを送るにはprocess.send を使います. worker.kill([signal='SIGTRM]):指定されたウォーカーを殺し、別名destory() worker.disconnect():workカーを切断し、workerを自殺させます. Event:'message':マスターとウォーカーのメッセージイベントを傍受する Event:'online':指定されたウォーカーを傍受して成功イベントを作成する Event:'listening':マスター・ウォーカー状態イベントを傍受する Event:'disconnect':ウォーカー切断イベントを傍受する Event:'exit':worker退出イベントを傍受する 5.マスターとウォーカーの通信
clusterのAPIを実現し、マスターとワーカーが通信するようにします.
新規ファイル:cluster.js
新規ファイル:server.js
7.clusterで負荷の均衡を実現する--uuntu成功
Linuxのシステム環境 Linux:Ubuntu 12.04.2 64 bit Server Node:v 0.1.2 Npm:1.2.21 構築項目:多く説明しない
8.cluster負荷バランス戦略のテスト
私達はLinuxの下でテストを完成しました.テストソフトを使ったことがあります.
インストール
server.logファイルを表示します.
はい、私たちはまた有用な技能を学びました.clusterを利用してマルチ核応用を構築し、マルチCPUのキャリア性能を十分に活用しましょう.
転載は出典を明記してください.http://blog.fens.me/nodejs-core-cluster/
nodejsの発展に従って、nodejsに環境を生産させて、多プロセスの多核処理を支持しなければなりません.V 0.0.6バージョンでは、Nodejsにclusterの特性が内蔵されています.これにより、Nodejsはついに独立したアプリケーション開発ソリューションとして目に映るようになりました.
目次
clusterはnodejs内蔵のモジュールで、nodejs多核処理に用いられます.clusterモジュールは、多プロセス並列化プログラムの開発難易度を簡略化し、負荷バランスのためのクラスタを容易に構築することができます.
2.clusterの簡単な使用
私のシステム環境
新しいプロジェクトディレクトリ:
~ D:\workspace\javascript>mkdir nodejs-cluster && cd nodejs-cluster
新規ファイル:ap.js
~ vi app.js
var cluster = require('cluster');
var http = require('http');
var numCPUs = require('os').cpus().length;
if (cluster.isMaster) {
console.log("master start...");
// Fork workers.
for (var i = 0; i < numCPUs; i++) {
cluster.fork();
}
cluster.on('listening',function(worker,address){
console.log('listening: worker ' + worker.process.pid +', Address: '+address.address+":"+address.port);
});
cluster.on('exit', function(worker, code, signal) {
console.log('worker ' + worker.process.pid + ' died');
});
} else {
http.createServer(function(req, res) {
res.writeHead(200);
res.end("hello world
");
}).listen(0);
}
コンソールでnodeプログラムを起動します.
~ D:\workspace\javascript
odejs-cluster>node app.js
master start...
listening: worker 2368, Address: 0.0.0.0:57132
listening: worker 1880, Address: 0.0.0.0:57132
listening: worker 1384, Address: 0.0.0.0:57132
listening: worker 1652, Address: 0.0.0.0:57132
マスターはマスターノードで、ウォーカーは実行ノードです.そしてCPUの数に応じて、ウォーカーを起動します.私はローカルにデュアルコアのCPUですので、4つのコアが検出され、4つのウォーカーが起動しました.3.clusterの動作原理
各ワーカープロセスはchild_を使うことによってprocess.fork関数は、IPC(Inter-Parocess Communication、プロセス間通信)に基づいて、masterプロセスとの間の通信を実現します.
workerがserver.listen(...)関数を使用するとパラメータシーケンスをmasterプロセスに伝えます.マスタープロセスがworkersにマッチしたら、最後の文を労働者に伝えます.マスターがワーカーにマッチしていない場合は、ワーカーを作成して、文を伝えてワーカーに伝えます.
境界条件では、3つの面白い行動があります.注:下のserver.listenは、下の「http.Server-」net.Server類への呼び出しです.
複数のプロセスが同じリソースにある場合、オペレーティングシステムの負荷バランスは非常に効率的である.Node.jsにはルーティングロジックがありません.worker間に共有状態がありません.したがって、プログラムはメモリベースのsessionなど、簡単に設計する必要があります.
ワーカーは独力で運行していますので、プログラムの必要に応じて独立して削除または再起動できます.ワーカーは互いに影響しません.ウォーカーが生きている限り、マスタは接続を受信し続けます.Nodeは自動的にworkersの数を維持しません.私たちは自分の接続池を作ることができます.
4.clusterのAPI
公式サイトのアドレス:http://nodejs.org/api/cluster.html#cluster_cluster
clusterオブジェクトの各種属性と関数
workerオブジェクトの各種属性と関数:cluster.workersを通じて、cluster.worketが得られます.
clusterのAPIを実現し、マスターとワーカーが通信するようにします.
新規ファイル:cluster.js
~ vi cluster.js
var cluster = require('cluster');
var http = require('http');
var numCPUs = require('os').cpus().length;
if (cluster.isMaster) {
console.log('[master] ' + "start master...");
for (var i = 0; i < numCPUs; i++) {
var wk = cluster.fork();
wk.send('[master] ' + 'hi worker' + wk.id);
}
cluster.on('fork', function (worker) {
console.log('[master] ' + 'fork: worker' + worker.id);
});
cluster.on('online', function (worker) {
console.log('[master] ' + 'online: worker' + worker.id);
});
cluster.on('listening', function (worker, address) {
console.log('[master] ' + 'listening: worker' + worker.id + ',pid:' + worker.process.pid + ', Address:' + address.address + ":" + address.port);
});
cluster.on('disconnect', function (worker) {
console.log('[master] ' + 'disconnect: worker' + worker.id);
});
cluster.on('exit', function (worker, code, signal) {
console.log('[master] ' + 'exit worker' + worker.id + ' died');
});
function eachWorker(callback) {
for (var id in cluster.workers) {
callback(cluster.workers[id]);
}
}
setTimeout(function () {
eachWorker(function (worker) {
worker.send('[master] ' + 'send message to worker' + worker.id);
});
}, 3000);
Object.keys(cluster.workers).forEach(function(id) {
cluster.workers[id].on('message', function(msg){
console.log('[master] ' + 'message ' + msg);
});
});
} else if (cluster.isWorker) {
console.log('[worker] ' + "start worker ..." + cluster.worker.id);
process.on('message', function(msg) {
console.log('[worker] '+msg);
process.send('[worker] worker'+cluster.worker.id+' received!');
});
http.createServer(function (req, res) {
res.writeHead(200, {"content-type": "text/html"});
res.end('worker'+cluster.worker.id+',PID:'+process.pid);
}).listen(3000);
}
コンソールログ:
~ D:\workspace\javascript
odejs-cluster>node cluster.js
[master] start master...
[worker] start worker ...1
[worker] [master] hi worker1
[worker] start worker ...2
[worker] [master] hi worker2
[master] fork: worker1
[master] fork: worker2
[master] fork: worker3
[master] fork: worker4
[master] online: worker1
[master] online: worker2
[master] message [worker] worker1 received!
[master] message [worker] worker2 received!
[master] listening: worker1,pid:6068, Address:0.0.0.0:3000
[master] listening: worker2,pid:1408, Address:0.0.0.0:3000
[master] online: worker3
[worker] start worker ...3
[worker] [master] hi worker3
[master] message [worker] worker3 received!
[master] listening: worker3,pid:3428, Address:0.0.0.0:3000
[master] online: worker4
[worker] start worker ...4
[worker] [master] hi worker4
[master] message [worker] worker4 received!
[master] listening: worker4,pid:6872, Address:0.0.0.0:3000
[worker] [master] send message to worker1
[worker] [master] send message to worker2
[worker] [master] send message to worker3
[worker] [master] send message to worker4
[master] message [worker] worker1 received!
[master] message [worker] worker2 received!
[master] message [worker] worker3 received!
[master] message [worker] worker4 received!
6.clusterで負荷バランスを実現する--win 7失敗新規ファイル:server.js
~ vi server.js
var cluster = require('cluster');
var http = require('http');
var numCPUs = require('os').cpus().length;
if (cluster.isMaster) {
console.log('[master] ' + "start master...");
for (var i = 0; i < numCPUs; i++) {
cluster.fork();
}
cluster.on('listening', function (worker, address) {
console.log('[master] ' + 'listening: worker' + worker.id + ',pid:' + worker.process.pid + ', Address:' + address.address + ":" + address.port);
});
} else if (cluster.isWorker) {
console.log('[worker] ' + "start worker ..." + cluster.worker.id);
http.createServer(function (req, res) {
console.log('worker'+cluster.worker.id);
res.end('worker'+cluster.worker.id+',PID:'+process.pid);
}).listen(3000);
}
サーバを起動:
~ D:\workspace\javascript
odejs-cluster>node server.js
[master] start master...
[worker] start worker ...1
[worker] start worker ...2
[master] listening: worker1,pid:1536, Address:0.0.0.0:3000
[master] listening: worker2,pid:5920, Address:0.0.0.0:3000
[worker] start worker ...3
[master] listening: worker3,pid:7156, Address:0.0.0.0:3000
[worker] start worker ...4
[master] listening: worker4,pid:2868, Address:0.0.0.0:3000
worker4
worker4
worker4
worker4
worker4
worker4
worker4
worker4
curlツールでアクセスする
C:\Users\Administrator>curl localhost:3000
worker4,PID:2868
C:\Users\Administrator>curl localhost:3000
worker4,PID:2868
C:\Users\Administrator>curl localhost:3000
worker4,PID:2868
C:\Users\Administrator>curl localhost:3000
worker4,PID:2868
C:\Users\Administrator>curl localhost:3000
worker4,PID:2868
C:\Users\Administrator>curl localhost:3000
worker4,PID:2868
C:\Users\Administrator>curl localhost:3000
worker4,PID:2868
C:\Users\Administrator>curl localhost:3000
worker4,PID:2868
私たちはclusterのwinにおけるbugを発見しました.思い切ってLinuxテストに切り替えます.7.clusterで負荷の均衡を実現する--uuntu成功
Linuxのシステム環境
~ cd :/home/conan/nodejs/
~ mkdir nodejs-cluster && cd nodejs-cluster
~ vi server.js
var cluster = require('cluster');
var http = require('http');
var numCPUs = require('os').cpus().length;
if (cluster.isMaster) {
console.log('[master] ' + "start master...");
for (var i = 0; i < numCPUs; i++) {
cluster.fork();
}
cluster.on('listening', function (worker, address) {
console.log('[master] ' + 'listening: worker' + worker.id + ',pid:' + worker.process.pid + ', Address:' + address.address + ":" + address.port);
});
} else if (cluster.isWorker) {
console.log('[worker] ' + "start worker ..." + cluster.worker.id);
http.createServer(function (req, res) {
console.log('worker'+cluster.worker.id);
res.end('worker'+cluster.worker.id+',PID:'+process.pid);
}).listen(3000);
}
サーバを起動
conan@conan-deskop:~/nodejs/nodejs-cluster$ node server.js
[master] start master...
[worker] start worker ...1
[master] listening: worker1,pid:2925, Address:0.0.0.0:3000
[worker] start worker ...3
[master] listening: worker3,pid:2931, Address:0.0.0.0:3000
[worker] start worker ...4
[master] listening: worker4,pid:2932, Address:0.0.0.0:3000
[worker] start worker ...2
[master] listening: worker2,pid:2930, Address:0.0.0.0:3000
worker4
worker2
worker1
worker3
worker4
worker2
worker1
curlツールでアクセスする
C:\Users\Administrator>curl 192.168.1.20:3000
worker4,PID:2932
C:\Users\Administrator>curl 192.168.1.20:3000
worker2,PID:2930
C:\Users\Administrator>curl 192.168.1.20:3000
worker1,PID:2925
C:\Users\Administrator>curl 192.168.1.20:3000
worker3,PID:2931
C:\Users\Administrator>curl 192.168.1.20:3000
worker4,PID:2932
C:\Users\Administrator>curl 192.168.1.20:3000
worker2,PID:2930
C:\Users\Administrator>curl 192.168.1.20:3000
worker1,PID:2925
Linux環境では、clusterが正しく動作します!!8.cluster負荷バランス戦略のテスト
私達はLinuxの下でテストを完成しました.テストソフトを使ったことがあります.
インストール
~ sudo apt-get install siege
node clusterを起動します~ node server.js > server.log
siege起動コマンドを実行して、毎秒50個の同時要求を行います.
~ sudo siege -c 50 http://localhost:3000
HTTP/1.1 200 0.00 secs: 16 bytes ==> /
HTTP/1.1 200 0.00 secs: 16 bytes ==> /
HTTP/1.1 200 0.00 secs: 16 bytes ==> /
HTTP/1.1 200 0.01 secs: 16 bytes ==> /
HTTP/1.1 200 0.00 secs: 16 bytes ==> /
HTTP/1.1 200 0.00 secs: 16 bytes ==> /
HTTP/1.1 200 0.00 secs: 16 bytes ==> /
HTTP/1.1 200 0.01 secs: 16 bytes ==> /
HTTP/1.1 200 0.00 secs: 16 bytes ==> /
HTTP/1.1 200 0.00 secs: 16 bytes ==> /
HTTP/1.1 200 0.00 secs: 16 bytes ==> /
HTTP/1.1 200 0.02 secs: 16 bytes ==> /
HTTP/1.1 200 0.00 secs: 16 bytes ==> /
HTTP/1.1 200 0.02 secs: 16 bytes ==> /
HTTP/1.1 200 0.01 secs: 16 bytes ==> /
HTTP/1.1 200 0.01 secs: 16 bytes ==> /
.....
^C
Lifting the server siege... done. Transactions: 3760 hits
Availability: 100.00 %
Elapsed time: 39.66 secs
Data transferred: 0.06 MB
Response time: 0.01 secs
Transaction rate: 94.81 trans/sec
Throughput: 0.00 MB/sec
Concurrency: 1.24
Successful transactions: 3760
Failed transactions: 0
Longest transaction: 0.20
Shortest transaction: 0.00
FILE: /var/siege.log
You can disable this annoying message by editing
the .siegerc file in your home directory; change
the directive 'show-logfile' to false.
私たちは3760回の要求を実行して、39.66秒を消費して、毎秒94.81回の要求を処理します.server.logファイルを表示します.
~ ls -l
total 64
-rw-rw-r-- 1 conan conan 756 9 28 15:48 server.js
-rw-rw-r-- 1 conan conan 50313 9 28 16:26 server.log
~ tail server.log
worker4
worker1
worker2
worker4
worker1
worker2
worker4
worker3
worker2
worker1
最後に、R言語で分析してみます.server.log
~ R
> df<-read.table(file="server.log",skip=9,header=FALSE)
> summary(df)
V1
worker1:1559
worker2:1579
worker3:1570
worker4:1535
私たちは、要求がワーカーのデータ量に相当することを見ました.したがって、clusterの負荷バランスの戦略は、ランダムに割り当てられるべきです.はい、私たちはまた有用な技能を学びました.clusterを利用してマルチ核応用を構築し、マルチCPUのキャリア性能を十分に活用しましょう.
転載は出典を明記してください.http://blog.fens.me/nodejs-core-cluster/