【问题标题】:How to get the number of subscriptions to a topic in RabbitMQ如何获取 RabbitMQ 中某个主题的订阅数
【发布时间】:2015-07-28 15:35:27
【问题描述】:

我有一个使用Spring Websokcets (with STOMP) 构建的聊天应用程序,我使用的消息代理是RabbitMQ

首先,我将尝试稍微解释一下流程。在我的应用程序中,同一用户可以从不同的设备连接到 websocket 服务器。为了简单起见,每个用户都将订阅/topic/{userId}。因此,当有人向用户123 发送消息时,他将能够在他连接的所有设备中看到该消息,因为我只是将该消息发送到目标/topic/{userId}

我的问题是在向特定topic 发送消息之前,我想检查此时topic 连接了多少用户(此数字指定用户登录的设备数量)。如果这个号码是0,我想把这条消息发送到一个单独的队列中。

我检查了this 问题,它们看起来与我的问题非常相似。但我相信我的问题更简单。我只是想知道用户的数量,我不需要任何关于他们的信息。

在我上面提到的问题中,Brian Clozel 提到可以从 RabbitMQ REST API 获取有关订阅的信息,我已经搜索了如何做到这一点。

如果我想知道订阅主题/topic/123的用户数,如何使用 RabbitMQ API 找到?

我还检查了这张this 票,似乎增加了对这个用例的支持,但据我所知,它只适用于SimpleMessageBroker。如果我是正确的,有人可以澄清一下。

我将能够使用Application Context Events 执行此操作,但这仅适用于单个服务器。在分布式系统中,这是行不通的。所以我认为从RabbiMQ 获取这些信息是正确的做法。

更新

让我更清楚地解释我想要做什么。假设我是userid 123 的用户,如果我从三个设备Laptop1Laptop2Mobile1 登录到该站点。最初,他们都将订阅/topic/123123 在这里是 UserId)。

基本上我想解决两个问题:

1) 即使用户处于非活动状态,我也不想让 websocket 连接保持打开状态,因此我会在一段时间不活动后关闭 websocket 连接。实际上,即使手机处于非活动状态,它也应该能够获取通知,因此我的应用程序将通过 ping notification server 获取通知(不仅仅是消息,任何类型的通知)。现在说有一条123 的传入消息,如果我知道没有消费者连接到/topic/123 并且如果用户123 安装了我们的应用程序(不知何故我会知道这个信息)我想发送推送这个向notification server 发送消息,这样即使 websocket 连接关闭,移动应用也能收到消息。

2) 第二个问题是,假设所有三个连接 (Laptop1,Laptop2,Mobile1) 都处于活动状态并且有传入消息,我只想在其中一个中显示通知活跃的客户端(就像 Gmail 或 Facebook 一样)。如果有一个传入消息到客户端并且如果它知道有多个设备(我可以从服务器发送此信息)订阅/topic/123,在客户端我可以决定是否显示弹出窗口或不是。

【问题讨论】:

  • 你在这里想要完成什么?知道某个特定主题有多少消费者的想法不是你应该做的,我认为......可能有更好的设计,但我需要知道你的意图是什么(不仅仅是 jsut 'send到不同的队列' - 你想把它发送到不同的队列吗?)
  • @DerickBailey 我编辑了问题并试图解释我要解决的问题。如果您认为有更好的方法来解决这些问题,请提出建议。
  • 我相信你的程序流逻辑已经和你的消息路由逻辑纠缠在一起了。如果您考虑所需的行为,而较少关注消息流或您认为您的设置可能实现的内容,那么它可能有助于指导您进行正确的设计。 发布者不应该知道或关心订阅者的数量。
  • @theMayer 通常是这样,但是对于这个特定的用例,我认为唯一的方法是拦截应用程序上下文事件或查询 RabbitMQ(不知何故)。如果您觉得有更好的方法,请提出建议。
  • @theMayer 在去推送话题之前,至少我应该知道有没有订阅者在听队列吧?

标签: java rabbitmq stomp spring-websocket


【解决方案1】:

鉴于您希望应用程序具有的功能,您将需要在 RabbitMQ 前面提供一些东西 - 一个 Web 服务器或其他可以托管您的 Websocket 并提供所需逻辑的应用程序服务器。

RabbitMQ 将根据路由键将消息传递到队列。任何连接到队列的消费者都有机会接收到消息。如果有多个消费者连接到一个队列,RabbitMQ 将轮询消息给消费者。除非您在给定队列上只有 1 个消费者,否则无法保证特定消费者会收到特定消息。

只需要向单个连接的设备发送通知意味着设备列表的优先顺序 - 哪个更重要并且应该接收通知。根据您的要求,优先顺序似乎是动态的......用户在给定设备上的活跃程度将改变该设备是否应该收到通知。

这种类型的逻辑在 RabbitMQ 中是不可能直接实现的。

我建议在 RabbitMQ 前面构建一个 Web 服务器,并让您的所有设备都连接到该 Web 服务器。使用 Web 服务器来促进 Web 套接字,并让 Web 服务器跟踪给定用户最活跃的设备。 Web 服务器可以使用该知识来确定哪个设备接收到通知。

【讨论】:

  • 我在RabbitMQ前面有一个websocket服务器,这就是我所说的Spring Websokcets (with STOMP)。要在 websocket 服务器中实现这个逻辑,我需要使用ApplicationContextEvents,它在集群环境中不会有效。这就是为什么我想知道是否有任何方法可以找到订阅特定队列的消费者数量。如果你在这里查看答案,stackoverflow.com/questions/24795340/…,他说这是可能的,但我没有在互联网上找到任何来源。
  • Any consumer connected to the queue has a chance of receiving the message. If there are multiple consumers connected to a queue, RabbitMQ will round-robin the messages to the consumers 也不完全正确我猜当 RabbitMQ 充当 websockets 的消息代理时。所有订阅者都会收到消息。如果我创建一个群聊应用程序,它应该是这样工作的,这就是它的工作方式。
猜你喜欢
  • 1970-01-01
  • 2015-08-11
  • 2012-12-07
  • 2019-11-11
  • 2016-08-18
  • 1970-01-01
  • 2020-09-24
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多