Kafka 生产者客户端基本使用

必要的参数

  • bootstrap.servers

该参数为 broker 地址,不需要全部都填,因为 kafka 会从当前 broker 中获取其他 broker 信息。不过为了某个 broker 挂掉,一般填多个 broker 地址

  • key.serializer

消息 key 如何序列化

  • value.serializer

消息内容如何序列化

示例代码

1
2
3
4
5
6
7
Properties properties = new Properties();

properties.put(ProducerConfig.BOOTSTRAP_SERVERS_CONFIG, "127.0.0.1:9092");

properties.put(ProducerConfig.KEY_SERIALIZER_CLASS_CONFIG, StringSerializer.class.getName());

properties.put(ProducerConfig.VALUE_SERIALIZER_CLASS_CONFIG, StringSerializer.class.getName());

生产者拦截器

在消息发送前,对消息进行处理,该动作发生在序列化器分区器之前。

实现 org.apache.kafka.clients.producer.ProducerInterceptor 接口,即可自定义拦截器

介绍一下接口定义的方法

  • ProducerRecord<K, V> onSend(ProducerRecord<K, V> record)

在消息发送之前,可以对消息进行处理

  • void onAcknowledgement(RecordMetadata metadata, Exception exception

消息被应答之前或者消息发送失败时被调用

  • void close()

producer 被关闭时,会调用

kafka 允许配置拦截器链,多个拦截器用 , 号隔开即可。

1
properties.put(ProducerConfig.INTERCEPTOR_CLASSES_CONFIG, TestProducerInterceptor.class.getName() + "," + TestProducerInterceptor2.class.getName());

序列化

序列化发生在分区器之前
实现 org.apache.kafka.common.serialization.StringSerializer 接口即可自定义序列化

介绍一下接口定义的方法

  • void configure(Map<String, ?> configs, boolean isKey)

StringSerializer 实现中,用于设置编码

  • byte[] serialize(String topic, String data)

定义如何序列化

  • void close()

producer 关闭时,被调用

分区器

实现 org.apache.kafka.clients.producer.Partitioner 即可自定义分区器

kafka 可按 key 进行哈希(MurmurHash2),将消息发往同一个分区。如果未指定 key,那么将会把消息发往随机的一个分区。

介绍一下接口定义的方法

  • int partition(String topic, Object key, byte[] keyBytes, Object value, byte[] valueBytes, Cluster cluster)

定义发往哪个分区;具体的实现可参考DefaultPartitioner

  • void close()

producer 关闭时,被调用

与 RocketMQ 异同

  1. kafka 一致,rocketMQ 允许生产者将消息发送到指定的 ‘partition’ 中
  2. rocketMQ 没有 序列化器 的概念。消息内容由 rocketMQ 自行序列化
  3. 从个人目前的使用情况,rocketMQ 也没有提供类似 拦截器 概念
  4. rocketMQ 提供了 hock 以此在消息发送前,和消息发送后,对消息进行处理

例如:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
DefaultMQProducer producer = new DefaultMQProducer("default");

producer.getDefaultMQProducerImpl().registerSendMessageHook(new SendMessageHook() {
@Override
public String hookName() {
return null;
}

@Override
public void sendMessageBefore(SendMessageContext context) {

}

@Override
public void sendMessageAfter(SendMessageContext context) {

}
});