我正在建立一个聊天服务,支持一对一和团体聊天。用户连接到一个LoadBalancer,它将它们分配给正在运行的服务器应用程序之一。
user1 Server1
user2 -> LoadBalancer -> Server2 => Kafka Message Bus
user3 Server3假设user1连接到Server1,user3连接到Server3。当user1向user3发送消息时,Server1会将该消息发布给卡夫卡,主题是chat.message。邮件信封包含收件人信息(recipient=user3)。当Server3收到消息时,它只会解析信封,检查收件人,说我已经连接了那个用户,所以我会处理它(Server2做同样的事情,但是删除消息,因为User3没有连接到它)。
到目前为止这个设计还不错。但是,如果我有一百万台服务器,那么除了一个服务器之外,所有的服务器都将处理该消息,而rest将删除它。似乎有点浪费(虽然每个服务只解析信封,而不是整个消息)。是否有更好的方法来拆分我的主题,使消息只发送到服务器的一个子集,而不是所有服务器。我可以有像chat.message.server1,2,3.这样的话题然而,这听起来太细了。
**我意识到我可以通过grpc或rest来处理这个问题,这样Server1就可以直接将消息发送给Server3。然而,我不想走那种硬耦合的道路。
发布于 2022-06-01 06:47:30
作为only sent to a subset of the servers,我理解您指的是您所称的Server服务,而不是卡夫卡服务器。
在这种情况下,您可以利用这样的事实:主题在分区中被划分,并且同一个使用者组的使用者被分配了这些分区的子集。
有几种选择:
Server,以及每个Server从哪个分区消费。当您想向用户发送消息时,查询数据库以了解它在哪个Server中注册,获取Server正在使用的分区,并将其发送到这些分区之一(然后将其本地缓存以避免连续查询数据库)。当出现再平衡(改变Servers数量)时,您将实现一个自定义钩子,该钩子在继续处理消息之前更新数据库中的这些映射,并且每个Server都清理其本地缓存。Servers。因此,必须向客户端发送消息的Server知道它必须根据客户端的唯一id向哪个分区发送消息,而不必查询任何外部系统。- You are going to need a deterministic mapping between users and `Servers` and partitions and `Servers`: The load balancer will need to know what `Server` is a particular user assigned to, and when sending a message, the server will need to know 1) in which `Server` is this user and 2) what partitions have this `Server` assigned.
- This can be fairly complex to get right and may require you to use a hashing technique like [`consistent hashing`](https://en.wikipedia.org/wiki/Consistent_hashing) to avoid reconnecting all clients to different `Servers` when there is a change in the number of `Servers`.https://stackoverflow.com/questions/72454021
复制相似问题