1.引入依赖
根据自己使用的kafka版本导入相应的kafka客户端依赖版本
<!--kafka 3.2.0-->
<dependency>
<groupId>org.apache.kafka</groupId>
<artifactId>kafka-clients</artifactId>
<version>3.2.0</version>
</dependency>
2.编码demo
public static void main(String[] args) {
//1.配置信息
Properties properties = new Properties();
properties.setProperty(ProducerConfig.BOOTSTRAP_SERVERS_CONFIG,"192.168.3.107:9092");
properties.setProperty(ProducerConfig.KEY_SERIALIZER_CLASS_CONFIG,StringSerializer.class.getName());
properties.setProperty(ProducerConfig.VALUE_SERIALIZER_CLASS_CONFIG,StringSerializer.class.getName());
//2.发送消息
KafkaProducer kafkaProducer = new KafkaProducer(properties);
for (int i = 0; i < 5; i++) {
ProducerRecord producerRecord = new ProducerRecord("test1","key1","消息"+i);
kafkaProducer.send(producerRecord, new Callback() {
@Override
public void onCompletion(RecordMetadata metadata, Exception exception) {
if (Objects.isNull(exception)){
System.out.println("发送成功!topic:"+metadata.topic()+"|分区:"+metadata.partition());
}
}
});
}
//3.关闭客户端连接
kafkaProducer.close();
}
2.1 配置信息
配置信息主要是指定kafka客户端地址;key value序列化方式
2.2 创建kafka生产者
需要传入上一步的配置properties
2.3 封装要发送给kafka的消息记录
- topic: 指定消息发送到那个topic
- partition: 指定消息发送到那个分区
- key:指定消息的key
- value:具体要发送的消息内容
如果不指定partition参数,会走默认的分区策略。默认分区策略又分为指定了key和没有指定key:
- 没有指定key:stickyPartitionCache.partition(topic, cluster)
随机选取一个分区,并一直使用,直到batch 16k满了或者等待时间linger.ms到了,下一次会选另一个分区
- 指定了key:DefaultPartitioner#partition#{Utils.toPositive(Utils.murmur2(keyBytes)) % numPartitions}
对key取hash,然后对分区数进行取模
2.4 发送消息以及回调函数
通过kafkaProducer.send()方法做最后的消息发送,send方法可选的指定回调函数CallBack,当消息发送成功或者失败,会回调该函数里的内容。这样,我们可以在消息发送失败时候,做一些日志记录,或者其它的业务操作。
3.验证
我们可以通过kafka的命令行消费端脚本,启动一个窗口,消费投递到kafka,指定topic的消息
./bin/kafka-console-consumer.sh --bootstrap-server 192.168.3.107:9092 --topic test1
4.如何自定义分区器
可以做一些消息的过滤,自定义分发规则。
1.自定义一个类,实现Partitioner接口,重写partition方法的逻辑,返回需要的分区
2.在初始化生产者对象,指定properies属性时候,指定分区器
producer的一些常用配置参数
Properties properties = new Properties();
//配置broker地址
properties.put(ProducerConfig.BOOTSTRAP_SERVERS_CONFIG, "192.168.3.107:9092");
//配置key value序列化方式
properties.put(ProducerConfig.KEY_SERIALIZER_CLASS_CONFIG,StringSerializer.class.getName());
properties.put(ProducerConfig.VALUE_SERIALIZER_CLASS_CONFIG,StringSerializer.class.getName());
//配置自定义的分区器
properties.put(ProducerConfig.PARTITIONER_CLASS_CONFIG, MyPartitioner.class.getName());
//消息的压缩方式:none,gzip,snappy,lz4,zstd
properties.put(ProducerConfig.COMPRESSION_TYPE_CONFIG,"snappy");
//缓冲队列总大小,默认32M
properties.put(ProducerConfig.BUFFER_MEMORY_CONFIG,33554432);
//最长等待多久投送消息
properties.put(ProducerConfig.LINGER_MS_CONFIG,1);
//每批次消息最大大小,默认16k
properties.put(ProducerConfig.BATCH_SIZE_CONFIG,16384);
//ack 0:不需要ack;1:leader收到数据后就返回ack; -1:leader和isr队列里所有节点收到数据后才ack
properties.put(ProducerConfig.ACKS_CONFIG,-1);
//.....生产者还有很多其它参数可以设置
KafkaProducer kafkaProducer = new KafkaProducer(properties);
问题
- 如果存在生产端代码连接不上broker,可以从以下几个方面排查:
- 检查下kafka的server是否已经起来了
- 如果是本地起的虚拟机,关闭防火墙;如果是云服务器,记得添加安全组策略
- 再telnet下是否通
- 将kafka配置文件server.properties如下配置注释打卡,并修改为自己虚拟机的ip尝试一下修改,
- 如果你是先发送消息,后面再打开的消费端控制台,你可能也没办法消费到消息
- 命令行添加
--from-beginning
参数,设置为从最开始的消息开始消费