Socket.io 在 Node.js + Redis + Heroku(多个测功机)环境中发出并不总是收到

Posted

技术标签:

【中文标题】Socket.io 在 Node.js + Redis + Heroku(多个测功机)环境中发出并不总是收到【英文标题】:Socket.io emits not always recieved on Node.js + Redis + Heroku (multiple dynos) environment 【发布时间】:2014-02-23 11:47:43 【问题描述】:

环境语境

我们正在 Heroku 上运行带有 Socket.io v0.9.16Node.js v0.10.25 应用程序。我们使用redis v2.6,更具体地说是Heroku 附加组件“redis to go”,作为套接字存储。我们目前正在运行两个测功机。

问题

问题是通过xhr-polling 的套接字连接被发送到一个套接字,但并不总是在同一个套接字上接收。一个例子:

我们在服务器端发出心跳。 我们并不总是收到客户端的响应。

服务器端代码

var app = require('express')()
      , server = require('http').createServer(app)
      , io = require('socket.io').listen(server);
    server.listen(3001);

    var RedisStore  = require('socket.io/lib/stores/redis')
    var redis       = require('redis')

    var rtg         = require("url").parse(FULL_REDIS_PATH);
    var hostname    = rtg.hostname;
    var database    = rtg.auth.split(":")[0];
    var portRedis   = rtg.port;
    var password    = rtg.auth.split(":")[1];

    var pub         = redis.createClient(portRedis, hostname)
    var sub         = redis.createClient(portRedis, hostname)
    var client      = redis.createClient(portRedis, hostname)

    pub.auth(password, function (err)  if (err) throw err; );
    sub.auth(password, function (err)  if (err) throw err; );
    client.auth(password, function (err)  if (err) throw err; );

    /** Initialize RedisStore for socket.io **/
    io.set('store', new RedisStore(
      redis    : redis
    , redisPub : pub
    , redisSub : sub
    , redisClient : client
    ));

    /** Configuration Settings for socket.io **/
    io.set('log level', 1);
    io.set('transports', ['flashsocket','xhr-polling']);
    io.set('polling duration', 10);

    io.sockets.on('connection', function (socket) 

        /** Associate Client ID to Socket ID **/
        client.set('client-'+client_id,socket.id, function(err)
                if (err) throw err;
                console.log("User " + client_id + " socket is now... " + socket.id);
                /**
                * Retrieve the Socket ID by the User's ID
                * Send a socket.emit message based on the Socket ID retrieved from Redis.
                **/
                client.get('client-'+client_id,function(err, response)
                    socketId = response;
                    io.sockets.socket(socketId).emit('response',user_id: client_id);
                    console.log('Retrieving User ' + client_id + ' - socket is now... ' + socket.id);
            );
        );
    );

客户端代码

<script src="http://localhost:3001/socket.io/socket.io.js"></script>
<script>
        var socket = io.connect('http://localhost:3001');

        socket.on('response', function (data) 
            console.log(data);
        );
</script>

对此的任何帮助将不胜感激,在此先感谢!

【问题讨论】:

遇到贵妇问题,已经解决了一段时间。你试过socket.io-clusterhub吗?我在redisStore之前试过了,还是不行,如果redisStore不行再试试。 【参考方案1】:

如果“我们目前有两个 dynos 正在运行”。你的意思是你的服务器有两个实例,通过 redis pub/sub 进行通信,那么这应该是你想要的:http://socket.io/docs/using-multiple-nodes/

【讨论】:

以上是关于Socket.io 在 Node.js + Redis + Heroku(多个测功机)环境中发出并不总是收到的主要内容,如果未能解决你的问题,请参考以下文章

Node.js 和 socket.io 的混淆

Node.js - Socket.io:socket.request 未定义

找不到Node.js /socket.io/socket.io.js express 4.0

node.js + socket.io:拍卖网站开发

Node.js + Socket.io 在套接字中存储数据

Node.js socket.io.js 未找到或 io 未定义