多台机器上的 Node.js tcp 套接字服务器
Posted
技术标签:
【中文标题】多台机器上的 Node.js tcp 套接字服务器【英文标题】:Node.js tcp socket server on multiple machines 【发布时间】:2011-11-24 19:50:52 【问题描述】:我有一个 node.js tcp 服务器,用作 iPhone 聊天客户端的后端。由于我的实现包括私人群聊,我将用户列表和他们所属的聊天室存储在内存中,以便适当地路由消息。假设我的聊天服务器总是在一台机器上,这一切都很好,但是当/如果我需要水平扩展时,我需要一种向连接到不同服务器的客户端广播消息的好方法。我不想开始在节点服务器之间进行进程间通信,并且更喜欢与 redis 共享状态。
我有一些想法,但我想知道是否有人对此有好的解决方案?这里要清楚的是一个例子:
用户 1 连接到房间 X 上的服务器 1,用户 2 连接到房间 X 上的服务器 2。用户 1 发送一条消息,我需要将它传递给用户 2,但由于我使用的是内存数据结构服务器不共享状态。我希望我的节点服务器尽可能保持低调,这样我就可以根据系统的需要添加/删除。
谢谢:)
【问题讨论】:
【参考方案1】:您可以使用跨进程的消息传递层(使用诸如 pub/sub 之类的东西):
Message Queue
-------------------------------------------------------------------------------
| |
ServerA ServerB
------- -------
Room 1: User1, User2 Room 1: User3, User5
Room 2: User4, User7, User11 Room 2: User6, User8
Room 3: User9, User13 Room 3: User10, User12, User14
假设 User1 发送了一条聊天消息。 ServerA 在消息队列上发送一条消息,上面写着“房间 1 中的用户 1 说了一些话”(以及他们所说的任何内容)。您的每个其他服务器进程都在监听此类事件,因此,在此示例中,ServerB 将看到它需要将来自 User1 的消息分发给其 自己的 Room 1 中的所有用户。您可以扩展到许多以这种方式处理进程——每个新进程只需要确保它们侦听队列中的适当消息。
Redis 有pub/sub functionality,如果您已经在使用 Redis,则可以使用它。另外,还有其他第三方工具可以处理这种事情,比如ZeroMQ;另见this question。
【讨论】:
这是一个相当好的解决方案,但是消息队列将成为瓶颈,而每条消息都必须经过消息队列。通过一个小的优化,这是一个最佳实践:尽量确保同一个房间的用户都在服务器上,所以你不需要消息队列。如果房间增长并且需要拆分为一堆服务器,您需要使用消息队列。但小频道不需要它。 这需要在他的架构中进行相当多的返工——我认为他正在寻找一个节点逻辑不可见的解决方案。【参考方案2】:Redis 应该会在不久的将来内置集群支持,同时您可以使用一致的散列算法将密钥均匀地分布在多个服务器上。有人有一个 node.js 的散列模块,它是专门为 node.js 的 redis 集群模块实现一致散列而编写的。您可能想要关闭“房间”名称,以确保房间的所有数据点都位于同一主机上。通过这种类型的设置,使用哪个服务器的所有逻辑都保留在客户端上,因此您的 redis 集群基本上可以保持不变,您可以轻松添加或删除主机。
更新
我找到了我所说的 redis 的一致性哈希实现,它当然给出了代码,并且还以一种易于理解的方式解释了分片。
http://ngchi.wordpress.com/2010/08/23/towards-auto-sharding-in-your-node-js-app/
【讨论】:
现在我不必担心对我的 redis 集群进行分片。我有一个相当大的共享实例可供操作。我的问题更多在 node.js 方面。现在我将用户的套接字对象存储在内存中,这样当消息进入特定房间时,我可以拉出与该房间相关的所有套接字并写入它们。问题在于内存 ds 中的 this 不在节点实例之间共享,因此我需要某种方式来管理其他地方的状态。这有意义吗? 是的,我想我只是假设当你说你将它存储在内存中时,你的意思是数据存储在 redis 中。在这种情况下,分片仍然可以帮助你,但看起来你需要重新考虑一下架构。以上是关于多台机器上的 Node.js tcp 套接字服务器的主要内容,如果未能解决你的问题,请参考以下文章