簡體   English   中英

如何在 spring kafka 生產者上實現重試?

[英]How to implement retries on spring kafka producer?

我想設置 3 次重試。 這是我正在想象的,如果生產者完成了 3 次重試並且仍然沒有發送消息,它應該 go 到本地主題(dlt)。

這就是我現在正在使用的東西。 這是配置

@Bean
    public ConcurrentKafkaListenerContainerFactory<?, ?> kafkaListenerContainerFactory(
            ConcurrentKafkaListenerContainerFactoryConfigurer configure,
            ConsumerFactory<Object, Object> kafkaConsumerFactory,
            KafkaTemplate<Object, Object> template) {
        ConcurrentKafkaListenerContainerFactory<Object, Object> factory = new ConcurrentKafkaListenerContainerFactory<>();
        configure.configure(factory, kafkaConsumerFactory);
        factory.setErrorHandler(new SeekToCurrentErrorHandler(new DeadLetterPublishingRecoverer(template), new FixedBackOff(0L, 2)));
        return factory;
    }

這是主要應用程序

@SpringBootApplication
@EnableKafka
@Retryable(value = Exception.class, maxAttemptsExpression = "3",
        backoff = @Backoff(delayExpression = "1000"))
public class KafkaApplication {

    public static void main(String[] args) throws Exception {
        ConfigurableApplicationContext context = SpringApplication.run(KafkaApplication.class, args);
        TestBean testBean = context.getBean(TestBean.class);
        while(true){
            for (int i = 0; i < 50; i++) {
                try{
                    Thread.sleep(5000);

                } catch (Exception e){
                    System.out.println("exception" + e.getMessage());
                }
                testBean.send("This is message " + i);
            }
            context.getBean(Consumer.Listener.class).latch.await(60, TimeUnit.SECONDS);
        }

    }

這是聽眾

@KafkaListener(topics = AppConfiguration.topic, groupId = AppConfiguration.groupid, containerFactory = "kafkaListenerContainerFactory")
        public void listen(@Payload String message, @Header(KafkaHeaders.RECEIVED_PARTITION_ID) int partition) {
            try{
                System.out.println("Successfully Received: " + message + " (partition: " + partition + ")");
                this.latch.countDown();
            } catch (Exception e){
                System.out.println("Error in sending record");
                System.out.println(e);
                e.printStackTrace();
            }

如果只想重試 3 次,又不想太多組件冗余,可以選擇使用 try catch 配合本地 Queue 實現。

最簡單的方法是在發生錯誤后立即重試 當然,很多時候你會想每隔幾分鍾重試一次 這時候只需要將錯誤信息放入catch中的一個隊列中,然后再從另一個方法中取出隊列數據再發送即可。 不過也許kafka已經為你解決了這個問題,有些異常可以自動重試,建議你理解: https://kafka.apache.org/21/documentation.html#producerconfigs

下面是最簡單的實現:

public void sendToKafka(String topic, String key, String value, Integer retryTimes) {
        try {
            kafkaTemplate.send(topic, key, value);
        } catch (Exception e) {
            //if retryTimes
            if (retryTimes < 3) {
                sendToKafka(topic, key, value, ++retryTimes);
            }
        }
    }

如此處所述,Kafka 直接在其生產者中支持配置。

但是,最好的方法是使用delivery.timeout.msrequest.timeout.msretry.backoff.ms屬性的組合來控制在給定時間段內發生的重試次數,如文檔中所述。

如果你使用的是 Spring Boot,你可以配置一個 bean 如下:

  @Bean(name = "ProducerConfig")
  public Map<String, Object> producerConfig() {
    return Map.of(
        ProducerConfig.BOOTSTRAP_SERVERS_CONFIG,
        bootstrapServers,
        // Enable safely ordered retries
        ProducerConfig.ENABLE_IDEMPOTENCE_CONFIG, "true",
        ProducerConfig.ACKS_CONFIG, "all",
        // Config number of retries
        ProducerConfig.DELIVERY_TIMEOUT_MS_CONFIG, 5000,
        ProducerConfig.REQUEST_TIMEOUT_MS_CONFIG, 200, 
        ProducerConfig.RETRY_BACKOFF_MS_CONFIG, 500
    );

  }

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM