当与Apache Kafka Server的连接丢失时,如何使用Spring Kafka Listener停止微服务?

时间:2017-11-01 19:32:16

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

我目前正在实施一项微服务,该服务从Apache Kafka主题中读取数据。我在微服务中使用“spring-boot,版本:1.5.6.RELEASE”,在同一个微服务中使用“spring-kafka,版本:1.2.2.RELEASE”。这是我的kafka配置:

    @Bean
public Map<String, Object> consumerConfigs() {
    return new HashMap<String, Object>() {{
        put(ConsumerConfig.BOOTSTRAP_SERVERS_CONFIG, servers);
        put(ConsumerConfig.KEY_DESERIALIZER_CLASS_CONFIG, StringDeserializer.class);
        put(ConsumerConfig.VALUE_DESERIALIZER_CLASS_CONFIG, StringDeserializer.class);
        put(ConsumerConfig.GROUP_ID_CONFIG, groupIdConfig);
        put(ConsumerConfig.AUTO_OFFSET_RESET_CONFIG, autoOffsetResetConfig);
    }};
}

@Bean
public ConsumerFactory<String, String> consumerFactory() {
    return new DefaultKafkaConsumerFactory<>(consumerConfigs());
}

@Bean
public ConcurrentKafkaListenerContainerFactory<String, String> kafkaListenerContainerFactory() {
    ConcurrentKafkaListenerContainerFactory<String, String> factory = new ConcurrentKafkaListenerContainerFactory<>();
    factory.setConsumerFactory(consumerFactory());
    return factory;
}

我已通过@KafkaListener注释实现了侦听器:

@KafkaListener(topics = "${kafka.dataSampleTopic}")
public void receive(ConsumerRecord<String, String> payload) {
    //business logic
    latch.countDown();
}

当侦听器断开与Apache Kafka服务器的连接时,我需要能够关闭微服务。

当我杀死kafka服务器时,我在spring boot log中收到以下消息:

2017-11-01 19:58:15.721  INFO 16800 --- [      0-C-1] o.a.k.c.c.internals.AbstractCoordinator  : Marking the coordinator 192.168.0.4:9092 (id: 2145482646 rack: null) dead for group TestGroup

当我启动kafka sarver时,我得到:

2017-11-01 20:01:37.748  INFO 16800 --- [      0-C-1] o.a.k.c.c.internals.AbstractCoordinator  : Discovered coordinator 192.168.0.4:9092 (id: 2145482646 rack: null) for group TestGroup.

很明显,我的微服务中的Spring Kafka Listener能够检测Kafka服务器启动和运行的时间以及何时启动。在第But How Do We Exit?章中汇总Kafka The Definitive Guide的书中,据说需要在Consumer上调用wakeup()方法,以便抛出WakeupException。因此,我尝试使用@EventListener标记捕获两个事件(Kafka服务器向下和Kafka服务器向上),如Spring for Apache Kafka documentation中所述,然后调用wakeup()。但文档中的示例是关于如何检测空闲的消费者,这不是我的情况。有人可以帮我这个。提前谢谢。

1 个答案:

答案 0 :(得分:4)

我不知道如何获取服务器停机状态的通知(根据我的经验,消费者在poll()内进入紧密循环。)

但是,如果你搞清楚了,你可以停止监听器容器,它将唤醒消费者并退出紧密循环......

@Autowired
private KafkaListenerEndpointRegistry registry;

...

    this.registry.stop();
  

2017-11-01 16:29:54.290 INFO 21217 --- [ad | so47062346] o.a.k.c.c.internals.AbstractCoordinator:将协调器localhost:9092(id:2147483647 rack:null)标记为群组so47062346

     

2017-11-01 16:29:54.346 WARN 21217 --- [ntainer#0-0-C-1] org.apache.kafka.clients.NetworkClient:无法建立与节点0的连接。经纪人可能无法使用。

     

...

     

2017-11-01 16:30:00.643 WARN 21217 --- [ntainer#0-0-C-1] org.apache.kafka.clients.NetworkClient:无法建立与节点0的连接。经纪人可能无法使用。

     

2017-11-01 16:30:00.680 INFO 21217 --- [ntainer#0-0-C-1] essageListenerContainer $ ListenerConsumer:消费者已停止

您可以通过添加reconnect.backoff.ms来改善紧密循环,但poll()永远不会退出,因此我们无法发出空闲事件。

spring:
  kafka:
    consumer:
      enable-auto-commit: false
      group-id: so47062346
    properties:
      reconnect.backoff.ms: 1000

我想你可以启用空闲事件并使用计时器来检测你是否在一段时间内没有收到任何数据(或空闲事件),然后停止容器。