socket.io 如何跨多个服务器发送消息?

Posted

技术标签:

【中文标题】socket.io 如何跨多个服务器发送消息?【英文标题】:How does socket.io send messages across multiple servers? 【发布时间】:2013-06-30 04:18:04 【问题描述】:

Socket.io API 能够向所有客户端发送消息。

对于一台服务器和内存中的所有套接字,我了解该服务器如何向其所有客户端发送消息,这很明显。但是如果多个服务器使用Redis 来存储套接字呢?

如果我有客户端 a 连接到服务器 y 并且客户端 b 连接到服务器 z(以及Redis box for store)我在一台服务器上做socket.broadcast.emit,另一台服务器上的客户端会收到这个消息。怎么样?

实际连接到另一台服务器的客户端如何获得该消息?

一台服务器是否告诉另一台服务器向其连接的客户端发送消息? 服务器是否与客户端建立了自己的连接以发送该消息?

【问题讨论】:

【参考方案1】:

Socket.io 默认使用 MemoryStore,因此所有连接的客户端都将存储在内存中,从而无法(嗯,不是安静,但稍后会详细介绍)从连接到不同 socket.io 服务器的客户端发送和接收事件.

让所有socket.io服务器接收所有事件的一种方法是所有服务器都使用redis的pub-sub。因此,可以改为使用 socket.emit 发布到 redis。

redis_client = require('redis').createClient();
redis_client.publish('channelName', data);

所有套接字服务器通过 redis 订阅该通道,并在收到消息后将其发送给连接到它们的客户端。

redis_sub = require('redis').createClient();
redis_sub.subscribe('channelName', 'moreChannels');

redis_sub.on("message", function (channel, message)         
    socket.emit(channel, message);
);

复杂的东西!!但是等等,事实证明你实际上并不需要这种代码来实现目标。 Socket.io 有 RedisStore,它基本上以更好的方式完成了上面的代码应该做的事情,这样您就可以像为单个服务器编写一样编写 Socket.io 代码,并且仍然会传播到其他 socket.io 服务器通过redis。

总结socket.io通过使用redis作为通道而不是内存来跨多个服务器发送消息。

【讨论】:

完美,正是我想要的!【参考方案2】:

有几种方法可以做到这一点。更多信息in this question。 here, in Redis' docs 很好地解释了 Redis 中的 pub/sub 是如何工作的。 here, on Wikipedia 解释了范式的一般工作原理。

引用 Redis 文档:

SUBSCRIBE、UNSUBSCRIBE 和 PUBLISH 实现发布/订阅 (引用***)发件人(发布者)所在的消息传递范式 没有编程将他们的消息发送给特定的接收者 (订户)。相反,发布的消息被描述为 频道,不知道可能有什么(如果有的话)订阅者。 订阅者对一个或多个频道表示兴趣,并且只收到 感兴趣的消息,但不知道是什么(如果有的话) 出版商有。这种发布者和订阅者的脱钩 可以实现更大的可扩展性和更动态的网络拓扑。

【讨论】:

花了我一些时间来破译这是如何回答我的问题的,但是在用这些信息重新阅读文档后,我意识到幕后发生的事情是 socket.io 正在使用 redis pubsub 来发布和订阅其他服务器客户端和它自己的消息

以上是关于socket.io 如何跨多个服务器发送消息?的主要内容,如果未能解决你的问题,请参考以下文章

使用 (socket.io + RedisStore) 跨多个服务器进行通信

使用 socket.io 防止向多个房间发送消息

当套接字重新连接时,如何让 socket.io 服务器向特定套接字重新发送消息?

Kubernetes 中的 Socket.IO 集群,多个节点未发送给所有客户端

向 Socket.io 中的其他房间发送消息

PHP 向 Node / Socket.IO 服务器发送消息