Producer拦截器(interceptor)和Consumer拦截器是在Kafka 0.10版本被引入的,主要用于实现clients端的定制化控制逻辑。
对于producer而言,interceptor使得用户在消息发送前以及producer回调逻辑前有机会对消息做一些定制化需求,比如修改消息等。同时,producer允许用户指定多个interceptor按序作用于同一条消息从而形成一个拦截链(interceptor chain)。Intercetpor的实现接口是org.apache.kafka.clients.producer.ProducerInterceptor,其定义的方法包括:
实现一个简单的双interceptor组成的拦截链。
第一个interceptor会在消息发送前将时间戳信息加到消息value的最前部;
第二个interceptor会在消息发送后更新成功发送消息条数或失败发送消息条数。
1). 使用IDEA工具创建Maven项目,并导入Kafka依赖
org.apache.kafka</groupId>
kafka-clients</artifactId>
0.11.0.0</version>
</dependency>
</dependencies>
2). 确保虚拟机已安装配置Zookeeper和Kafka
3). 启动Zookeeper和Kafka集群
1). 创建时间拦截器类
package com.learn.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;
public class TimeInterceptor implements ProducerInterceptor,String> {
public ProducerRecord,String> onSend(ProducerRecord,String> producerRecord) {
return new ProducerRecord,String>(producerRecord.topic(),producerRecord.partition(),producerRecord.timestamp(),producerRecord.key(),System.currentTimeMillis()+","+producerRecord.value().toString(),producerRecord.headers());
}
public void onAcknowledgement(RecordMetadata recordMetadata, Exception e) {
}
public void close() {
}
public void configure(Map, ?> map) {
}
}
2). 创建消息统计拦截器,统计发送消息成功和发送失败消息数,并在producer关闭时打印输出成功/失败的消息条数
package com.learn.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;
public class CountIncerceptor implements ProducerInterceptor,String> {
private long successNum = 0L;
private long errorNum = 0L;
public ProducerRecord, String> onSend(ProducerRecord, String> producerRecord) {
return producerRecord;
}
public void onAcknowledgement(RecordMetadata recordMetadata, Exception e) {
if(e == null){
successNum+=1;
}else{
errorNum+=1;
}
}
//Producer的close()方法执行完毕后再执行拦截器的close()方法
public void close() {
System.out.println("发送成功的数量为:"+successNum);
System.out.println("发送失败的数量为:"+errorNum);
}
public void configure(Map, ?> map) {
}
}
3). 创建producer主程序,配置中加入自定义的拦截器(两种方法)
package com.learn.kafka.Interceptor;
import org.apache.kafka.clients.producer.KafkaProducer;
import org.apache.kafka.clients.producer.ProducerConfig;
import org.apache.kafka.clients.producer.ProducerRecord;
import org.apache.kafka.common.serialization.StringSerializer;
import java.util.ArrayList;
import java.util.List;
import java.util.Properties;
public class CustomerProducer2 {
public static void main(String[] args) {
//参数配置
Properties prop = new Properties();
prop.put(ProducerConfig.BOOTSTRAP_SERVERS_CONFIG,"cos100:9092");
prop.put(ProducerConfig.KEY_SERIALIZER_CLASS_CONFIG, StringSerializer.class.getName());
prop.put(ProducerConfig.VALUE_SERIALIZER_CLASS_CONFIG,StringSerializer.class.getName());
prop.put(ProducerConfig.ACKS_CONFIG,"all");
prop.put(ProducerConfig.BATCH_SIZE_CONFIG,16384);
prop.put(ProducerConfig.LINGER_MS_CONFIG,1);
//将多个拦截器加入配置的方法有两个
//1.在配置参数后边添加,用,隔开,如下
prop.put(ProducerConfig.INTERCEPTOR_CLASSES_CONFIG,"com.learn.kafka.Interceptor.TimeInterceptor,com.learn.kafka.Interceptor.CountIncerceptor");
//2.将多个拦截器加入一个List集合中,然后将List加入配置中
// List interceptors = new ArrayList();
// interceptors.add("com.learn.kafka.Interceptor.TimeInterceptor");
// interceptors.add("com.learn.kafka.Interceptor.CountIncerceptor");
// prop.put(ProducerConfig.INTERCEPTOR_CLASSES_CONFIG,interceptors);
//创建Topic对象
KafkaProducer, String> producer = new KafkaProducer, String>(prop);
//调用send方法
for(int i=0;i<100;i++){
producer.send(new ProducerRecord, String>("test",i+"","message-"+i));
}
//关闭生产者
producer.close();
}
}
producer主程序编写完成后开启虚拟机消费者端口等待生产者生产发送数据
[root@cos100 kafka]# bin/kafka-console-consumer.sh --bootstrap-server cos100:9092 --topic test
运行producer主程序,控制台输出如下,说明自定义的消息统计拦截器生效并正常工作。
消费者端消费到的信息如下,说明自定义的时间拦截器也生效并正常工作,我们的双interceptor组成的拦截链生效。
1582560717345,message-4
1582560717345,message-6
1582560717346,message-10
1582560717346,message-12
1582560717346,message-13
1582560717346,message-14
1582560717346,message-18
1582560717347,message-19
1582560717347,message-20
1582560717347,message-24
...
完毕!