我已经构建了一个WebSockets
服务器,它充当聊天消息路由器(即接收来自客户端的消息,并根据客户端ID
将其推送给其他客户端)。
要求服务能够扩展以处理数百万个并发的开放套接字连接,我希望能够水平扩展服务器。
我想到的体系结构是将websocket服务器节点放在负载均衡器后面,这会产生问题,因为连接到不同节点的客户端不会相互了解。当客户端A
和B
都通过LoadBalancer
进入时,客户端A
可能与节点1
有开放连接,而客户端B
连接到节点2
——每个节点都有自己的开放套接字连接字典。
为了解决这个问题,我考虑使用一些MQ系统,如ZeroMQ
或RabbitMQ
。所有websocket服务器节点都将是MQ服务器的订阅者,当节点收到将消息路由到不在本地连接字典中的客户端的请求时,它将pub
-lish向MQ服务器发送一条消息,MQ服务器将告诉所有sub
描述符节点查找该客户端,并在该客户端连接到该节点时发出该消息。
Q1:
这种体系结构有意义吗?
Q2:
这里描述的pub-sub
模式真的是我想要的吗?
ZeroMQ将是我的选择-无论是架构方面还是;性能方面
--快速&低延迟(可以衡量您的实现性能和开销,低至子级别)
--无代理(不引入另一个故障点,而其本身可以具有{N+1|N+M}自修复架构)
--smart准备使用的正式通信模式基元(PUB
/SUB
是最不重要的基元)
--公平队列&负载平衡架构内置(外部观察者不可见)
--许多用于服务器端内部多进程/多线程分布式/并行处理的传输类
--准备几乎线性可扩展性
自适应节点重新发现
这是一个比较复杂的问题。您想要创建一个可行的体系结构,必须深入了解更多细节才能解决。
- 节点身份验证与对等消息
- 节点(重新)-发现与法律&隐私问题
- 基于节点的自主自组织代理与中央策略实施需求
为了在2021年更新这一点,我们刚刚解决了这个问题,我们需要设计一个能够处理来自物联网设备的数百万个同时WS连接的系统。WS服务器只是将消息中继到处理实际逻辑的无服务器API后端。我们选择使用docker和节点ws
包,使用前面有ALB的自动缩放AWS ECS Fargate集群。
这解决了路由消息的主要问题,但随后我们遇到了同样的问题,即如何从服务器路由响应消息。我们最初只考虑保留一个连接的中央数据库,但将消息路由到ALB后面的特定Fargate实例似乎不可行。
相反,我们使用AWS SNS设置了一个简单的sub/pub模式(https://aws.amazon.com/pub-sub-messaging/)。每个WS服务器接收响应,然后搜索其自己的WS连接。由于每个Fargate实例只处理路由(没有逻辑),所以当我们垂直扩展它们时,它们可以处理很多连接。
更新:为了提高性能,您可以使用Redis-Pub/Sub等持久连接,允许响应消息只发送到一台服务器,而不是每个服务器。