当前位置: 首页 > 知识库问答 >
问题:

ActiveMQ最后一个值队列没有按预期运行

詹夕
2023-03-14

我使用的是ActiveMQ Artemis 2.19.1。我用Spring Boot创建了生产者和消费者应用程序。我需要消费者的多个实例来接收所有消息(多播)。我像这样配置了最后一个值队列(broker.xml):

<address-settings>
   <address-setting match="quote.#">
      <max-size-bytes>1000000000</max-size-bytes> <!-- 1GB -->
      <address-full-policy>BLOCK</address-full-policy>
      <default-last-value-key>symbol</default-last-value-key>
      <default-last-value-queue>true</default-last-value-queue>
      <default-non-destructive>true</default-non-destructive>
   </address-setting>
   ...
</address-settings>

发送是这样的,似乎工作正常。“符号”是VLQ键。

import org.springframework.jms.core.JmsTemplate;

@Service
html" target="_blank">public class DispatcherService {

@Autowired
JmsTemplate jmsTemplate;

public void sendMessageA(String message) {
    jmsTemplate.convertAndSend(jmsQueue, message, m-> {
        m.setStringProperty("symbol", "ABC");
        return m;
    });
}

如果Spring Bootapplicaiton.properties有:

spring.jms.pub-sub-domain=true

...然后所有客户端在发布时都会收到所有消息(好)。但是,当新客户启动并订阅主题时,不会向他们发布最新消息。

如果改为使用:

spring.jms.pub-sub-domain=false

我可以看到最后一条消息仍保留在最后一个值队列中(良好),连接的消费者得到最后一条消息。然而,当消息发布时,它们是循环(anycast)分发的,而不是所有消息都分发给所有消费者。

如何确保连接到LVQ的客户端接收到最新的消息,然后是所有未来的消息,而不仅仅是未来消息的循环分发?

编辑:

只留下spring.jms.pub-sub-domain=true,并将追溯消息计数设置为大于可能遇到的符号数,否则一些符号将不会被保留:

<address-setting match="quotes">
  <retroactive-message-count>100000</retroactive-message-count>
</address-setting>

<address-setting match="*.*.*.quotes.*.retro">
  <default-last-value-key>symbol</default-last-value-key>
</address-setting>

共有1个答案

颜修真
2023-03-14

在我看来,一切都在按设计进行。我相信你的期望正在受挫,因为你正在使用pub/sub(即JMS主题)。

让我提供一点背景知识。当JMS客户机对主题创建订阅时,代理通过在具有相同名称的地址上创建多播队列来响应。队列是根据订阅的类型命名的。如果是非持久订阅,则队列将使用UUID命名。如果是持久订阅,则根据客户端提供的订阅名称和客户端ID(如果可用)来命名队列。当消息被发送到该地址时,它会被放入绑定到该地址的所有多播队列中。

因此,当创建新的非持久订阅时,也会为该订阅创建一个新队列,这意味着订阅服务器在创建订阅之前不会收到发送到主题的任何消息。这是JMS主题的预期行为(即正常的发布/订阅语义)。此外,由于非持久订阅的队列仅在订阅服务器连接时可用,这意味着无法强制执行LVQ语义,因为到达队列的任何消息都将立即发送给使用者。简而言之,带有JMS主题的LVQ没有太多意义。

使用JMS队列时,行为会发生变化,因为队列总是在那里接收消息。当经纪人强制执行LVQ语义时,消费者可以随心所欲地来来去去。

一种可能的解决方案是创建一个特殊的“初始化”队列,消费者可以在其中首先连接以获取最新信息,然后订阅JMS主题以获取所需的发布/订阅语义。您可以使用转移功能使发送消息的应用程序透明,这样它们就可以继续只发送到JMS主题。以下是示例配置:

<configuration xmlns="urn:activemq" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="urn:activemq /schema/artemis-configuration.xsd">
   <core xmlns="urn:activemq:core">

      ...      

      <diverts>
         <divert name="myDivert">
            <address>myTopic</address>
            <forwarding-address>initQueue</forwarding-address>
            <exclusive>false</exclusive>
         </divert>
      </diverts>

      ...

      <addresses>
         <address name="myTopic">
            <multicast/>
         </address>
         <address name="initQueue">
            <anycast>
               <queue name="initQueue" last-value-key="symbol" non-destructive="true" />
            </anycast>
         </address>
         ...
      </addresses>
   </core>
</configuration>

使用此配置,发送到JMS主题myTopic的每条消息也将透明地发送到initQueue。此队列将只保留自使用last value语义以来最新的消息。此外,由于队列是非破坏性的,因此这些最新消息将保留在队列中,以供后续消费者使用。

我在这里预期的唯一困难是Spring,它可能无法为您提供创建初始队列使用者然后创建主题订阅者的灵活性。如果直接使用JMS API,这将是一件相对简单的事情。

另一个可能的解决方案是使用追溯地址。这里要做的主要事情是确保内部环形队列是LVQ。您可以使用默认最后一个值键地址设置。请参阅要使用的匹配上的文档详细信息。

 类似资料:
  • 问题内容: 问题出在此CSS和HTML之内。 HTML CSS 这两行CSS都不应该 以“ complete”类 为目标的 最后一个li元素 吗? jQuery中的此查询也不针对它: 但这确实做到了: 问题答案: 该选择器用于选择父的最后一个子元素。它不能用于选择给定父元素下具有特定类的最后一个子元素。 复合选择器的另一部分(位于之前)指定了附加条件,最后一个子元素必须按顺序满足才能被选择。在下面

  • 在我对Artemis LastValueQueue代码的测试和回顾中,消息的调度延迟似乎优先于对“last value key”的评估。换言之,如果您安排了一条消息,那么它只会在准备传递时替换队列中的最后一个值。 我的问题是我是否正确理解了代码,如果是,是否有一个解决方案或ActiveMQ/Artemis的功能可以帮助满足我们的要求。 我们的要求如下: 生成一条消息,并将该消息的处理延迟到将来的某

  • 我正在开发一个graqphqlapi,它通过Mongoose从MongoDB获取数据。现在我遇到的问题是GraphQL不使用查询来解析字段,而是使用字段解析程序,因为没有设置ID,所以字段解析程序无法工作。 TypeDefs: 解析程序: 功能: 查询: 结果:

  • 我正在尝试解析下面的XML文件并基于它创建一个JTree。 “窗口01”将添加到根节点“对象列表”,但“页面01”节点不会显示在“窗口01”节点下。下面给出了使用的源代码。请帮忙!!! 这是主课。编译时不会显示错误或警告。

  • 我在使用R的group_by和SUMMARY函数时遇到了一些问题,我想知道你们是否可以帮我一些忙。我有一张类似的表格: 我试图使用dplyr的group_by和SUMMARY来找到频率列的平均值。下面是我的示例代码: 我所期望的是,一个表格被吐出来,分解按单个类别分组的平均频率,如下所示: 但是,我收到的是一个按类别分组的表,每个类别接收整个表的平均值,如下所示: 有什么线索吗?我应该说我是初学者

  • 我有这样的矩阵: 我需要在最后一列中过滤它tp get value 1。所以结果应该是这样的: 我的当前代码是: 我的代码返回一个空数组。我一定错过了什么...