英文:
How can I connect two Scala Servers together to share a client pool using Akka w/ Play framework for Websockets
问题
我有几个具有RESTful API的HTTP服务器和一个使用Akka和Play框架的Scala WebSocket服务器。我的移动应用程序使用Scala WebSocket(响应式)服务器进行实时更新。HTTP服务器将与Scala服务器通信,将数据推送到移动应用程序。当只有一个Scala服务器时,这非常有效,因为所有移动客户端都连接到同一个Scala服务器。但是,我想部署第二个WebSocket服务器,这会破坏流程。
Scala 1
- 客户端 1
- 客户端 2
Scala 2
- 客户端 3
- 客户端 4
HTTP 1(发送消息给客户端 3)-> 负载均衡器 -> Scala 1
Scala 1未连接到客户端 3,因此消息无法传递给客户端。
我如何将这两个Scala服务器连接起来,即使消息被Scala 1接收,Scala 2也会将消息发送给客户端 3?或者可能共享客户端池,以便Scala 1可以通过套接字向客户端发送消息,即使客户端最初连接到Scala 2?
我考虑过实现SNS,并使HTTP后端将事件推送到队列,然后使Scala后端订阅队列,但我不太喜欢这种方式,因为还有一些事件是从移动客户端发送的,我也希望两个Scala服务器都能接收到。示例:
HTTP 1(发送报价给所有客户端)-> SNS -> 两个Scala服务器广播报价给所有客户端-> 客户端 3发送接受给Scala -> Scala 2接收,取消了在Scala 2上的其他客户端的报价,Scala 1不知情,继续为连接到Scala 1上的客户端保持报价
我将不得不再次将事件发布到SNS以取消其他服务器上现有报价。这将是很多工作。
我真的需要这两个服务器像一个服务器一样运行。
英文:
I have several HTTP servers with a RESTful API and a Scala WebSocket server utilizing Akka w/ Play Framework. The Scala Websocket (reactive) server is used by my mobile apps for realtime updates. The HTTP servers will communicate with the Scala server, to push data out to the mobile apps. This works great when there is 1 scala server, because all the mobile clients are connected to the same Scala server. However, I'd like to deploy a second websocket server, and this breaks the flow.
Scala 1
- Client 1
- Client 2
Scala 2
- Client 3
- Client 4
HTTP 1 (sends message for Client 3) -> LoadBalancer -> Scala 1
Scala 1 is not connected to Client 3, so the message never makes it to the client.
How can I connect the two Scala servers together, so even if the message is received by Scala 1, Scala 2 will send the message to Client 3? Or possibly share the client pool, so Scala 1 can send the message to the client over the socket, even if the Client initially connected to Scala 2?
I thought about implementing SNS and having the HTTP backend push events to a Queue, and then having the Scala backend subscribe to the Queue, but I'm not crazy about it because there are some events sent from the Mobile Client, that I also want both Scala servers to receive as well.
Example:
HTTP 1 (Sends Offer to All Clients) -> SNS -> Both Scala Servers Broadcast Offer to All Clients -> Client 3 Sends Accept to Scala -> Scala 2 receives, cancels offers to other clients on Scala 2, Scala 1 is unaware, keeps offer open to Clients connected on Scala 1
I'd have to publish the event to SNS again to cancel existing offers on the other server. It would be a lot of work.
I really need the two servers to act as one.
答案1
得分: 1
对于这个问题,通常需要让两个服务器形成一个集群,这可以有效地被视为允许两个服务器形成一个系统(出于各种原因,通常最好至少有三个服务器在集群中)。然后,与任何服务器建立的HTTP或WebSocket连接(对于HTTP/WebSocket连接的另一端而言是透明的)可以与其他任何服务器互动。
在Akka中使用的精确的集群工具包部分将取决于具体情况。例如,如果来自HTTP的大多数消息将被发送到单个客户端,并且WebSocket客户端的数量较少(比如不超过十万个),并且可以容忍客户端偶尔错过更新,那么在集群中使用分布式发布-订阅是相当实际的:当客户端连接到WebSocket时,处理程序会生成一个Actor,该Actor订阅了与客户端相关联的唯一ID的主题。HTTP请求的处理程序请求发布到特定客户端的消息将发布到与该客户端相关联的主题。相反,如果您的HTTP消息大多是广播,并且预计接收者的数量少于客户端数量(最多约10,000个接收者),那么可以倒转这一过程:为每个允许的接收者集创建一个主题,客户端通过HTTP请求订阅相应的主题以发布消息。
如果需要消息的有保障传递,而且客户端数量可能超过数万个,而大多数消息将是点对点的,那么集群分片(以及根据您想要的保障强度是否在集群成员更改等方面需要持久性)是一个好工具:您的HTTP请求处理程序将为特定客户端的消息转发到与该客户端相关联的分片实体,您的WebSocket处理程序基本上会订阅该分片实体(您可能需要自己实现缓冲等功能:这是Akka文档所谈论的“更加自定义的解决方案”),并将来自客户端的确认转发给分片实体(这些确认从本质上来说是领域问题的一部分):请注意,在集群中的任何给定HTTP -消息-> 实体 -消息-> WebSocket -确认-> 实体消息流可能需要至少三到四个网络跃点(这取决于您是否希望对HTTP请求做出响应,以指示消息是否已明确缓冲到WebSocket客户端或否)。
英文:
In general for this, what you will want to do is have the two servers form a cluster, which can effectively be thought of as allowing the two servers to form one system (for a variety of reasons, it's generally preferable to have at least three servers in the cluster). Then an HTTP or websocket connection to any of the servers can (transparently to whatever's on the other side of the HTTP/websocket connection) interact with any of the other servers.
The exact parts of the clustering toolkit in Akka to use will depend on the particulars. For instance, if most of the messages from HTTP are going to be intended for a single client and there's a small number (say less than a hundred thousand or so) of websocket clients and it's acceptable for a client to miss the occasional update, it's reasonably practical to use distributed pub sub within the cluster: when the client connects to the websocket, the handler spawns an actor which subscribes to a topic with a unique ID associated with the client. The handler for the HTTP request asking to publish a message to a given client will then publish a message to the topic associated with that client. If, conversely, your HTTP messages are mostly broadcasts and there are expected to be fewer sets-of-recipients than there are clients (and there are at most 10k or so sets-of-recipients), then you can invert this: have a topic for each set-of-recipients that's allowed and the clients subscribe to the appropriate topics with an HTTP request publishing to that topic.
If a guaranteed delivery of a message is required and you could have more than tens of thousands of clients and most messages will be point-to-point, then cluster sharding (and likely persistence, depending on how strong you want the guarantee to be around changes of cluster membership etc.) is a good tool: your HTTP request handler forwards a message for a given client to a sharded entity associated with that client, and your websocket handler essentially subscribes to that sharded entity (you'll likely have to implement the buffering, etc. functionality yourself: this is the sort of "more custom solution" the Akka docs talk about) and forwards acknowledgements from the client (such acknowledgements are intrinsically part of the domain problem): note that any given HTTP -message-> entity -message-> websocket -ack-> entity message flow could entail at least three or four network hops in the cluster (depending on whether you want to respond to the HTTP request with an indication of whether the message was definitely buffered for the websocket client or not).
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论