![](/img/trans.png)
[英]Spring Kafka Simple Producer and Consumer with Retries and DLQ
[英]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.ms 、 request.timeout.ms和retry.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.