kafka_自定义Interceptor_producer

本文介绍了如何在ApacheKafka生产者中使用自定义Interceptor进行消息发送前的操作(如添加时间戳)和发送后的计数跟踪。文章详细解释了ProducerInterceptor接口的方法,并提供了两个示例:My_Interceptor_Timestamp用于添加时间戳,My_Interceptor_ResultCallback用于记录发送成功和失败的消息数。
摘要由CSDN通过智能技术生成

自定义Interceptor

​ 对于 producer 而言,interceptor 使得用户在消息发送前以及 producer 回调逻辑前有机会对消息做一些定制化需求,比如修改消息等。同时,producer 允许用户指定多个 interceptor按序作用于同一条消息从而形成一个拦截链(interceptor chain)。Intercetpor 的实现接口org.apache.kafka.clients.producer.ProducerInterceptor,其定义的方法包括:

(1)configure(configs)
获取配置信息和初始化数据时调用。
(2)onSend(ProducerRecord):
该方法封装进 KafkaProducer.send 方法中,用户可以在该方法中对消息做任何操作,但最好保证不要修改消息所属的 topic 和分区
(3)onAcknowledgement(RecordMetadata, Exception):
该方法会在消息从 RecordAccumulator 成功发送到 Kafka Broker 之后,或者在发送过程中失败时调用。并且通常都是在 producer 回调逻辑触发之前。onAcknowledgement 运行在producer 的 IO 线程中,因此不要在该方法放入很重的逻辑,否则会拖慢 producer 的消息发送效率
(4)close:
关闭 interceptor,主要用于执行一些资源清理工作

注意:interceptor 可能被运行在多个线程中,因此在具体实现时用户需要自行确保线程安全

1案例需求:

实现一个简单的双interceptor组成的拦截链。第一个interceptor会在消息发送前将时间戳信息加到消息value的最前部;第二个interceptor会在消息发送后更新成功发送消息数或失败发送消息数。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

1,java参考代码,详情见代码内:

My_Interceptor_Timestamp

package com.itwise.kafka.interceptor;

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;

/*
         * 自定义拦截器进行接收然后再数据前面添加一个时间戳
         * 此拦截器是拦截生产者要发送消息之前
         *ProducerRecord 是之前创建的生产者
         *
         * */
public class My_Interceptor_Timestamp implements ProducerInterceptor<String,String> {


    @Override
    public ProducerRecord<String, String> onSend(ProducerRecord<String, String> producerRecord) {
//        定义一个字符串,将系统时间戳与要发送的消息拼接起来
        String Timestamp_value =System.currentTimeMillis()+"--"+producerRecord.value();
//        重新定义一个 ProducerRecord1(生产者 记录) 与producerRecord 的参数 并将其返回
        ProducerRecord<String, String> producerRecord1 = new ProducerRecord<>(
                producerRecord.topic(),
                producerRecord.partition(),
                producerRecord.timestamp(),
                producerRecord.key(), Timestamp_value);

        return producerRecord1;
    }

//    ack应答机制
    @Override
    public void onAcknowledgement(RecordMetadata recordMetadata, Exception e) {

    }

    @Override
    public void close() {

    }

    @Override
    public void configure(Map<String, ?> map) {

    }
}

2,自定义拦截器进行条件判断成功了多少条消息

My_Interceptor_ResultCallback

package com.itwise.kafka.interceptor;

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;

/*
         * 自定义拦截器进行条件判断成功了多少条消息,失败了多少条消息
         * 此拦截器是拦截生产者要发送消息之前
         *ProducerRecord 是之前创建的生产者
         *
         * */
public class My_Interceptor_ResultCallback implements ProducerInterceptor<String,String> {

//    定义参数,统计次数
    private int success;
    private int fail;

