1.生产者组件
生产者,发送消息到broker,流程图如下:
流程大概如下:
1.创建ProducerRecord对象,对象内指定目标主题和发送内容,同时还可以指定键和要发送到的分区。
2.创建定制的序列化器或使用现有的序列化器,Kafka支持的序列化协议有JSON、Protobuf、arvo等,其中arvo是Kafka本身支持的定制化协议格式。
3.对象通过序列化器序列化后,会被发往指定分区。如果ProducerRecord对象未指定分区,则交由分区器根据对象的键来选择一个分区。
4.接着数据会被传到一个记录批次里,这个批次的数据会被发往相同的topic和Partition
5.Kafka服务器处理上面的发送请求,同时抛出成功与否的响应消息,如果失败则重试。
2.创建生产者
2.1.设置必要参数
private static Properties initConfigProperties() {
Properties properties = new Properties();
properties.put("key.serializer", "org.apache.kafka.common.serialization.StringSerializer");
properties.put("value.serializer", "org.apache.kafka.common.serialization.StringSerializer");
properties.put("bootstrap.servers", "127.0.0.1:9092");
return properties;
}
2.2发送消息
发送消息有三种:发后即忘、同步发送、异步发送
2.2.1发后即忘
消息发送个服务器,并不关心是否正常到达。大多数情况下,消息会正常到达,同时生产者会自动重试,但是存在丢失消息风险。
public static void main(String[] args) {
KafkaProducer<String, String> producer = new KafkaProducer<>(initConfigProperties());
ProducerRecord<String, String> record = new ProducerRecord<>(topic, "hello, Kafka!");
try {
producer.send(record);
} catch (Exception e) {
e.printStackTrace();
}
producer.close();
}
2.2.2同步发送
调用send()方法发送消息,开启send线程,能够返回一个Future对象,调用get()方法进行等待,能够知道消息是否发送成功。
public static void main(String[] args) {
KafkaProducer<String, String> producer = new KafkaProducer<>(initConfigProperties());
ProducerRecord<String, String> record = new ProducerRecord<>(topic, "hello, Kafka!");
try {
producer.send(record).get();
} catch (Exception e) {
e.printStackTrace();
}
producer.close();
}
2.2.3异步发送
调用send()方法,并指定一个回调函数,服务器在响应时间调用该函数。
public static void main(String[] args) throws InterruptedException {
KafkaProducer<String, String> producer = new KafkaProducer<>(initConfigProperties);
ProducerRecord<String, String> record = new ProducerRecord<>(topic, "hello, Kafka!");
try {
producer.send(record, new Callback() {
@Override
public void onCompletion(RecordMetadata metadata, Exception exception) {
if (exception == null) {
System.out.println(metadata.partition() + ":" + metadata.offset());
}
}
});
} catch (Exception e) {
e.printStackTrace();
}
}
2.3.序列化器
创建生产者,必须指定一个序列化器,因为需要把对象转换为字节数组才能通过网络发送个kafka服务器。
Kafka自带的序列化器,对应的序列化方式和Java类型如下:
(1)可以自定义序列化方式,需要实现Serializer接口;
(2)使用Avro、Json、Thrif、ProtoBuf等工具;
2.4分区器
ProducerRecord对象包含了topic key value。大多数情况,都会用到key,有两个好处:一是,可以作为消息的附加消息;二是,决定消息被写到哪个分区。key可以为null,若为null则需要使用默认的分区器。自定义分区器,需要实现partitioner接口。
2.5生产者重要参数
kafka的producer的参数,不止上述代码给的四个,当然默认的参数值都是经过优化的,一般情况下不建议修改。详细的内容可以参考中文官网。
2.6其他
- producer是线程安全的,单线程不能够满足条件的时候,可以使用线程池发送消息;
- 0.9版本之前的生产者是scala client,通常称为old consumer,0.9版本之后的生产者是Java Client通常称为new consumer;
- 生产者在发送消息的时候,在序列化之前还有拦截器,但是拦截器是非必须的;