Kafka生产者客户端详解

本文详细介绍了Kafka生产者客户端的特性,包括其线程安全性质、Java客户端配置、消息发送模式(发后即忘、同步、异步)以及消息发送流程中的拦截器、序列化器、分区器。重点讨论了消息确认、异常重试机制,同时分析了生产者客户端的整体架构,包括主线程与Sender线程、消息累加器RecordAccumulator和已发送未响应缓存InFlightRequests的作用。
摘要由CSDN通过智能技术生成

引言

  • 生产者(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.serverskey.serializervalue.serializer是生产者客户端连接kafak必备的参数;
  • 为了防止参数名记错,可以使用 ProductConfig的常量配置,每一个生产者客户端需要的参数都有一个常量名;
  • 序列化器要使用全类别(带包名),为了防止字符串写错,可以使用StringSerializer.class.getName(),其中getName()方法是获取全限定类名,getShortName()方法是只获取类名;
必备参数配置
  • bootstrap.servers:连接Kafka集群所需要的broker地址清单。可以设置一个或多个,中间以逗号隔开,默认值是"";
    • 注意:这里并非需要所有的broker地址,因为生产者会从给定的broker里查找其他broker的信息。不过建议至少要配置两个以上的broker地址信息,当其中任意一台宕机时,生产者仍然可以连接到kafka集群上;
  • key.serializervalue.serializer:broker端接收的消息必须以字节数组byte[]的形式存在,所以在将消息发往broker之前需要将消息中对应的keyvalue做相应的序列化来转换成字节数组(在消费者客户端再使用对应的反序列化类将字节数组反序列化回来);
    • 这两个参数都无默认值;
  • 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>分别是消息的keyvalue的类型;
  • topic属性指定消息要发送到哪个主题;
  • value是消息内容;
  • topicvalue属性是必填项;
  • 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);

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值