kafka生产者拦截器详细讲解,附带代码

文章介绍了Kafka0.10版本引入的Producer和Consumer拦截器功能,用于实现客户端的定制化控制逻辑。ProducerInterceptor允许用户在消息发送前和发送后进行定制化操作,例如修改消息内容。文中通过示例展示了如何创建和配置两个拦截器,InterceptorOne和InterceptorTwo,来改变消息的内容。在实际应用中,需要注意线程安全和拦截器的执行顺序。
摘要由CSDN通过智能技术生成

拦截器

Producer拦截器(interceptor)和Consumer端Interceptor是在Kafka 0.10版本被引入的,主要用于实现Client端的定制化控制逻辑。

对于Producer而言,Interceptor使得用户在消息发送前以及Producer回调逻辑前有机会对消息做一些定制化需求,比如修改消息等
可指定多个Interceptor按序作用于同一条消息从而形成一个拦截链(interceptor chain)

Intercetpor的实现接口是org.apache.kafka.clients.producer.ProducerInterceptor,其定义的方法包括:
onSend(ProducerRecord):该方法封装进KafkaProducer.send方法中,即运行在用户主线程中。在序列化前调用该方法。用户可以在该方法中对消息做任何操作
onAcknowledgement:该方法在消息被应答前或消息发送失败时调用,且通常都是在Producer回调逻辑触发前。运行在Producer的IO线程中,不要在该方法中放入很重的逻辑,否则会拖慢Producer的消息发送效率。
close:关闭Interceptor,主要用于执行一些资源清理工作。

Interceptor可能被运行在多个线程中,因此在具体实现时用户需要自行确保线程安全。
另外倘若指定了多个Interceptor,则Producer将按照指定顺序调用它们,并仅仅是捕获每个Interceptor可能抛出的异常记录到错误日志中而非在向上传递。这在使用过程中要特别留意。


02 测试

拦截器1

public class InterceptorOne implements ProducerInterceptor<Integer, String> {

    private static final Logger LOGGER = LoggerFactory.getLogger(InterceptorOne.class);

    @Override
    public ProducerRecord<Integer, String> onSend(ProducerRecord<Integer, String> record) {
        System.out.println("拦截器1 -- go");

        // 消息内容
        final String topic = record.topic();
        final Integer partition = record.partition();
        final Integer key = record.key();
        final String value = record.value();
        final Long timestamp = record.timestamp();
        final Headers headers = record.headers();

        // 拦截器拦下来之后改变原来的消息内容
        ProducerRecord<Integer, String> newRecord = new ProducerRecord<Integer, String>(topic, partition, timestamp, key, value+"1", headers);
        // 传递新的消息
        return newRecord;
    }

    @Override
    public void onAcknowledgement(RecordMetadata metadata, Exception exception) {
        System.out.println("拦截器1 -- back");
    }

    @Override
    public void close() {}

    @Override
    public void configure(Map<String, ?> configs) {
        // 这里的config就是消息发送方的config配置
        final Object classContent = configs.get(ProducerConfig.VALUE_SERIALIZER_CLASS_CONFIG);
        System.out.println(classContent);
    }
}

拦截器2

public class InterceptorTwo implements ProducerInterceptor<Integer, String> {

    private static final Logger LOGGER = LoggerFactory.getLogger(InterceptorTwo.class);

    @Override
    public ProducerRecord<Integer, String> onSend(ProducerRecord<Integer, String> record) {
        System.out.println("拦截器2 -- go");

        // 消息内容
        final String topic = record.topic();
        final Integer partition = record.partition();
        final Integer key = record.key();
        final String value = record.value();
        final Long timestamp = record.timestamp();
        final Headers headers = record.headers();

        // 拦截器拦下来之后改变原来的消息内容
        ProducerRecord<Integer, String> newRecord = new ProducerRecord<Integer, String>(topic, partition, timestamp, key, value+"2", headers);
        // 传递新消息
        return newRecord;
    }

    @Override
    public void onAcknowledgement(RecordMetadata metadata, Exception exception) {
        System.out.println("拦截器2 -- back");
    }

    @Override
    public void close() {}

    @Override
    public void configure(Map<String, ?> configs) {
        // 这里的config就是消息发送方的config配置
        final Object classContent = configs.get(ProducerConfig.VALUE_SERIALIZER_CLASS_CONFIG);
        System.out.println(classContent);
    }
}

发送方

public static void main(String[] args) {
    Map<String, Object> configs = new HashMap<>();
    configs.put(ProducerConfig.BOOTSTRAP_SERVERS_CONFIG, "120.77.206.207:9092");
    configs.put(ProducerConfig.KEY_SERIALIZER_CLASS_CONFIG, IntegerSerializer.class);
    configs.put(ProducerConfig.VALUE_SERIALIZER_CLASS_CONFIG, StringSerializer.class);

    // 保证等待确认的消息只有设置的这几个。如果设置为1,则只有一个请求在等待响应
    // 此时可以保证发送消息即使在重试的情况下也是有序的。
    configs.put(ProducerConfig.MAX_IN_FLIGHT_REQUESTS_PER_CONNECTION, 1);

    // 配置拦截器
    configs.put(ProducerConfig.INTERCEPTOR_CLASSES_CONFIG, "com.test.inter.interceptor.InterceptorOne,com.test.inter.interceptor.InterceptorTwo");

    KafkaProducer<Integer, String> producer = new KafkaProducer<Integer, String>(configs);
    ProducerRecord<Integer, String> record = new ProducerRecord<Integer, String>("topicName", 0, 1001, "this is message");
    producer.send(record, new Callback() {
        @Override
        public void onCompletion(RecordMetadata metadata, Exception exception) {
            if (exception == null) {
                System.out.println(metadata.offset());
            }
        }
    });
    producer.close();
}

输出
class org.apache.kafka.common.serialization.StringSerializer
class org.apache.kafka.common.serialization.StringSerializer
拦截器1 – go
拦截器2 – go
拦截器1 – back
拦截器2 – back
偏移量2

接收方收到的信息
this is message12

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值