继续浏览精彩内容
慕课网APP
程序员的梦工厂
打开
继续
感谢您的支持,我会继续努力的
赞赏金额会直接到老师账户
将二维码发送给自己后长按识别
微信支付
支付宝支付

如何停止项目中不需要的kafka监听

小王子LePetitPrince
关注TA
已关注
手记 3
粉丝 1
获赞 11

背景

组件式开发过程中常会遇到一些自己不需要的组件开启了太多的kafka监听的情况,会带来以下问题:

  1. kafka监听中打印太多日志,影响自己查看自己的日志信息,不利于排查定位问题。

  2. kafka监听频繁消费消息,占用大量时间片,影响项目响应效率,严重者还会导致启动会长时间无法正常响应请求。笔者就遇到大量无用kafka监听导致程序启动后一个多小时才能正常提供服务的情况。

目标:

因此,停止项目中自己不需要的kafka监听就变得尤其重要。我们希望:

  1. 程序启动时不开启任何监听。

  2. 需要开启kafka监听时,支持手动开启和关闭。

解决思路:

通过阅读spring源码我们发现,spring启动过程中kafka监听的启动过程如下:

1、KafkaListenerEndpointRegistrar实现了InitializingBean接口,初始化bean的时候会执行该接口的afterPropertiesSet()方法,在该方法中注册所有带有@KafkaListener的监听。

http://img1.mukewang.com/6088f2810001765112820469.jpg

2、在KafkaListenerEndpointRegistry类实现了SmartLifecycle接口,SmartLifecycle 是一个接口。当Spring容器加载所有bean并完成初始化之后,会接着回调实现该接口的类中对应的方法(start()方法)。在start方法中会启动监听。我们要做的就是重写该方法,在项目启动时不启动监听。

3、在KafkaBootstrapConfiguration配置类中注册KafkaListenerEndpointRegistry类的实例,实例名为:

org.springframework.kafka.config.internalKafkaListenerEndpointRegistry。这样每次程序启动,都会自动启动全部监听。

http://img3.mukewang.com/6088f0350001f06c12380435.jpg


于是,我们决定重写KafkaListenerEndpointRegistry类中的start方法,具体过程如下:

  1. 写一个类:TransitAlarmKafkaListenerEndpointRegistry继承KafkaListenerEndpointRegistry,重写start,在start方法中不启动监听。

  2. @Slf4j
    public class TransitAlarmKafkaListenerEndpointRegistry extends KafkaListenerEndpointRegistry {
        @Override
        public void start() {
            log.info("此处不自动启动kafka监听,请手动启动");
        }
    }
  3. 在配置类中使用@Bean注入该类的实例,命名为:

@Primary
@Configuration
public class TransitAlarmKafkaListenerEndpointRegistryConfig {
    @Bean(value = "org.springframework.kafka.config.internalKafkaListenerEndpointRegistry")
    public TransitAlarmKafkaListenerEndpointRegistry kafkaListenerContainerFactory() {
        return new TransitAlarmKafkaListenerEndpointRegistry();
    }
}

,这样在程序启动是会用TransitAlarmKafkaListenerEndpointRegistry代替KafkaListenerEndpointRegistry类的实例注入到KafkaBootstrapConfiguration中。

***********************************************************************************************************

此时,已经实现了程序启动时不启动任何监听。下面,还需要能够支持手动开启和关闭监听,具体过程如下:

  1. 启动监听:通过KafkaListenerEndpointRegistry的实例调用根据listenerId获取监听,调用start方法启动:

@Autowired
private KafkaListenerEndpointRegistry registry;

/**
 * 开启监听.
 *
 * @param listenerId 监听ID
 */
@Override
public void startListener(String listenerId) {
    //判断监听容器是否启动,未启动则将其启动
    if (!registry.getListenerContainer(listenerId).isRunning()) {
        registry.getListenerContainer(listenerId).start();
    }
}

  2.停止监听:通过KafkaListenerEndpointRegistry的实例调用根据listenerId获取监听,调用stop方法停止:

@Override
public void stopListener(String listenerId) {
    registry.getListenerContainer(listenerId).stop();
}

至此,真正实现了项目启动时不启动任何监听,可以手动开启和停止监听。





打开App,阅读手记
1人推荐
发表评论
随时随地看视频慕课网APP