【问题标题】:How to deal with jms message consumer with DUPS_OK_ACKNOWLEDGE on exception如何处理带有 DUPS_OK_ACKNOWLEDGE 异常的 jms 消息使用者
【发布时间】:2018-05-18 23:40:28
【问题描述】:

我正在使用来自 tibco 队列的消息,session transacted true 的吞吐量为 13 msgs/sec,session transacted as falseDUPS_OK_ACKNOWLEDGE ack 模式的吞吐量为 160 msgs/sec,这是有希望的,但是当应用程序中抛出异常,然后消息丢失。

任何人都可以建议我如何处理这种情况,我需要高吞吐量,同时不会在异常时丢失消息。

    .from(Jms.messageDrivenChannelAdapter(tibcoConnectionFactory)
            .destination(sourceQueue)
            .configureListenerContainer(spec -> {
                spec.sessionTransacted(false);
                spec.sessionAcknowledgeMode(Session.DUPS_OK_ACKNOWLEDGE);
            }))
            .transform(orderTransformer, "transform", e -> e.advice(idempotentReceiverInterceptor())
            .handle(orderService, "save")
            .get();

【问题讨论】:

  • 您使用的是什么容器?如果您不使用事务,则必须使用 SimpleMLC(而不是 DefaultMLC)。那么你不应该丢失消息。
  • 使用 spring boot 容器和CachingConnectionFactory。而且我还需要按顺序阅读消息,所以只有单线程消费者

标签: jms spring-jms tibco


【解决方案1】:

.from(Jms.messageDrivenChannelAdapter(tibcoConnectionFactory)

将使用默认容器,如果不进行事务处理,该容器可能会丢失消息,因为侦听器是在 consumer.receive() 之外调用的。

使用

.from(Jms.messageDrivenChannelAdapter(tibcoConnectionFactory, 
    SimpleMessageListenerContainer.class)

改为。

编辑

错误信息应该是一个线索...

2018-05-18 11:38:43.657 WARN 48531 --- [Session Task-1] o.s.j.l.SimpleMessageListenerContainer:JMS 消息监听器的执行失败,并且没有设置 ErrorHandler。

所以添加一个错误处理程序...

@SpringBootApplication
public class So50413144Application {

    public static void main(String[] args) {
        SpringApplication.run(So50413144Application.class, args);
    }

    @Bean
    public ApplicationRunner runner(JmsTemplate template) {
        return args -> {
            for (int i = 0; i < 10; i++) {
                template.convertAndSend("foo", "foo" + i);
            }
        };
    }

    @Bean
    public IntegrationFlow flow(ConnectionFactory connectionFactory) {
        return IntegrationFlows
                .from(Jms.messageDrivenChannelAdapter(connectionFactory, SimpleMessageListenerContainer.class)
                        .destination("foo")
                        .configureListenerContainer(c -> {
                            c.sessionAcknowledgeMode(Session.DUPS_OK_ACKNOWLEDGE);
                            c.errorHandler(t -> {
                                if (t instanceof RuntimeException) {
                                    throw (RuntimeException) t;
                                }
                            });
                        }))
                .handle((p, h) -> {
                    System.out.println(p);
                    if (p.equals("foo5")) {
                        throw new RuntimeException("fail");
                    }
                    try {
                        Thread.sleep(200);
                    }
                    catch (InterruptedException e) {
                        Thread.currentThread().interrupt();
                    }
                    return null;
                })
                .get();
    }

}

...和foo5 一遍又一遍地传递。

【讨论】:

  • 仍然是相同的行为,如果在上面的代码中orderService 抛出 sql 异常,我会从队列中丢失消息。
  • 您需要ErrorHandler - 请参阅我的答案的编辑。
  • 感谢您的快速示例响应。我可以看到它与 activeMq 一起工作,因为消息被重新传递了 7 次(如标志 jms_redelivered=true, JMSXDeliveryCount=7 所说)。但是由于 tibco 它不起作用,会话中是否有任何标志来设置重新交付的数量?
  • “不工作”是什么意思? JMSXDeliveryCountnew JMS 2.0 feature 但一些老经纪人实现了它。在一定数量的交付后放弃不是 JMS 规范的一部分,但大多数代理都有一些方法来配置该行为。我对 tibco 不熟悉。
  • camel 有一个 maximumRedeliveries 的概念例外,我认为在 spring 集成中我错过了一些东西。关于 tibco,上述程序在出现异常时无法重新交付,它继续消耗 foo6。当我设置 sessionTransacted to trueAUTO_ACKNOWLEDGE 时,foo5 消息被重新传递 n 次。
猜你喜欢
  • 2013-07-10
  • 1970-01-01
  • 2017-03-16
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-08-02
  • 1970-01-01
相关资源
最近更新 更多