【问题标题】:Configuring ActiveMQ Artemis in Wildfly 12 for time-critical delivery of messages in a cluster在 Wildfly 12 中配置 ActiveMQ Artemis 以在集群中交付时间关键的消息
【发布时间】:2018-12-20 01:58:57
【问题描述】:

我不知道如何让 Wildfly 12 中的消息传递子系统在原始节点发生故障时将队列消息重新传递到不同的节点。当第一个尝试的节点没有足够快地确认/提交时,我需要一种将消息定向到不同节点的方法。

我有一个带有单个队列 (TestQueue) 的 3 节点 Wildfly 12 集群。我部署了一个带有单个 bean 的应用程序,该 bean 抓取 JMS 连接并与该队列上的消费者创建会话;这是构造函数:

public TestMessageListener( ConnectionFactory connectionFactory, Destination destination )
{
    this.context = connectionFactory.createContext( JMSContext.DUPS_OK_ACKNOWLEDGE );
    this.consumer = this.context.createConsumer( destination );
    this.consumer.setMessageListener( this );
    this.context.start();
}

连接工厂和目的地被注入到别处:

@Resource( lookup = "java:/ConnectionFactory" ) private ConnectionFactory connectionFactory;
@Resource( lookup = "java:/jms/queue/TestQueue" ) private Destination destination;

回到监听器,我只记录它接收到的内容:

@Override
public void onMessage( Message message )
{
    try
    {
        message.acknowledge();
        String body = new String( message.getBody( byte[].class ), StandardCharsets.UTF_8 );
        LOG.info( body );
    }
    catch ( JMSException e )
    {
        LOG.warning( e.toString() );
    }
}

最后,我在消息子系统配置中启用了 STOMP:

<socket-binding-groups>
    <socket-binding-group name="full-ha-sockets" default-interface="public">
        <socket-binding name="stomp" port="6164"/>
        ... 
    </socket-binding-group>
</socket-binding-groups>

<subsystem xmlns="urn:jboss:domain:messaging-activemq:3.0">
    <server name="default">
        <remote-acceptor name="stomp-acceptor" socket-binding="stomp">
            <param name="protocols" value="STOMP"/>
        </remote-acceptor>            
        <address-setting name="jms.queue.TestQueue" redistribution-delay="0"/>
        ...
    </server>

我通过 stomp 连接并每 2 秒发送一条带有唯一标识符的测试消息。 3 个节点中的每个节点轮流接收一个,循环。然后我从其中一个节点上拔下网线。

1 分钟后(我假设是 connection-ttl),我在其他 2 个节点上收到有关连接失败的错误消息:

2018-07-11 20:02:18,813 INFO  [TestMessageListener] (Thread-1 (ActiveMQ-client-global-threads)) TEST 435
2018-07-11 20:02:21,448 WARN  [org.apache.activemq.artemis.core.client] (Thread-8 (ActiveMQ-server-org.apache.activemq.artemis.core.server.impl.ActiveMQServerImpl$3@3070595f)) AMQ212037: Connection failure has been detected: AMQ119014: Did not receive data from /192.168.1.82:51046 within the 60,000ms connection TTL. The connection will now be closed. [code=CONNECTION_TIMEDOUT]
2018-07-11 20:02:21,449 WARN  [org.apache.activemq.artemis.core.server] (Thread-8 (ActiveMQ-server-org.apache.activemq.artemis.core.server.impl.ActiveMQServerImpl$3@3070595f)) AMQ222061: Client connection failed, clearing up resources for session b7be7d58-855c-11e8-91dd-6c626d5557a6
2018-07-11 20:02:21,449 WARN  [org.apache.activemq.artemis.core.server] (Thread-8 (ActiveMQ-server-org.apache.activemq.artemis.core.server.impl.ActiveMQServerImpl$3@3070595f)) AMQ222107: Cleared up resources for session b7be7d58-855c-11e8-91dd-6c626d5557a6
2018-07-11 20:02:21,449 WARN  [org.apache.activemq.artemis.core.server] (Thread-8 (ActiveMQ-server-org.apache.activemq.artemis.core.server.impl.ActiveMQServerImpl$3@3070595f))     AMQ222061: Client connection failed, clearing up resources for session b7becb79-855c-11e8-91dd-6c626d5557a6
2018-07-11 20:02:21,449 WARN  [org.apache.activemq.artemis.core.server] (Thread-8 (ActiveMQ-server-org.apache.activemq.artemis.core.server.impl.ActiveMQServerImpl$3@3070595f)) AMQ222107: Cleared up resources for session b7becb79-855c-11e8-91dd-6c626d5557a6

再过 30 秒后,我收到另一轮有关连接失败的错误消息:

