NodeJS / SocketIO消息无法可靠地传递

时间:2016-03-02 05:03:01

标签: node.js socket.io load-balancing

我在NodeJS / SocketIO开发中遇到了非常奇怪的行为,我只是不知道是什么导致了我的问题。在我们的代码中,我几乎无处可寻,但找不到任何可能导致此问题的明显问题。最后,我有一个网络人员建议它可能与NodeJS服务器上的负载平衡有关。我不确定这是否属实,但我想我会告诉你们这些问题,看看你们是否有任何建议。

我们运行NodeJS / SocketIO应用程序,基本上允许我们基于Web的管理应用程序监控我们网站上用户的连接。实际上,它应该做的就是接收传入消息并重新格式化消息,然后将它们重新广播到所有客户端(实时是我们所有的基于Web的管理员)。基本上它就像这样......

  • 用户(通过我们的某个网站)连接到NodeJS / SocketIO
    服务器和网站向NodeJS / SocketIO服务器发送消息 发生了连接。

  • NodeJS / SocketIO应用程序将一条简短消息记录到控制台以告知
    我们建立了联系。

  • 然后,NodeJS / SocketIO应用程序重新格式化消息并发出该消息 发送给所有连接的消息。

  • 该消息包含NodeJS / SocketIO应用程序收到的数据 来自用户ip的连接。

  • 然后,基于Web的管理员会收到该消息并更新它的视图 显示所有当前连接的列表。

  • 当用户断开连接时,NodeJS / SocketIO应用会发送新消息 对于用户已断开连接且基于Web的所有客户端 管理员会收到这些消息,然后更新他们的观点。

我的问题是,当我在一台IP上的一台PC上运行基于Web的管理员实例时,在另一台PC和另一台IP上运行同一个基于Web的管理员的另一个实例 - 两者同时 - 他们大多数看不到相同的流量。几乎在每种情况下,来自用户的连接都显示在一个或另一个基于Web的管理实例中,但很少会出现连接,正如我所期望的那样。似乎来自NodeJS / SocketIO的几乎所有消息都是由一个基于Web的管理员接收的,而不是另一个,即使他们都应该正在收听和接收相同的消息。我设计了代码,以便当NodeJS / SocketIO收到连接时,它会向正在侦听的所有客户端广播新的连接消息,这些客户端应包括基于Web的管理员,并且两个基于Web的管理实例都应该看到所有传入的连接并更新他们的视图匹配。但是,这并没有发生。这些消息几乎总是由基于Web的管理员的一个实例接收,而不是另一个。

奇怪的是,当我在2台不同的PC上运行2个基于Web的管理员实例但是在同一个IP上时,这些消息在两个基于Web的管理员中都被正确接收和处理。正如我所料,如果两个基于Web的管理员都在不同的IP上运行。

我们的网络人员建议它可能与NodeJS服务器上的负载平衡有关。他建议,当基于Web的管理实例连接到NodeJS服务器时,它只能看到NodeJS服务器的一个实例,因此无法看到可能进入NodeJS服务器的另一个实例的所有连接。

服务器上运行的NodeJS / SocketIO应用程序如下所示......

var app = require('express')();

var http = require('http').Server(app);

var io = require('socket.io')(http);

http.listen(process.env.PORT, function(){
  console.log('listening on PORT:' + process.env.PORT);
});

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

// Report a new connection and where it came from
var client_ip_address = socket.handshake.headers['x-forwarded-for'] ||    socket.request.socket.remoteAddress;
console.log("Connection from:" + client_ip_address);

socket.on('disconnect', function () {
    emitMessageToAll({type: "disconnect", ip: client_ip_address, senderID: socket.id});
});

// After a new user connects, we wait for them to emit to us the website they are currently on before notifying all users (Admin)
// Of the new connection. That way Admin can filter users by what site & page they are currently on. 
socket.on('newConnectionInfo',function(data){   
    console.log("User reports connection data: " + data.IP);    
    emitMessageToAll({type: "newConnection", ip: data.IP, url: data.url, senderID: socket.id});
});

socket.on('newBooking',function(data){  
    console.log("User reports new booking: " + data.IP);    
    emitMessageToAll({type: "newBooking", ip: data.IP,PurchDate: data.PurchDate, Surname: data.Surname});
});
});

function emitMessageToAll(data){
    io.emit('message',data);
    console.log("Sending:");
    console.log(data);
} 

无论如何,我对这可能导致问题的原因感到十分困惑,你能否提出任何可能导致这种奇怪行为的想法?是否可能是负载平衡问题或服务器相关问题?

1 个答案:

答案 0 :(得分:0)

因此,我的答案是服务器的负载平衡允许我们的NodeJS / SocketIO应用程序的多个实例运行。我们最多同时运行3个实例,这导致一些连接通过实例1路由,一些连接通过实例2,其他连接通过实例3.一旦NodeJS / SocketIO应用程序的其他实例关闭,问题就解决了。