引言
- 生产者(Producer)就是负责向Kafka发送消息的应用程序;
- 消费者(Consumer)就是可以从Kafka订阅主题,并从订阅的主题中拉取消息的应用程序;
- 对于Kafka来说,生产者和消费者都属于客户端;
生产者 vs 消费者
线程安全
- 生产者KakfaProducer是线程安全的,可以在多个线程中共享KafkaProducer实例,也可以将Kafka实例进行池化来供其他线程调用;
- 消费者KafkaConsumer是非线程安全的;
1. 生产者Java客户端
使用Java开发生产者/消费者客户端需要先引入Pom依赖:
<!-- 使用Kafaka生产者/消费者客户端需要的依赖 -->
<dependency>
<groupId>org.apache.kafka</groupId>
<artifactId>kafka-clients</artifactId>
<version>2.0.0</version>
</dependency>
- 注意:kafka从2.0.0版本开始,不再支持JDK7及以下的版本!
生产者客户端代码:
/**
* Java生产者客户端
*/
public class ProducerFastStart {
public static final String brokerList = "localhost:9092";
public static final String topic = "topic-learn";
/**
* 构建生产者客户端配置参数
*/
public static Properties initConfig() {
Properties proper = new Properties();
proper.put("bootstrap.servers", brokerList);
proper.put("key.serializer", "org.apache.kafka.common.serialization.StringSerializer");
proper.put("value.serializer", "org.apache.kafka.common.serialization.StringSerializer");
proper.put("client.id", "producer.client.id.demo");
return proper;
}
public static void main(String[] args) {
Properties proper = initConfig();
// 创建一个生产者客户端实例
KafkaProducer<String, String> producer = new KafkaProducer<>(proper);
// 构建所需要发送的消息
ProducerRecord<String, String> record = new ProducerRecord<>(topic, "Hello,Kafka");
// 发送消息
producer.send(record);
// 关闭生产者客户端实例
producer.close();
}
}
bootstrap.servers
、key.serializer
和value.serializer
是生产者客户端连接kafak必备的参数;- 为了防止参数名记错,可以使用
ProductConfig
的常量配置,每一个生产者客户端需要的参数都有一个常量名; - 序列化器要使用全类别(带包名),为了防止字符串写错,可以使用
StringSerializer.class.getName()
,其中getName()
方法是获取全限定类名,getShortName()
方法是只获取类名;
必备参数配置
bootstrap.servers
:连接Kafka集群所需要的broker地址清单。可以设置一个或多个,中间以逗号隔开,默认值是"";- 注意:这里并非需要所有的broker地址,因为生产者会从给定的broker里查找其他broker的信息。不过建议至少要配置两个以上的broker地址信息,当其中任意一台宕机时,生产者仍然可以连接到kafka集群上;
key.serializer
和value.serializer
:broker端接收的消息必须以字节数组byte[]
的形式存在,所以在将消息发往broker之前需要将消息中对应的key
和value
做相应的序列化来转换成字节数组(在消费者客户端再使用对应的反序列化类将字节数组反序列化回来);- 这两个参数都无默认值;
client.id
:用来设定KafkaProducer对应客户端的id,默认值为"",如果客户端不设置,则KafkaProducer会自动生成一个非空字符串;- 注意:这个参数不是必备参数;
- 其他参数见
000-参数配置
;
2. 消息发送模式
生产者实例是KafkaProducer
,发送的消息是ProducerRecord
:
/**
* 消息 ProducerRecord 的成员属性
*/
public class ProducerRecord<K, V> {
private final String topic;
private final Integer partition;
private final Headers headers;
private final K key;
private final V value;
private final Long timestamp;
// ... 省略成员方法
- ProducerRecord接收的泛型<K,V>分别是消息的
key
和value
的类型; topic
属性指定消息要发送到哪个主题;value
是消息内容;topic
和value
属性是必填项;parition
指定消息要发送的分区,如果不指定partition字段,则由分区器根据key
字段计算partition
的值;
消息发送方法send()
有两个重载方法:
/**
* KafkaProducer的send方法签名
*/
public Future<RecordMetadata> send(ProducerRecord<K, V> record);
public Future<RecordMetadata> send(ProducerRecord<K, V> record, Callback callback);
- 方法的返回类型是
Future<RecordMetadata>
,代表方法本身就是异步的,返回的Future
对象可以使调用方稍后获得发送的结果; - 第二个重载的方法接收一个
Callback
的回调函数,Kafka在返回响应时调用该函数来实现异步的发送确认;
所以,生产者发送消息可以有三种模式:发后即忘(fire-and-forget)、同步(sync)和异步(async);