2018-07-11 20:02:49,443 WARN  [org.apache.activemq.artemis.core.client] (Thread-1 (ActiveMQ-client-global-threads)) AMQ212037: Connection failure has been detected: AMQ119011: Did not receive data from server for org.apache.activemq.artemis.core.remoting.impl.netty.NettyConnection@5e696d4b[local= /192.168.1.27:39202, remote=/192.168.1.82:8080] [code=CONNECTION_TIMEDOUT]
2018-07-11 20:02:49,444 WARN  [org.apache.activemq.artemis.core.server] (Thread-1 (ActiveMQ-client-global-threads)) AMQ222095: Connection failed with failedOver=false
2018-07-11 20:02:49,446 WARN  [org.apache.activemq.artemis.core.server] (Thread-1 (ActiveMQ-client-global-threads)) AMQ222095: Connection failed with failedOver=false

请注意,我的 STOMP 客户端已连接到正常节点之一,并在“失败”框断开连接时继续向队列发送消息。

我的问题是:

  • 在 90 秒内,Artemis 继续向未插电的盒子传递消息。
  • 即使在 90 秒过去后,我也不知道如何让 Artemis 尝试将旧消息重新传递到其他节点。
  • 我不明白为什么在 60s 第一轮连接错误后它继续尝试向拔出的盒子传递消息。
  • 设置 redistribution-delay 无效,但我认为由于https://activemq.apache.org/artemis/docs/latest/clusters.html 会很有用。

像这样:

<address-setting name="jms.queue.TestQueue" redistribution-delay="0"/>
  • 当我重新插入网络电缆时,本应传送到故障节点的所有消息现在都已传送。

对于这个特定的队列,我不仅希望尝试重新传递到另一个节点,而且我希望消息确认超时来触发此重新传递,或者,如果失败,则需要一个 750-1000 毫秒的小连接 ttl。如果我将 connection-ttl 设置为 15000 毫秒,所有节点之间的所有连接(即使整个集群都健康)在 15000 毫秒后都会抛出错误。根据https://activemq.apache.org/artemis/docs/latest/configuration-index.html 的文档,此参数为“网桥的 TTL。这应该大于 ping 周期”。目前还不清楚“ping 周期”是什么参数,更不清楚这样的参数将如何映射到 Wildfly 子系统配置。我假设 connection-ttl 在这里,我将其设置为 15000:

<cluster-connection name="my-cluster" address="jms" connector-name="http-connector" connection-ttl="60000" retry-interval-multiplier="1.5" max-retry-interval="60000" discovery-group="dg-group1"/>

我很擅长接收和处理重复消息;我认为 JMSContext.DUPS_OK_ACKNOWLEDGE 和 redistribution-delay="0" 的组合至少可以解决它的重新传递部分。

我尝试了 JMSContext.TRANSACTED 并使用了 JMSContext.commit() 和 JMSContext.rollback()。显然,当故障节点与集群的其余部分断开时,rollback() 不适用,但这是我能看到的触发重新交付的唯一方法。

我现在正处于调整看似无穷无尽的配置参数而几乎没有效果的阶段。任何帮助将不胜感激。

【问题讨论】:

    标签: jms wildfly activemq-artemis


    【解决方案1】:

    我相信这里发生的事情是-1 的默认reconnect-attempts 被用于集群连接,并且只要集群连接尝试重新连接到关闭节点,那么该节点的消息将保存在特殊的“存储转发”队列中。您应该能够将 reconnect-attempts 设置为 -1 以外的其他值,以便集群连接将放弃尝试重新连接,此时用于其他节点的消息将普遍可供使用。

    【讨论】:

    • 太棒了;明天我会试一试并发布我的结果。感谢您的回复。
    • 我设置了 reconnect-attempts=2, connection-ttl=1000, check-period=500 (最后一个是必需的,否则它会每秒超时每个连接)但它似乎从来没有重新传递在该 1 秒窗口内发送的所有消息。
    • 需要一种简单、自动化的方法来重现问题以进一步调查。越简单越好。
    • 我准备了一个样本,但不幸的是它并不简单或自动化。我有两个 Maven 项目,每个项目都有一个耳朵; wildfly 需要解压和配置两次(尽管它在同一个节点上工作)。一只耳朵(消费者)部署到两个节点,而另一只耳朵(生产者)部署到第二个节点。然后我向第一个节点发送 SIGSTOP,等待几分钟,然后 SIGKILL 第一个节点。然后在两个日志文件之间,我寻找一个间隙,指示在第一个节点发生故障期间发送到第一个节点的消息永远不会针对第二个节点重试。
    • 所以要真正复制需要构建两个小型 maven 项目并遵循大约 100 行指令。我很乐意输入它,但同样,它不是自动化的或简单的。我对想法持开放态度。
    猜你喜欢
    • 2016-06-23
    • 1970-01-01
    • 1970-01-01
    • 2018-05-08
    • 2020-02-24
    • 1970-01-01
    • 1970-01-01
    • 2019-11-14
    • 1970-01-01
    相关资源
    最近更新 更多