Spring cloud Spring Cloud Stream Kafka-最终一致性-Kafka是否自动重试未确认的消息(使用autocommitoffset=false时)

Spring cloud Spring Cloud Stream Kafka-最终一致性-Kafka是否自动重试未确认的消息(使用autocommitoffset=false时),spring-cloud,microservices,distributed-transactions,spring-cloud-stream,spring-kafka,Spring Cloud,Microservices,Distributed Transactions,Spring Cloud Stream,Spring Kafka,实现最终一致的分布式体系结构是一件痛苦的事情。有大量的博客文章讲述了如何做到这一点,但没有展示(代码)如何实际做到这一点 我遇到的一个问题是,当消息未被确认时,必须手动重试消息 例如:我的订单服务向卡夫卡发送支付事件。支付服务已订阅并处理它,回答“支付确定”或“支付失败” 要求付款:订单服务----付款活动---->Kafka----付款活动---->付款服务 付款确认:->付款服务----付款确认事件---->Kafka----付款确认事件---->订单服务 支付失败->支付服务----支付失

实现最终一致的分布式体系结构是一件痛苦的事情。有大量的博客文章讲述了如何做到这一点,但没有展示(代码)如何实际做到这一点

我遇到的一个问题是,当消息未被确认时,必须手动重试消息

例如:我的订单服务向卡夫卡发送支付事件。支付服务已订阅并处理它,回答“支付确定”或“支付失败”

  • 要求付款:
    订单服务----付款活动---->Kafka----付款活动---->付款服务

  • 付款确认:->
    付款服务----付款确认事件---->Kafka----付款确认事件---->订单服务

  • 支付失败->
    支付服务----支付失败事件---->Kafka----支付失败事件---->订单服务

  • 重点是:

    我可以确定何时通过同步发送将消息发送给卡夫卡。但是,我必须知道付款服务已经处理了付款的唯一方法是等待一个应答事件(付款确定|付款失败)

    这迫使我在Order server中实现重试机制。如果它在一段时间内没有得到答复,请使用新的支付事件重试

    更重要的是,这也迫使我在支付服务中处理重复的消息,以防它们被实际处理,但答案没有到达订单服务

    我想知道,如果消费者没有确认消息的新偏移量,卡夫卡是否有一个内置机制来发送重试

    在Spring Cloud Stream中,我们可以将
    autocommitofset
    属性设置为false,并处理消费者中的偏移确认:

     @StreamListener(Sink.INPUT)
     public void process(Message<?> message) {
         Acknowledgment acknowledgment = message.getHeaders().get(KafkaHeaders.ACKNOWLEDGMENT, Acknowledgment.class);
         if (acknowledgment != null) {
             System.out.println("Acknowledgment provided");
             acknowledgment.acknowledge();
         }
     }
    
    如果可以,如何在Kafka中配置重试期

    在最坏的情况下(也是最有可能的情况下),这是不受支持的,我们必须手动重试。你知道使用Kafka处理最终一致性的Spring云流应用程序的真实例子吗

    如果我们不执行acknowledge.acknowledge()会发生什么;卡夫卡会自动将该消息重新发送给该消费者吗

    不会。只要客户端打开,卡夫卡消费者就会按顺序阅读消息。Kafka不支持更复杂的确认模式,例如单个消息确认,只更新给定消费者组和分区主题的偏移量。Spring Cloud Stream支持在Spring Cloud Stream中对异步处理的消息进行手动确认(从而防止消息丢失)——但假设消息一旦被手动确认,其偏移量就会被保存,因此来自同一分区主题的所有以前的消息都将被视为“已读”。如果您想挑出失败的消息,可以使用DLQ支持,并让后续消费者接收它们。重新启动使用者将从上次保存的偏移量恢复读取,因此您可以选择不为一系列处理失败的消息保存偏移量

    Spring Cloud Stream使用者具有内置的重试和DLQ支持—请参阅中的
    enableDlq
    ,以及作为默认使用者属性的一部分提供的重试设置:

     @Autowired
     private PaymentBusiness paymentBusiness;
    
     @StreamListener(Sink.INPUT)
     public void process(Order order) {
         Acknowledgment acknowledgment = message.getHeaders().get(KafkaHeaders.ACKNOWLEDGMENT, Acknowledgment.class);
         if (acknowledgment != null) {
             paymentBusiness(order);            
             //If we don't get here because of an exception 
             //Kafka would retry...
             acknowledgment.acknowledge();
         }
     }