我认为您最初的想法比临时订阅更好。我的意思是它有效,但感觉完全不自然。看你的要求是什么。例如,客户端是否只需要在连接时接收消息,还是都需要获取所有消息?
仅在连接时
你最初的想法是更好的imo。我可能会做的是创建一个客户端可以连接的 gRPC 流服务。该实现本质上是一个观察者模式。消费者将收到一条消息,然后遍历订阅者以向所有订阅者执行“发送”。从那里,任何时候客户端连接到服务,它只是向该观察者集合注册自己,并在断开连接时取消注册。水平扩展是被动的,因为客户端会粘在他们连接的任何实例上。
如果最终,每个人都会收到信息
该概念与上述类似,但客户端不会在断开连接时从观察者隐式取消注册。相反,它会显式地注册和取消注册(通过为此而设计的方法/命令)。修改“on disconnected”逻辑,告诉观察者列表客户端已经离线。那么消费者的广播逻辑略有不同。现在它遍历列表并说“如果在线,则发送,否则排队”,并将消息发送到临时队列(属于客户端)。然后,您的“连接时”逻辑将在通知消费者它重新联机之前将所有排队的消息发送到客户端。基本上是一个收件箱。在 RabbitMQ 等大多数产品中,设置临时的、自删除的队列非常容易。我觉得你' 不过,我必须做一些管理是否可以删除队列。例如,除非客户端明确取消订阅或长时间处于非活动状态,否则永远不要删除队列。如果不这样做,整个收件箱的想法就会分崩离析。
上面选择的答案与我在这里订阅的内容最相似,因为订阅是队列。如果我这样做了,那么我可能会将它实现为内部总线而不是观察者(因为它是不必要的) - 您按需为连接客户端创建一个消费者,该客户端实际上只是转发消息。消息消费者根据客户端是否连接进行订阅和取消订阅。正如 Kamal 所指出的,如果您的规模超过 pubsub 允许的最大订阅数,您将遇到问题。如果你发现自己处于那个位置,那么你可以通过实现上面的模式来解除这个约束。这基本上是相同的模式,但是您将责任转移到您的基础设施上,其中唯一的限制是您自己的资源。
gRPC 使这种机制非常简单。或者,对于 Web,如果您使用 Microsoft 堆栈,那么 SignalR 也可以让这变得非常容易。客户端连接到集线器,您可以发布到所有连接的客户端。这里的消费者模式基本保持不变,但您不必手动实现观察者模式。
(注意:图中的箭头是依赖的方向,不是数据流的方向)