不应该确认一条消息就将其重新发送给Kafka用户吗?

时间:2019-08-02 14:35:30

标签: java apache-kafka ibm-mq spring-cloud-stream

我正在运行一个Spring Cloud Stream应用程序,在其中我从Kafka主题读取事务,处理该事务,然后将其发送到IBM MQ。当与IBM MQ没有连接以防止事务丢失时,我正在尝试处理该错误。在这种情况下,jms模板将引发异常,并且流侦听器不会提交事务。预期的行为是使事务保留在Kafka主题中,并让流侦听器再次读取它。但是,该消息似乎只消耗了一次,并且没有发生“回滚”。为此,这是我的配置:

spring:
  cloud:
    stream:
      kafka:
        bindings:
          input:
            consumer:
              auto-commit-offset: false
      bindings:
        input:
          destination:  kafka_topic
          brokers: localhost:9092

这是代码:

    public void handleMessage(Message<TransactionMessage> request,  @Header(KafkaHeaders.ACKNOWLEDGMENT) Acknowledgment acknowledgment) {
        TransactionMessage message = request.getPayload();
        System.out.println("Consumed a message");
        try {
            executionFlow.execute(message); // here the jmsTemplate throws an exception
            System.out.println("doing the ack");
            acknowledgment.acknowledge();
        }
        catch (RuntimeException e) {
            System.out.println("did not send to MQ");
        }
    }

executionFlow调用的jmsTemplate的代码:

    public void sendMessage(String messageTarget) {

        System.out.println("i am trying to send to MQ");
        try {
            jmsTemplate.convertAndSend(destinationTopicQueue, messageTarget);
        } catch (Exception e) {
            throw new RuntimeException("jmsTemplate failed to send to IBM MQ");
        }
    }

这是我关闭与IBM MQ的连接时的输出:

Consumed a message
i am trying to send to MQ
did not send to MQ

1 个答案:

答案 0 :(得分:0)

   catch (RuntimeException e) {
        System.out.println("did not send to MQ");
    }

您需要重新引发异常以引起回滚。

您还需要在活页夹中启用Kafka事务。

请参见Kafka Binder Properties

spring.cloud.stream.kafka.binder.transaction.transactionIdPrefix
  

在活页夹中启用事务。请参阅Kafka文档中的transaction.id和spring-kafka文档中的Transactions。启用事务后,单个生产者属性将被忽略,所有生产者都将使用spring.cloud.stream.kafka.binder.transaction.producer。*属性。

     

默认为空(无交易)

如果您还向kafka发送数据,则需要交易生产者

spring.cloud.stream.kafka.binder.transaction.producer.*
  

交易绑定中生产者的全球生产者属性。请参阅spring.cloud.stream.kafka.binder.transaction.transactionIdPrefix和Kafka生产者属性以及所有绑定程序支持的常规生产者属性。

     

默认:查看各个生产者属性。