REDISなしのクラスター+ EXPRESS + socket.io

socket.ioライブラリがとても気に入りました。 これにより、リアルタイムアプリケーションを簡単に実装できます。 彼女自身がブラウザに応じてプロトコルを選択し、必要に応じてWebSocketを作成します。



もちろん、これはすべて良いですが、Node.jsが1つのスレッドで機能することを忘れないでください。 このために、素晴らしいClusetツールがあります。



私の前に疑問が生じました。クラスタリングを使用してアプリケーションを作成することはできますが、このためにREDISを使用することはできませんか? また、便宜上、EXPRESSを使用します。



簡単な例を作成してみましょう(これまでのところクラスターはありません): 公式ドキュメントの例:



var app = require('express')(); var server = require('http').Server(app); var io = require('socket.io')(server); server.listen(3038); app.get('/', function (req, res) { res.sendfile(__dirname + '/index.html'); }); io.on('connection', function (socket) { socket.emit('news', { hello: 'world' }); socket.on('my other event', function (data) { console.log(data); }); });
      
      





これまでのところ、複雑なことは何もなく、すべてが明確です。エクスプレスとsoket.ioを使用して、ポート3038でサーバーを停止します。 クライアントコードは変更されません。



 <html> <head> <title>Test socket.io</title> <script src="socket.io.js"></script> <script> var connect_error_count = 0; var socket = io.connect('http://localhost:3038/', { 'reconnectionDelay': 10 // defaults to 500 } ); socket.on('connect_error', function(){ console.log('Connection Failed'); //  5  ,    connect_error_count++; if (connect_error_count>=5){ socket.disconnect(); console.log("stop reconection"); } }); socket.on('reconnect', function(){ console.log('reconnect'); connect_error_count=0; }); socket.on('news', function (data) { console.log(data); }); </script> </head> <body> </body> </html>
      
      





クライアントコードに関する簡単な説明。 設定(ポート3038、接続タイムアウト10ミリ秒)でソケットオブジェクトを作成します。 接続エラーが5回を超える場合は、ソケットを無効にし、少ない場合は、カウンターをリセットします。 また、ニュースルームに接続します。



次のステップは、クラスターを作成することです。 なぜなら 1つのポートにソケットを作成することはできません。その場合、新しいワーカーはそれぞれ新しいポートにsocket.ioを作成します。



 var cluster = require('cluster');// cluster var cpuCount = require('os').cpus().length;//   var io = []; //   worker'     if (cluster.isMaster) { for (var i = 0; i < cpuCount; i += 1) { var worker = cluster.fork(); } } //  if (cluster.isWorker) { var worker_id = cluster.worker.id; var express = require('express'); var app = express(); var server = require('http').Server(app); io[worker_id] = require('socket.io')(server); server.listen(3030+worker_id); io[worker_id].on('connection', function (socket) { console.log( socket.id ); console.log( "WORKER ID :"+worker_id ); socket.emit('news', { hello: 'world' }); socket.on('my other event', function (data) { console.log(data); }); }); var app_express = express(); app_express.listen(8081); app_express.use(express.static('public'));//   (.  ) app_express.get('/', function (request, response) { response.send('Hello from Worker '+worker_id); console.log( '------' ); }); app_express.get('/get_port', function (request, response) { response.send(3030+worker_id); console.log( 'get_port' ); }); } app_express.get('/api', function (request, response) { response.setHeader('Content-Type', 'application/json'); var id = request.param('id'); var msg = request.param('msg'); var port = request.param('port'); var JSON_DATA = { "worker_id":worker_id ,"id":id ,"msg":msg ,"port":port }; });
      
      





すべてがどのように見えるかを概略的に示します。



画像



ブラウザでlocalhost:8081を開くと、クラスターはそのルールに従ってワーカーでサービスを提供します。 電話があります:



 app_express.get('/api', function (request, response){...}
      
      





この呼び出しで、localhost:8081 / api?Msg = test&port = 3032&id = 100500を開くとき、ポート3032 id = 100500で接続されたクライアントにmsg = teestのメッセージを送信します。



最も簡単な方法:クライアントを作成し、特定のポートでsocket.ioを開きます。



 var http = require('http'); var client = http.createClient(3032 , "localhost"); request = client.request(); request.on('response', function( res ) { res.on('data', function( data ) { console.log( data ); } ); } ); request.end();
      
      





しかし、たとえば、ブロードキャストメッセージを送信する必要があり、クライアントがサービスを提供しているポートがわかりません。 問題はこれです:localhost:8081 / apiを開いたときに、メッセージ=テスト&ポート= 3032&id = 100500、ワーカー2で提供されることを確実に知りません。



画像



図は、worker1でブロードキャストメッセージを送信する場合、クライアントに直接送信できないことを示していますsocket.io 2、socket.io 3、socket.io 4、socket.io ...



この問題を解決するために、クラスター内のメソッドを使用できます。 cluster'eでは、master→workerとworker→masterからメッセージを送信できます。 明確にするために、これを概略的に示します。



画像



送信マスター→ワーカーおよびワーカー→マスターを使用した作業の例を以下に示します。



 //   var cluster = require('cluster'); var io = []; var cpuCount = require('os').cpus().length; var workers = []; if (cluster.isMaster) { // Count the machine's CPUs // Create a worker for each CPU for (var i = 0; i < cpuCount; i += 1) { var worker = cluster.fork(); //   workera worker.on('message', function(data) { //  worker'  for (var j in workers) {workers[j].send(data);} }); //  worker   workers.push(worker); } } if (cluster.isWorker) { //------------------------------------------------------------------------------------// var worker_id = cluster.worker.id; var express = require('express'); var app = express(); var server = require('http').Server(app); io[worker_id] = require('socket.io')(server); server.listen(3030+worker_id); io[worker_id].on('connection', function (socket) { console.log( socket.id ); console.log( "WORKER ID :"+worker_id ); socket.emit('news', { hello: 'world' }); socket.on('my other event', function (data) { console.log(data); }); }); //------------------------------------------------------------------------------------// var app_express = express(); app_express.listen(8081); app_express.use(express.static('public'));//   app_express.get('/', function (request, response) { response.send('Hello from Worker '+worker_id); console.log( '------' ); }); app_express.get('/get_port', function (request, response) { response.send(3030+worker_id); console.log( 'get_port' ); }); app_express.get('/api', function (request, response) { //process.send("----------------------"); response.setHeader('Content-Type', 'application/json'); var id = request.param('id'); var msg = request.param('msg'); var JSON_DATA = { "worker_id":worker_id ,"id":id ,"msg":msg }; io[port-3030].to(msg.id).emit('news', msg.msg); response.send( JSON.stringify(JSON_DATA) ); //    process.send(JSON_DATA); }); //   worker// process.on('message', function(msg){ console.log(worker_id); console.log(msg.id); console.log(msg.msg); io[worker_id].to(msg.id).emit('news', msg.msg); }); }
      
      





この記事が、クラスターと、マスター→ワーカーとワーカー→マスターとの間のコミュニケーションに精通したい初心者に役立つことを願っています。 socket.ioの簡単なレビュー。 そして最も重要なこととして、redisは使用されません。



All Articles