2016-02-10 1 views
5

質問要求:私はこの解決策に過ぎないが、私は必要な方法で動作しているようです見つけることを試みたhttps://stackoverflow.com/a/18650183/4478897socket.io + Redisの+ expressjsクラスタ - expressjsにソケットオブジェクトを取得し、この回答に基づいて

を。

クラスタリングexpressjssocket.io我々は(... io.sockets.on('connection',)のRedisを使ってセッションを共有し、io世界の内側ioメッセージを送ることができます。問題は、expressjsの世界(route.get/post)内にメッセージを送信する(または単純なsocket.join/leaveを使用する)場合です。

我々は急行requestオブジェクト(または単にexportioオブジェクト)にクライアントsocketオブジェクトをatachし、任意のGET/POSTルート上の任意の時点でそれを使用することができ、クラスタを使用していない場合。我々はクラスタリングとexpressjs世界内側socketオブジェクトを取得するような方法を使用している場合は、このクライアントのsocketオブジェクトが他のworkerで初期化されるので、一方では

は、時々 socketオブジェクトが定義されていません。

いくつかの例の流れ:

  • クライアントがhttp://localhostに接続し、worker 1がこの要求を処理します。
  • ページがロードされた後、クライアントはsocket.ioに接続します。 Worker 2がこの接続を処理します。
  • クライアントはPOSTを実行し、もう一度worker 1またはworker Xがこの要求を処理します。

この場合、クライアントがPOSTを実行する場合、worker 2のみがこのクライアントのsocketオブジェクトを認識します。したがって、これは未定義のsocketオブジェクトを取得します。

だから、質問:

がどのように我々はexpressjs requestオブジェクト上でそれを再利用するために、任意のworkerからクライアントsocketオブジェクトを取得することができます。

多分私のコードは間違っていますが、上記の答えへのリンクに似ています。


ノート

  • は、プロキシのいくつかの種類を使用する必要はありません。
  • 他のライブラリ(sockjs方法、式...)に移行したくない
  • 私の英語のため申し訳ありません
  • :)最後nodejsを使用して

、socket.io、expressjs、socket.io-赤、赤...バージョン

何かお気軽にお問い合わせください!


UPDATE 1

解決策が、まだそれをテストする必要があります。これが本当に良いのか分かりません:解決策。

  • UPDATE 3:更新1と同様に、私自身の答え

UPDATE 2

上のコードの作業が、https://nodejs.org/dist/latest-v5.x/docs/api/cluster.html#cluster_event_message

答えて

-1

(まあ最終的には、コードを試してみましたし、それが動作を使用していくつかのミススペルの修正や他のものがありますが)どこかでより良いコードにする必要があると確信しています。だから私はより多くの答えに公開されています!

このコードは...クライアントソケットといくつかの他のものを認可する私のsocket.ioモジュールの一部である

var redis = require("redis"); 
    var redisPub = redis.createClient(); 
    var redisSub = redis.createClient(); 
    var PubSubChannel = "clusterChannel"; 

    // Function that checks if this worker knows the socket object of this socketId. 
    // If not, publish the message to all the other sockets (workers) 
    io.socketDo = function (type, socketId, roomName) { 
    if (typeof io.sockets.connected[socketId] != "undefined") { 
     if (type === "join") { 
     return io.sockets.connected[socketId].join(roomName); 
     } 
     if (type === "leave") { 
     return io.sockets.connected[socketId].leave(roomName); 
     } 
    } else { 
     redisPub.publish(
     PubSubChannel, 
     JSON.stringify({ 
      type: type, 
      socketId: '' + socketId, 
      roomName: roomName 
     }) 
    ); 
    } 
    }; 

    // Subscribe to some channel 
    redisSub.subscribe(PubSubChannel); 

    // When this worker receive a message from channel "PubSubChannel" checks 
    // if it have the socket object for this socketId and do the operation 
    redisSub.on("message", function (channel, data) { 
    data = JSON.parse(data); 
    var type = data.type; 
    var socketId = data.socketId; 
    var roomName = data.roomName; 
    if ((type === "join" || type === "leave") && channel == PubSubChannel){ 
     if (typeof io.sockets.connected[socketId] != "undefined") { 
     if (type === "join") { 
      return io.sockets.connected[socketId].join(roomName); 
     } 
     if (type === "leave") { 
      return io.sockets.connected[socketId].leave(roomName); 
     } 
     } 
    } 
    }); 

その後、単にモジュールをエクスポートして、あなたのexpressjsに添付request => req.io = io

// req.session.socketId value is fetched on "io.sockets.on('connection', function(socket) {" 
// by express to socket.io using redis shared sessions 
app.get('/', function (req, res) { 
    req.io.socketDo('join', req.session.socketId, 'someRoomToJoin'); 

    // IT WORKS! 
    req.io.sockets.in('someRoomToJoin').emit('text'); 

    req.io.socketDo('leave', req.session.socketId, 'someRoomToLeave'); 
    res.send('Hello World!'); 
}); 
1

remoteJoinremoteLeave方法はsocket.io-Redisの3.0.0に添加した:

io.adapter.remoteJoin('<my-id>', 'room1', function (err) { 
    if (err) { /* unknown id */ } 
    // success 
}); 

io.adapter.remoteLeave('<my-id>', 'room1', function (err) { 
    if (err) { /* unknown id */ } 
    // success 
}); 

注:実装は答えaboveようにたくさんの(?たぶん)に見えます。

+0

私は、マージを見ました。とにかくありがとう:D – nada

関連する問題