前言:
拦截器这个概念相信大部分朋友都不会陌生,Spring MVC 拦截器相信大家都用过,拦截器的核心思想就是运行应用程序在不修改业务逻辑的前提下,动态的实现一组可插拔的事件处理器链,它可以在业务链路中的前后各个点进行对应的拦截,做一些统一的处理,Sping MVC 的拦截器大家都了解,本篇我们来分享一下 Kafka 的拦截器。
Kafka 系列文章传送门
Kafka 客户端工具使用分享【offsetexplorer】
什么是 Kafka 的拦截器?
Kafka 的拦截器分为 Producer 拦截器和 Consumer 拦截器,使用 Producer 拦截器可以在消息发送前及消息发送成功后植入自定义的业务逻辑,而 Consumer拦截器支持在消息消费前以及提交位移后编写特定逻辑,不管是 Producer 拦截器还是 Consumer 拦截器都支持拦截器链,可以将一系列的拦截器组装成一个拦截器链,Kafka 会按照添加顺序一次执行拦截器逻辑,Kafka 为我们提供了两个拦截器接口,分别是 ProducerInterceptor 和 ConsumerInterceptor,我们实现该接口重新方法实现自定义业务其逻辑即可。
ProducerInterceptor 源码分析
ProducerInterceptor 是 Kafka 的生产者拦截器,实现了 Configurable 接口,提供了 onSend、onAcknowledgement、close、configure 四个方法,方法的作用如下:
- onSend:该方法会在消息发送之前被调用,如果你想给发送出去的消息进行统一处理,可以从这里下手。
- onAcknowledgement:该方法会在消息成功提交或者发送失败后调用,我们的异步消息发送中有个 callback,onAcknowledgement 方法会在 callback 方法之前调用,需要注意的是该方法和 onSend 方法不是在同一个线程中调用,如果在这两个方法中使用贡献变量的时候就要特别注意,一般不建议在这个方法中加入过多的业务逻辑,否则会影响 Kafka 的性能。
- close:拦截器关闭前的处理。
- configure:初始化配置。
public interface ProducerInterceptor<K, V> extends Configurable {
ProducerRecord<K, V> onSend(ProducerRecord<K, V> var1);
void onAcknowledgement(RecordMetadata var1, Exception var2);
void close();
}
public interface Configurable {
void configure(Map<String, ?> var1);
}
ConsumerInterceptor 源码分析
ConsumerInterceptor 是 Kafka 的消费者拦截器,同样实现了 Configurable 接口,提供了 onConsume、onCommit、close、configure 四个方法,方法的作用如下:
- onConsume:该方法会在消费者正式消费之前被调用,如果你想对消息消费之前做一些统一处理,可以在该方法中实现。
- onCommit:该方法会在 Kafka 提交 offset 之后调用,通常可以在该方法中进行一些日志记录等。
- close:拦截器关闭前的处理。
- configure:初始化配置。
package org.apache.kafka.clients.consumer;
import java.util.Map;
import org.apache.kafka.common.Configurable;
import org.apache.kafka.common.TopicPartition;
public interface ConsumerInterceptor<K, V> extends Configurable, AutoCloseable {
ConsumerRecords<K, V> onConsume(ConsumerRecords<K, V> var1);
void onCommit(Map<TopicPartition, OffsetAndMetadata> var1);
void close();
}
自定义实现 Kafka 生产者拦截器
Kafka 给我们提供了生产者拦截器接口,现在我们自己来实现一个 Kafka 生产者拦截器,自定义 Kafka 生产者拦截器代码如下:
package com.order.service.interceptor;
import lombok.extern.slf4j.Slf4j;
import org.apache.kafka.clients.consumer.ConsumerInterceptor;
import org.apache.kafka.clients.consumer.ConsumerRecords;
import org.apache.kafka.clients.producer.ProducerInterceptor;
import org.apache.kafka.clients.producer.ProducerRecord;
import org.apache.kafka.clients.producer.RecordMetadata;
import java.util.Map;
/**
* @ClassName: MyKafkaProducerInterceptor
* @Author: Author
* @Date: 2024/10/31 11:11
* @Description:
*/
@Slf4j
public class MyKafkaProducerInterceptor implements ProducerInterceptor<Object, Object> {
//消息发送前的确认
@Override
public ProducerRecord<Object, Object> onSend(ProducerRecord<Object, Object> producerRecord) {
log.info("消息发送前操作");
return producerRecord;
}
//消息确认
@Override
public void onAcknowledgement(RecordMetadata recordMetadata, Exception e) {
log.info("消费发送后的回调");
}
//拦截器关闭后的操作
@Override
public void close() {
}
//初始化相关操作
@Override
public void configure(Map<String, ?> map) {
}
}
在实现 Kafka 生产者拦截器的代码中,我这里只是记录了日志,真正在项目中使用的时候,根据自己的业务需求增加业务