在Spring Cloud Stream Kafka中正确管理DLQ

时间:2018-07-09 13:46:06

标签: spring-boot apache-kafka spring-cloud-stream

我想使用kafka在Spring Cloud Stream中管理DLQ。

application.yaml

server:
    port: 8091
eureka:
    client:
        serviceUrl:
            defaultZone: http://IP:8761/eureka
spring:
    application:
        name: employee-consumer
    cloud:
        stream:
            kafka:
                binder:
                    brokers: IP:9092
                bindings:
                    greetings-in:
                        destination: greetings
                        contentType: application/json
                    greetings-out:
                        destination: greetings
                        contentType: application/json
            bindings:
                greetings-out:
                    consumer:
                        enableDlq: true
                        dlqName: dead-out
    kafka:
      consumer:
        group-id: A

您可以在我的配置中看到,我启用了dlq并将名称设置为dlq主题。

为了测试DLQ行为,我在某些消息上抛出了异常

我的听众组件

@StreamListener("greetings-out")
    public void handleGreetingsInput(@Payload Greetings greetings) throws Exception {
        logger.info("Greetings input -> {}", greetings);
        if (greetings.getMessage().equals("ciao")) {
            throw new Exception("eer");
        }
    }

这样,等于“ ciao”的消息将引发异常,并且在日志中,我看到它被处理了三遍

2018-07-09 13:19:57.256  INFO 1 --- [container-0-C-1] com.mitro.service.GreetingsListener      : Greetings input -> com.mitro.model.Greetings@3da9d701[timestamp=0,message=ciao]
2018-07-09 13:19:58.259  INFO 1 --- [container-0-C-1] com.mitro.service.GreetingsListener      : Greetings input -> com.mitro.model.Greetings@5bd62aaf[timestamp=0,message=ciao]
2018-07-09 13:20:00.262  INFO 1 --- [container-0-C-1] com.mitro.service.GreetingsListener      : Greetings input -> com.mitro.model.Greetings@c26f92b[timestamp=0,message=ciao]
2018-07-09 13:20:00.266 ERROR 1 --- [container-0-C-1] o.s.integration.handler.LoggingHandler   : org.springframework.messaging.MessagingException: Exception thrown while invoking com.mitro.service.GreetingsListener#handleGreetingsInput[1 args]; nested exception is java.lang.Exception: eer, failedMessage=GenericMessage [payload=byte[32], headers={kafka_offset=3, scst_nativeHeadersPresent=true, kafka_consumer=org.apache.kafka.clients.consumer.KafkaConsumer@510302cb, deliveryAttempt=3, kafka_timestampType=CREATE_TIME, kafka_receivedMessageKey=null, kafka_receivedPartitionId=0, contentType=application/json, kafka_receivedTopic=greetings-out, kafka_receivedTimestamp=1531142397248}]

这对我来说很好,但是我不明白为什么会创建一个名为“停顿”的主题(请看下面的图片)。 topics' view

我在做什么错了?

编辑1 :(仍然不会为DLQ创建主题)

server:
    port: 8091
eureka:
    client:
        serviceUrl:
            defaultZone: http://IP:8761/eureka
spring:
    application:
        name: employee-consumer
    cloud:
        stream:
            kafka:
                streams:
                    binder:
                        serdeError: sendToDlq
                binder:
                    brokers: IP:9092
                    auto-create-topics: true
                bindings:
                    greetings-out:
                        destination: greetings-out
                        contentType: application/json
                        consumer:
                          enableDql: true
                          dlqName: dead-out
                          autoCommitOnError: true
                          autoCommitOffset: true
            bindings:
                greetings-out:
                    destination: greetings-out
                    contentType: application/json
                    consumer:
                        enableDlq: true
                        dlqName: dead-out
                        autoCommitOnError: true
                        autoCommitOffset: true
    kafka:
      consumer:
        group-id: A

enter image description here

1 个答案:

答案 0 :(得分:3)

看起来您的属性被颠倒了;通用属性-destination,contentType-必须在spring.cloud.stream.bindings下。特定于kafka的属性(enableDlq,dlqName)必须位于spring.clound.stream.kafka.bindings下。

您将它们颠倒了。

编辑

(修改后的)配置存在两个问题。

  1. 键入enableDql而不是enableDlq
  2. 没有组-您不能与匿名使用者一起使用DLQ:
  

原因:java.lang.IllegalArgumentException:DLQ支持不适用于匿名订阅

这很好:

spring:
  application:
    name: employee-consumer
  cloud:
    stream:
      kafka:
        binder:
          brokers: localhost:9092
          auto-create-topics: true
        bindings:
          input:
            consumer:
              enableDlq: true
              dlqName: dead-out
              autoCommitOnError: true
              autoCommitOffset: true
      bindings:
        input:
          group: so51247113
          destination: greetings-out
          contentType: application/json

@SpringBootApplication
@EnableBinding(Sink.class)
public class So51247113Application {

    public static void main(String[] args) {
        SpringApplication.run(So51247113Application.class, args);
    }

    @StreamListener(Sink.INPUT)
    public void in(String in) {
        System.out.println(in);
        throw new RuntimeException("fail");
    }

    @KafkaListener(id = "foo", topics = "dead-out")
    public void dlq(Message<?> in) {
        System.out.println("DLQ:" + in);
    }

}