史上最差的kafka教程第五天(kafka避免重复消费与避免异常处理死循环)
kafka避免重复消费实际上是修改offset的提交方式。但是如果前一段消费失败通常是采取继续发送到该topic下,但是调用的服务已经挂了,如果
服务一直处于异常意味着,要不停的重复失败的数据。会变成死循环,不停报错,浪费系统资源。
解决方案:将处理失败的信息发送到指定topic底下,该topic监听器采用定时器开关,每天定时去读取操作失败的数据。
具体操作:
- 设置监听器启动方式或者不设置
- 设置需要设置定时开关监听器的id
- 利用定时器定时开关指定监听器
@Component public class TaskListener{ private static final Logger log= LoggerFactory.getLogger(TaskListener.class); @Autowired private KafkaListenerEndpointRegistry registry; @Autowired private ConsumerFactory consumerFactory;
//如果在kafkaconfiguration里面有设置过的话,不需要再设置 @Bean public ConcurrentKafkaListenerContainerFactory delayContainerFactory() { ConcurrentKafkaListenerContainerFactory container = new ConcurrentKafkaListenerContainerFactory(); container.setConsumerFactory(consumerFactory); //禁止自动启动,这个是全局监听器的。可以根据具体业务设置 container.setAutoStartup(false); return container; } @KafkaListener(id = "durable", topics = "topic.durable",containerFactory = "delayContainerFactory") public void durableListener(String data) { //这里做数据持久化的操作 log.info("topic.quick.durable receive : " + data); }
}
@Component @EnableScheduling @Slf4j public class TaskDemo { @Autowired private KafkaListenerEndpointRegistry registry; @Scheduled(cron = "0/30 * * * * ?") public void startRun(){ //判断监听容器是否启动,未启动则将其启动 if (!registry.getListenerContainer("durable").isRunning()) { log.info("开启监听器"); registry.getListenerContainer("durable").start(); } } @Scheduled(cron = "0/10 * * * * ?") public void stopRun(){ //判断监听容器是否启动,未启动则将其启动 if (registry.getListenerContainer("durable").isRunning()) { log.info("关闭监听器"); registry.getListenerContainer("durable").stop(); } }