【发布时间】: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