代码不会写怎么办?看官方写好的类,照着写一遍就行!
一、生产者
实现类
无需实现任何类,需要开启main方法
基本思路
new Properties() 来配置一些参数——>new KafkaProducer() 创建一个生产者对象,并将配置信息传入 ——> 调用生产者对象的send()方法来发送数据
代码示例
public static voidmain(String[] args) {//producer的配置信息
Properties props = newProperties();//服务器的地址和端口,也可用ProducerConfig中的属性来代替//ProducerConfig.BOOTSTRAP_SERVERS_CONFIG
props.put("bootstrap.servers", "hadoop102:9092,hadoop103:9092,hadoop104:9092");//接受服务端ack确认消息的参数,0,-1,1
props.put("acks", "all");//如果接受ack超时,重试的次数
props.put("retries", 3);//sender一次从缓冲区中拿一批的数据量
props.put("batch.size", 16384);//如果缓冲区中的数据不满足batch.size,只要和上次发送间隔了linger.ms也会执行一次发送
props.put("linger.ms", 1);//缓存区的大小
props.put("buffer.memory", 33554432);//配置生产者使用的key-value的序列化器
props.put("key.serializer", "org.apache.kafka.common.serialization.IntegerSerializer");
props.put("value.serializer", "org.apache.kafka.common.serialization.StringSerializer");//,泛型,必须要和序列化器所匹配
Producer producer = new KafkaProducer<>(props);for (int i = 0; i < 10; i++){//发送数据,此处演示带回调函数的异步发送//异步带回调的发送
producer.send(new ProducerRecord("test2", i, "atguigu" + i), newCallback() {//一旦发送的消息被server通知了ack,此时会执行onCompletion()//RecordMetadata: 当前record生产到broker上对应的元数据信息//Exception: 如果发送失败,会将异常封装到exception返回
@Overridepublic voidonCompletion(RecordMetadata metadata, Exception exception) {//没有异常
if (exception==null){//查看数据的元数据信息
System.out.println("partition:"+metadata.topic()+"-"+metadata.partition()+",offset:"+metadata.offset());
}
}
});/**如果要实现同步发送,只需要调用get()方法,使main线程阻塞即可
RecordMetadata result=producer.send(new ProducerRecord()).get();*/producer.close();
}
二、拦截器
实现类
MyInterproter2 implementsProducerInterceptor
基本思路
在onsend()方法里对record进行业务逻辑的操作,之后封装成一个全新的ProducerRecord
代码示例
public class TimeStampInterceptor implements ProducerInterceptor{//拦截数据
@Overridepublic ProducerRecord onSend(ProducerRecordrecord) {
String newValue=System.currentTimeMillis()+"|"+record.value();return new ProducerRecord(record.topic(),record.key(),newValue);
}//当拦截器收到此条消息的ack时,会自动调用onAcknowledgement()
@Overridepublic voidonAcknowledgement(RecordMetadata metadata, Exception exception) {
}//Producer关闭时,调用拦截器的close()
@Overridepublic voidclose() {
}//读取Producer中的配置
@Overridepublic void configure(Mapconfigs) {
}
}
在Producer中设置
//拦截器链
ArrayList interCeptors = new ArrayList<>();//添加的是全类名,注意顺序,先添加的会先执行
interCeptors.add("com.atguigu.kafka.custom.TimeStampInterceptor");
interCeptors.add("com.atguigu.kafka.custom.CounterInterceptor");//设置拦截器
props.put(ProducerConfig.INTERCEPTOR_CLASSES_CONFIG,interCeptors);
三、分区器
实现类
MyPartitioner implements Partitioner
代码实现
public class MyPartitioner implementsPartitioner {//为每个ProduceRecord计算分区号//根据key的hashCode() % 分区数
@Overridepublic int partition(String topic, Object key, byte[] keyBytes, Object value, byte[] valueBytes, Cluster cluster) {//获取主题的分区数
List partitions =cluster.partitionsForTopic(topic);int numPartitions =partitions.size();return (key.hashCode() & Integer.MAX_VALUE) %numPartitions;
}//Producer执行close()方法时调用
@Overridepublic voidclose() {
}//从Producer的配置文件中读取参数,在partition之前调用
@Overridepublic void configure(Mapconfigs) {
System.out.println(configs.get("welcomeinfo"));
}
}
在producer中设置
props.put(ProducerConfig.PARTITIONER_CLASS_CONFIG,"com.atguigu.kafka.custom.MyPartitioner");