3

ソケット IO サーバーは、NodeJ の単一インスタンスで正常に動作しています。しかし、NodeJS のクラスター モジュールを使用して複数のコアでサーバーを実行すると、「ハンドシェイク応答を受信する前に接続が閉じられました」というエラーが表示されます。その理由をググってみたところ、

問題の本質は、サーバーまたは複数のサーバーで複数の Node アプリ スレッド (ワーカー) を実行すると、socket.io クライアント接続がクラスターによってランダムなラウンドロビン方式でルーティングされ、ハンドシェイク/承認された io クライアント リクエストが処理されることです。混乱が始まる場所で、握手/承認されていない労働者に。 ソースリンク

私はそれを機能させるためにいくつかのことを試みましたが、これまでのところ成功していません。これがコードです

'use strict';

process.env.NODE_ENV = process.env.NODE_ENV || 'development';

var express = require('express');
var config = require('./config/environment');
var session = require('express-session');
var redisStore = require('connect-redis')(session);
var cluster = require('cluster');
var domain = require('domain');
var socketIo = require('./config/socketio');
var REDIS = require('redis')

var store = REDIS.createClient();
var pub = REDIS.createClient();
var sub = REDIS.createClient();


if(cluster.isMaster) {
    var numWorkers = require('os').cpus().length;

for(var i = 0; i < numWorkers; i++) {
    cluster.fork();
}

} else {
    var d = domain.create ();
    d.on ("error", function (error){
     // start new server
    });

// Setup server
var app = express();
var server = require('http');

  d.run (function (){
    server = server.createServer(app);
  });

require('./config/express')(app);
require('./config/redis')();
require('./routes')(app);

server.listen(config.port, config.ip, function () {
  console.log('Express server listening on %d, in %s mode', config.port, app.get('env'));
});


var redis = require('socket.io-redis');

var socketIO = require('socket.io')(server, {
  serveClient: (config.env === 'production') ? false : true,
  path: '/socket.io-client'
});

sub.subscribe('chat');
socketIO.adapter(redis( {host: 'localhost', port: 6379}));
socketIo.createSocketConnection('/dummy', socketIO, sub, pub, store);

exports = module.exports = app;
}

ファイル: ./config/socketio

'use strict';

function addNamespaceForId (socketio, namespace, sub, pub, store){

    socketio.of(namespace).on('connection', function(socket) {

        onConnect(socketio, socket, namespace, sub, pub, store);

        console.info('[%s] CONNECTED', socket.address);

         sub.on('message', function(pattern, key){
             store.hgetall(key, function(e, obj){
                 socket.send(obj.uid + ": " + obj.text)
            })
        })


        socket.on('disconnect', function() {
            console.info('[%s] DISCONNECTED', socket.address);
        });
    });
}
}


function onConnect(io, socket, namespace, sub, pub, store) {
socket.on('message', function(from, msg) {

    store.incr("messageNextId", function(e, id){
        store.hmset("messages:" + id, { uid: socket.sessionId, text: 'text;'     }, function(e, r){
            pub.publish("chat", "messages:" + id)
        })
    })

    io.emit('broadcast', {
        payload : from['message'],
        source : from
    });
    io.of(namespace).emit('broadcast', {
        payload : from['message'],
        source : from
    });
});

// When the client emits 'info', this listens and executes
socket.on('info', function(data) {
    console.info('[%s] %s', socket.address, JSON.stringify(data, null, 2));
});

// Insert sockets below
require('../api/thing/thing.socket').register(socket);
}

module.exports = {
    createSocketConnection : function (namespace, socketio, sub, pub, store){
    addNamespaceForId(socketio, namespace, sub, pub, store);
    }
};

ドキュメントで提案されているように、redis用のアダプターも使用してみました

このセットアップは時々機能しますが、常に機能するとは限りません。欠けている点がわかりません。

4

0 に答える 0