从 QueueBrowser 确认消息的替代方案

发布于 2024-12-03 09:58:20 字数 1146 浏览 0 评论 0原文

我对 JMS 比较陌生。我有这样的要求:

事件被发布到队列中。每个事件都有一个与其关联的 UserID,并且必须按顺序处理给定 UserID 的事件。有时事件无法立即处理,因此我们希望暂时忽略来自该 UserID 的事件,同时继续使用队列中其他 UserID 的事件。

最初我认为 QueueBrowser 可能会有所帮助,a la:

Session session = connection.createSession(true, Session.CLIENT_ACKNOWLEDGE);
QueueBrowser queueBrowser = session.createBrowser(eventQueue);
Enumeration messages = queueBrowser.getEnumeration();
HashSet<Integer> busylist = new HashSet<Integer>(); // Keeps track of busy users
while (messages.hasNextElement())
{
  t.begin()
  Message msg = (Message) messages.getNextElement();
  Integer userId = msg.getIntProperty("UserID");
  if (busylist.contains(userId))
    continue;
  boolean userIsBusy = process(msg);
  if (userIsBusy)
  {
    busylist.add(userId);
    continue;
  }
  msg.acknowledge();
  t.commit();
}

这个想法是消耗队列中的所有内容,但是当用户忙碌时,将其记录在繁忙列表中并继续处理下一条消息。上面的代码可能每分钟调用一次。 在测试了与上述代码类似的内容后,我发现来自队列浏览器的消息上的acknowledge()消息按设计没有执行任何操作。

我的问题是,我怎样才能实现与上述类似的目标?我看到的一个解决方案是为我想要确认的每条消息创建一个 MessageConsumer,使用消息选择器来选择单个消息......对我来说这似乎有点低效。还有其他方法可以做到这一点吗?

我认为每个用户一个队列是不可接受的解决方案。有数百万用户。

I'm relatively new to JMS. I have a requirement as such:

events are published to a queue. Each event has a UserID associated with it, and the events for a given UserID must be processed in order. Sometimes an event cannot be processed immediately, so we'd like to temporarily ignore events from that UserID while continuing to consume events for the other UserIDs in the queue.

Initially I thought that a QueueBrowser might help, a la:

Session session = connection.createSession(true, Session.CLIENT_ACKNOWLEDGE);
QueueBrowser queueBrowser = session.createBrowser(eventQueue);
Enumeration messages = queueBrowser.getEnumeration();
HashSet<Integer> busylist = new HashSet<Integer>(); // Keeps track of busy users
while (messages.hasNextElement())
{
  t.begin()
  Message msg = (Message) messages.getNextElement();
  Integer userId = msg.getIntProperty("UserID");
  if (busylist.contains(userId))
    continue;
  boolean userIsBusy = process(msg);
  if (userIsBusy)
  {
    busylist.add(userId);
    continue;
  }
  msg.acknowledge();
  t.commit();
}

The idea is to consume everything from the queue, but when a user is busy, record that in busylist and continue on to the next message. The above code might be called once per minute.
After testing something similar to the above code I found that the acknowledge() message on messages from a queuebrowser does nothing by design.

My question is, how might I achieve something similar to the above? One solution I see is to create a MessageConsumer for every message I want to ack using a message selector to select out the individual message... It seems a bit inefficient to me. Are there other ways to do this?

I don't think an acceptable solution would be one queue per user. There're millions of users.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

深海里的那抹蓝 2024-12-10 09:58:20

不要立即偏离您的方法,但是您可以在发送消息时设置消息的生存时间吗?这样,如果用户没有在指定时间内消费他们的消息,他们的消息将被JMS引擎自动清除。

或者,采用您的方法,而不是为每个空闲用户的每条消息创建一个消息使用者,而是将消息 ID 批处理为 n 条消息集。当批次已满或浏览器到达消息集末尾时,指示消息使用者使用指定所有空闲消息ID的选择器并使用它们。

Not to immediately sidetrack your approach, but could you set a time-to-live on messages when they are sent ? That way, if a user does not consume their messages within the designated time, their messages will automatically be purged by the JMS engine.

Alternatively, pursuing your approach, rather than creating a message consumer per message per idle user, batch the message IDs into sets of n messages. When the batch is full, or the browser reaches the end of the message set, direct the message consumer to use a selector which specifies all the idle message IDs and consume them.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文