一个正常的生产逻辑需要具备的步骤
- 配置生产者客户端参数以及相应的生产者实例
- 构建待发送的消息
- 发送消息
- 关闭生产者实例
生产者消息 productRecord<K,V>
String topic; // 主题
Integer partition; //分区号
Header headers; //消息头部 kafka0.11版本引入
K key; //键
V value; //值
long timestamp; // 消息时间戳
必要的参数
在Kafka生产者客户端KafkaProducer中有3个参数是必填的
bootstrap.servers: kafka集群所需的broker地址清单
key.serializer: broker端接收的消息必须以字节数组的形式存在
value.serializer: broker端接收的消息必须以字节数组的形式存在
client.id: 用来设定生产者对应的客户端id(非必填,不设置kafka会自动生成)
消息的发送
创建生产者实例和构建消息之后,就可以发送消息了。发送消息主要有三种模式:发送即忘、同步、异步
发送即忘:在发生不可重试异常时,会造成消息的丢失,这种方式的性能最高,可靠性是最差的
可重试异常(网路异常、leader不可用、不知道主题和分区异常、没有充分复制异常等)、不可重试异常(数据太大异常)
配置Retries_config参数,重试次数。
同步发送的可靠性是最高的,要么消息被发送成功,要么发送异常,性能较差(一条消息发送完了,才发送吓一跳消息)
异步发送:使用callback方式,要么发送成功,要么抛出异常
序列化
生产者需要用序列化器把对象转换为字节数组才能通过网络发送给Kafka。
分区器
消息通过send方法发送到broker的过程中,有可能需要经过拦截器(Interceptor)、序列化器(serializer)、分分区器(Partitioner)的一些列作用之后才能被真正的发往broker。
如果ProducerRecord中指定了partition字段,那么就不需要分区器的作用。
拦截器
整体架构
整个生产者客户端是由两个线程协调运行的(主线程、sender线程)。
主线程:kafkaProducer创建消息,然后通过可能的拦截器、序列化器、分区器的作用之后缓存到消息累加器(消息收集器)中。
sender线程:负责从消息收集器中获取消息并将其发送到Kafka中。
RecordAccumulator缓存的大小可以通过生产者客户端参数buffer.memory设置(默认32MB),如果生产者发送消息的速度超过发送到服务器的速度,则会导致生产者空间不足,这时候KafkaProducer的send方法调用要么被阻塞,要么抛出异常,这个取决于max.block.ms的配置(默认是60秒)
消息在网络上都是以字节形式传输的,在发送之前需要创建一块内存区域来保存对应的消息。在Kafka生产者客户端中,通过java.io.ByteBuffer实现消息内存的创建和释放。频繁的创建和释放是比较消耗资源的,为了实现资源的高效利用,消息收集器(RecordAccumulator)内部有一个bufferPool,它主要用来实现ByteBuffer的复用。不过BufferPool只针对特定大小的ByteBuffer进行管理,而其他大小的ByteBuffer不会缓存进BuferPool中。这个大小由batch.size参数来指定,默认为16KB。
重要的生产者参数
大部分参数都是合理的默认值,一般都不需要修改它们。不过了解这些参数有利于程序的可用性和性能。
- acks
这个参数用来指定分区中必须要由多少个副本收到这条消息,之后生产者才认为这条消息是成功写入的; acks = 1;只要分区leader副本写入成功 acks = 0;生产者发送消息之后不需要等待任何服务端的响应 acks = -1或者all;生产者在纤细发送之后,需要等待ISR中所有副本都成功写入
- max.request.size
限制生产者客户端能发送的消息的最大值(默认1MB)
- reties和retry.backoff.ms
配置生产者重试的次数,默认为0。 retry.backoff.ms默认值是100,它主要用来设置重试之间的时间间隔,避免无效的频繁重试。
- compression.ype
指定压缩的方式,默认是none。可配置gzip、snappy、lz4;对消息进行压缩可以极大地减少网络传输量、降低网络IO,从而提高整体性能
- connections.max.idle.ms
这个参数用来指定在多久后关闭限制的连接,默认9分钟
- linger.ms
指定生产者发送ProducerBatch之后等待更多消息加入消息批次的时间。默认是0.
- receive.buffer.bytes
这个参数设置Socket接收消息缓存区的大小,默认32KB
- send.buffer.bytes
设置socket发送消息缓冲区大小,默认128KB
- request.timeout.ms
配置producer等待请求响应的最长时间,默认30秒