    @Override
    public ProducerRecord<String, String> onSend(ProducerRecord<String, String> producerRecord) {
//        不用定义也一定要有返回值
        return producerRecord;
    }

//    ack应答机制
    @Override
    public void onAcknowledgement(RecordMetadata recordMetadata, Exception e) {

        if (e==null){
//            成功
            success+=1;
        }else {
//            失败
            fail+=1;
        }
    }

//    关闭之前返回条数
    @Override
    public void close() {
        System.out.println("发送数据的成功的条数是:"+success);
        System.out.println("发送数据的失败的条数是:"+fail);

    }

    @Override
    public void configure(Map<String, ?> map) {

    }
}

3,生产者:注意调用两个拦截器的关键代码,其他保持不变

package com.itwise.kafka.interceptor;


import org.apache.kafka.clients.producer.KafkaProducer;
import org.apache.kafka.clients.producer.ProducerConfig;
import org.apache.kafka.clients.producer.ProducerRecord;

import java.util.ArrayList;
import java.util.List;
import java.util.Properties;

public class My_Interceptor_Producer {
    /**
     * 链接哪一个topic分区
     * 实验的主题是itwise
     */
    public static void main(String[] args) {
//        定义参数,通过这个属性对象将参数传递进来
        Properties props = new Properties();
//        连接kafka集群
        props.put("bootstrap.servers", "node2:9092");
//        应答机制--all(-1)
        props.put("acks", "all");
//        重试的次数,重连
        props.put("retries", 1);
//        每个批次大小(16k)
        props.put("batch.size", 16384);
//        等待时间
        props.put("linger.ms",1);
//        RecordAccumulator 缓冲区大小 32MB
        props.put("buffer.memory", 33554432);
//        serializer序列化配置;
        props.put("key.serializer", "org.apache.kafka.common.serialization.StringSerializer");
        props.put("value.serializer", "org.apache.kafka.common.serialization.StringSerializer");

//        !!!!!!添加拦截器!!!!  先定义一个拦截器泛型集合
        ArrayList<Object> Interceptor_lists = new ArrayList<>();
        Interceptor_lists.add("com.itwise.kafka.interceptor.My_Interceptor_ResultCallback");
        Interceptor_lists.add("com.itwise.kafka.interceptor.My_Interceptor_Timestamp");
//        将拦截器与生产者链接 ProducerConfig静态方法,连的是Interceptor_lists集合
        props.put(ProducerConfig.INTERCEPTOR_CLASSES_CONFIG,Interceptor_lists);

//        需要传参数
        KafkaProducer<String, String> stringStringKafkaProducer
                = new KafkaProducer<String, String>(props);

//        发送消息
        //发送消息:
        for (int i = 0; i < 2000; i++) {
stringStringKafkaProducer.send(new ProducerRecord<String,String>("itwise","itwise-"+i));
//stringStringKafkaProducer.send(new ProducerRecord<String,String>("itwise",0,null,"itwise->"+i));
           /* stringStringKafkaProducer.send(new ProducerRecord<String,String>
                    ("itwise", UUID.randomUUID().toString(),"itwise-->>"+i));*/
        }
//        关闭IO流
        stringStringKafkaProducer.close();
    }
}

4,linux启动消费者

可以看见之前订阅的消息
[itwise@node2 ~]$ kafka-console-consumer.sh -consumer.config /opt/module/kafka_2.11-2.4.1/config/consumer.properties -bootstrap-server node2:9092 --topic itwise
在末尾追加消息:
[itwise@node2 ~]$ kafka-console-consumer.sh --bootstrap-server node2:9092 --topic itwise


5,实验结果:

dule/kafka_2.11-2.4.1/config/consumer.properties -bootstrap-server node2:9092 --topic itwise
在末尾追加消息:
[itwise@node2 ~]$ kafka-console-consumer.sh --bootstrap-server node2:9092 --topic itwise


5,实验结果:

![外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传](https://img-home.csdnimg.cn/images/20230724024159.png?origin_url=C%3A%5CUsers%5CAdministrator%5CAppData%5CRoaming%5CTypora%5Ctypora-user-images%5Cimage-20240314195740618.png&pos_id=img-SZsIy1lq-1713315101712)
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值