如何在异常时使用DUPS_OK_ACKNOWLEDGE处理jms消息使用者

时间:2018-05-18 14:06:53

标签: jms spring-jms tibco

我正在使用来自tibco队列的消息,session transacted true我看到吞吐量为13 msgs / sec,session transacted as falseDUPS_OK_ACKNOWLEDGE ack模式的吞吐量为160 msgs /是承诺的秒,但是当应用程序中抛出异常时,消息将丢失。

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

    .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();

1 个答案:

答案 0 :(得分:2)

  

.from(Jms.messageDrivenChannelAdapter(tibcoConnectionFactory)

将使用默认容器,如果未处理,则可能会丢失邮件,因为侦听器是在consumer.receive()之外调用的。

使用

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

代替。

修改

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

  

2018-05-18 11:38:43.657 WARN 48531 --- [会话任务-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一次又一次地传递。