我在我的系统中有以下架构集成:
2个Mule实例(不是在Mule集群中,因为CE版本)和2个activemq实例,使用共享数据库锁在主从中配置。
Mule中有一个流,它具有入站队列,其中另一个流写入消息。从该队列中读取此消息后,它会进行一些处理并调用另一个系统,这可能会返回一些受控异常,在这种情况下,应该重新传递消息。
我已配置此重新投放政策:
<spring:bean id="redeliveryPolicy" class="org.apache.activemq.RedeliveryPolicy">
<spring:property name="maximumRedeliveries" value="5" />
<spring:property name="initialRedeliveryDelay" value="30000" />
<spring:property name="maximumRedeliveryDelay" value="7200000" />
<spring:property name="useExponentialBackOff" value="true" />
<spring:property name="backOffMultiplier" value="4" />
<spring:property name="useCollisionAvoidance" value="true"/>
</spring:bean>
这是上次重试时的重新传输延迟2小时。由于这是一个很长的时间间隔,我们不想阻止处理新的传入消息,所以我们算法配置'nonBlockingRedelivery'= true。
Mule的每个实例为此队列启动4个消费者,总共8个消费者。
我们面临的问题是,在某些负载测试中,我们发送500条消息,这些消息会在某个时刻在目标系统中生成受控异常(强制重新传递),处理性能会下降很多。 我们知道,随着重新传递延迟的增加,有一些区间没有任何处理是正常的,但是当重新发送时应该只发生它 不时处理一次重新发送。
我们注意到,如果我们停止其中一个Mule实例,则另一个开始处理合理数量的重新传输(如果它们被阻止直到那个时刻)并且经过一段时间相同的低性能重复方案。当我们最近停止启动该实例时,它不会开始处理任何重新传递,但是如果我们停止另一个(第一次没有停止的那个),它会处理“排队”的重新传递。虽然我不确定我认为这是因为redelivey标志位于内存中,所以当其中一个节点停止时,它会“释放”其消息,并由另一个实例处理,如“新鲜”的新消息。
在我们的一个测试中,我们等待几个小时,最后处理所有消息(它们都达到了最大重试次数限制)。
所以这似乎是阻碍的问题,但我们有点卡住了。
我尝试了一些配置但没有成功:
useCollisionAvoidance = true,以避免重新传递勾结(也许我应该增加默认碰撞因子)。
我更改了预取最大挂起= 1(默认值为1000)。
我们知道这是一个极端的场景(所有对目标系统的调用都失败了)但是如果系统出现故障可能会发生这种情况,所以我们希望对它做好准备。
任何帮助?
当这个“阻塞场景”发生时,我附加了与其中一个实例的ActiveMQ相关的mule线程转储:
"ActiveMQ InactivityMonitor Worker" daemon prio=10 tid=0x00007fb79863c800 nid=0x1520 waiting on condition [0x00007fb77aceb000]
java.lang.Thread.State: TIMED_WAITING (parking)
at sun.misc.Unsafe.park(Native Method)
- parking to wait for <0x000000078dc457c0> (a java.util.concurrent.SynchronousQueue$TransferStack)
at java.util.concurrent.locks.LockSupport.parkNanos(LockSupport.java:226)
at java.util.concurrent.SynchronousQueue$TransferStack.awaitFulfill(SynchronousQueue.java:460)
at java.util.concurrent.SynchronousQueue$TransferStack.transfer(SynchronousQueue.java:359)
at java.util.concurrent.SynchronousQueue.poll(SynchronousQueue.java:942)
at java.util.concurrent.ThreadPoolExecutor.getTask(ThreadPoolExecutor.java:1068)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1130)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:615)
at java.lang.Thread.run(Thread.java:745)
"ActiveMQConnection[ID:HSLPRELABMUL801-45728-1456487568559-1:1] Scheduler" daemon prio=10 tid=0x00007fb7c0226000 nid=0x1479 in Object.wait() [0x00007fb7a13a9000]
java.lang.Thread.State: TIMED_WAITING (on object monitor)
at java.lang.Object.wait(Native Method)
at java.util.TimerThread.mainLoop(Timer.java:552)
- locked <0x000000078d39f060> (a java.util.TaskQueue)
at java.util.TimerThread.run(Timer.java:505)
"ActiveMQ InactivityMonitor WriteCheckTimer" daemon prio=10 tid=0x00007fb790002800 nid=0x1466 in Object.wait() [0x00007fb77abea000]
java.lang.Thread.State: TIMED_WAITING (on object monitor)
at java.lang.Object.wait(Native Method)
at java.util.TimerThread.mainLoop(Timer.java:552)
- locked <0x000000078d7aaa78> (a java.util.TaskQueue)
at java.util.TimerThread.run(Timer.java:505)
"ActiveMQ Transport: tcp:///10.237.89.167:61616@45020" prio=10 tid=0x00007fb78801d000 nid=0x1464 runnable [0x00007fb77adec000]
java.lang.Thread.State: RUNNABLE
at java.net.SocketInputStream.socketRead0(Native Method)
at java.net.SocketInputStream.read(SocketInputStream.java:152)
at java.net.SocketInputStream.read(SocketInputStream.java:122)
at org.apache.activemq.transport.tcp.TcpBufferedInputStream.fill(TcpBufferedInputStream.java:50)
at org.apache.activemq.transport.tcp.TcpTransport$2.fill(TcpTransport.java:609)
at org.apache.activemq.transport.tcp.TcpBufferedInputStream.read(TcpBufferedInputStream.java:58)
at org.apache.activemq.transport.tcp.TcpTransport$2.read(TcpTransport.java:594)
at java.io.DataInputStream.readInt(DataInputStream.java:387)
at org.apache.activemq.openwire.OpenWireFormat.unmarshal(OpenWireFormat.java:267)
at org.apache.activemq.transport.tcp.TcpTransport.readCommand(TcpTransport.java:221)
at org.apache.activemq.transport.tcp.TcpTransport.doRun(TcpTransport.java:213)
at org.apache.activemq.transport.tcp.TcpTransport.run(TcpTransport.java:196)
at java.lang.Thread.run(Thread.java:745)
"ActiveMQ InactivityMonitor ReadCheckTimer" daemon prio=10 tid=0x00007fb78801b800 nid=0x1462 in Object.wait() [0x00007fb77aeed000]
java.lang.Thread.State: TIMED_WAITING (on object monitor)
at java.lang.Object.wait(Native Method)
at java.util.TimerThread.mainLoop(Timer.java:552)
- locked <0x000000078d7aad88> (a java.util.TaskQueue)
at java.util.TimerThread.run(Timer.java:505)
谢谢