【问题标题】:ActiveMQ : dead letter queue keeps my messages orderActiveMQ:死信队列保持我的消息顺序
【发布时间】:2011-03-15 09:42:00
【问题描述】:

我使用 ActiveMQ 作为代理来传递消息。这些消息旨在以数据库形式编写。有时,数据库无法访问或关闭。在这种情况下,我想回滚我的消息以便稍后重试这条消息,并且我想继续阅读其他消息。

这段代码运行良好,除了一点:回滚的消息阻止我阅读其他代码:

private Connection getConnection() throws JMSException {
    RedeliveryPolicy redeliveryPolicy = new RedeliveryPolicy();
    redeliveryPolicy.setMaximumRedeliveries(3); // will retry 3 times to dequeue rollbacked messages
    redeliveryPolicy.setInitialRedeliveryDelay(5 *1000);  // will wait 5s to read that message

    ActiveMQConnectionFactory connectionFactory = new ActiveMQConnectionFactory(user, password, url);
    Connection connection = connectionFactory.createConnection();
    ((ActiveMQConnection)connection).setUseAsyncSend(true);
    ((ActiveMQConnection)connection).setDispatchAsync(true);
    ((ActiveMQConnection)connection).setRedeliveryPolicy(redeliveryPolicy);
    ((ActiveMQConnection)connection).setStatsEnabled(true);
    connection.setClientID("myClientID");
    return connection;
}

我以这种方式创建会话:

session = connection.createSession(true, Session.SESSION_TRANSACTED);

回滚很容易问:

session.rollback();

假设我的队列中有 3 条消息:

1: ok
2: KO (will need to be treated again : the message I want to rollback)
3: ok
4: ok

我的消费者会做(线性序列):

commit 1 
rollback 2
wait 5s
rollback 2
wait 5s
rollback 2
put 2 in dead letter queue (ActiveMQ.DLQ)
commit 3
commit 4

但我想要:

commit 1
rollback 2
commit 3
commit 4
wait 5s
rollback 2
wait 5s
rollback 2
wait 5s
put 2 in dead letter queue (ActiveMQ.DLQ)

那么,如何配置我的消费者以延迟我的回滚消息?

【问题讨论】:

    标签: java jms activemq dead-letter


    【解决方案1】:

    您是否在 ActiveMQ XML 配置文件中使用<strictOrderDispatchPolicy />?我不确定这是否会影响重新发送消息的顺序。如果您使用严格的订单调度,请尝试注释掉该策略以查看是否会改变行为。

    布鲁斯

    【讨论】:

    • 不,我没有使用此策略。谢谢你的链接。
    【解决方案2】:

    这实际上是预期的行为,因为消息重试由客户端而不是代理处理。因此,由于您有 1 个会话绑定,并且您的重试策略是为 DLQ 之前的 3 次重试设置的,因此整个重试过程会阻止该特定线程。

    所以,我的第一个问题是,如果数据库插入失败,您会不会期望所有其他数据库插入都因类似原因而失败?

    如果不是,解决此问题的方法是将该队列的重试策略设置为 0 次重试,并使用特定的 DLQ,这样消息将立即失败并进入 DLQ。然后让另一个进程每 5 秒退出 DLQ 并重新处理和/或将其放回主队列进行处理。

    【讨论】:

    • 感谢您对行为的清晰解释。我们最终选择了 RabbitMQ 作为代理,并自己实现了 DLQ。
    【解决方案3】:

    我遇到了同样的问题,我在这里没有找到解决方案,所以在我找到一个解决同样问题的人之后决定在这里发布它。 当您在连接工厂中将属性 nonBlockingRedelivery 设置为 true 时,此问题在 5.6 版之前已修复:

    <property name="nonBlockingRedelivery" value="true" />
    

    【讨论】:

      猜你喜欢
      • 2018-03-31
      • 2012-01-24
      • 2018-07-04
      • 2015-04-21
      • 1970-01-01
      • 1970-01-01
      • 2012-12-28
      • 1970-01-01
      • 2019-09-27
      相关资源
      最近更新 更多