一个正常的生产逻辑需要具备以下几个步骤:
1. 配置生产者客户端参数及创建相应的生产者实例。
2. 构建待发送的消息。
3. 发送消息。
4. 关闭生产者实例。
1. 必要的参数配置
- bootstrap.servers: 该参数用来指定生产者客户端连接kafka集群所需的broker地址清单。格式:host1:port1,host2:port2,可以设置一个或多个地址,以逗号分割,默认值为“”。可以不用把kafka所有集群中的broker地址信息,生产者会从给定的broker里查找到其他broker的信息,建议至少设置两个以上的broker信息,当其中任意一个宕机时,生产者仍然可以连接到kafka集群上。
- key.serializer 和value.serializer: broker端接收的消息必须以字节数组(byte[])的形式存在。key.serializer 和value.serializer 这两个参数分别用来指定key和value序列化操作的序列化器,这两个参数无默认值。
- client.id: 用来设定KafkaProducer对应的客户端id,默认值为“”,如果客户端不设置,则kafkaProducer会自动生成一个非空字符串,内容形式为“producer-1” “producer-2”,即字符串“producer-”与数字的拼接
KafkaProducer中的参数众多,不仅是上面四个,可以用客户端中的org.apache.kafka.clients.producer.ProducerConfig类来避免参数配置错误,每个参数在ProducerConfig类中都有对应的名称。
发送消息主要有三种模式:发后即忘(fire-and-forget)、同步(sync)、异步(async)
发后即忘:只管往kafka中发送信息而不关心消息是否正确到达。这种方式性能最高,可靠性最差。
同步:可靠性高,要么消息被发送成功,要么发生异常。如果发生异常,则可以捕获并进行相应的处理,而不会像”发后即忘”的方式直接造成消息的丢失。同步发送,性能较差,需要阻塞等待一条消息发送完之后才能发送下一条。
异步:一般是在sender()方法里指定一个Callback的回调函数,kafka在返回响应时调用该函数来实现异步的发送确认。回调函数的调用可以保证分区有序。
序列化
生产者需要用序列化器(Serializer)把对象转成成字节数组才能通过网络发送给Kafka。
消费者需要反序列化器(Deserializer)把从Kafka中收到的字节数组转换成相应的对象。
生产者使用的序列化器和消费者使用的反序列化器是需要一一对应的,如果生产者使用了某种序列化器,比如StringSerializer,而消费者使用了另一种序列化器,比如IntegerSerializer,那么是无法解析出想要的数据的。
分区器
分区器的作用是为消息分配分区。如果消息ProducerRecord中指定了partition字段,那么就不需要分区器的作用,因为partition代表的就是所要发往的分区号。
拦截器
kafka拦截器有两种,一种是生产者拦截器、一种是消费者拦截器。
生产者拦截器既可以用来在消息发送前做一些准备工作,比如按照某个规则过滤不符合要求的消息、修改消息的内容等,也可以用来在发送回调逻辑前做一些定制化的需求,比如统计类工作。
重要的生产者参数
1. acks:用来指定分区中必须要有多少个副本收到这条消息,之后生产者才会认为这条消息是成功写入的。
- acks = 1, 默认值即为1.生产者发送消息之后,只要分区的leader副本成功写入消息,那么它就会收到来自服务端的成功响应。如果消息无法写入leader副本,比如在leader副本崩溃、重新选举新的leader副本的过程中,那么生产者就会收到一个错误的响应,为了避免消息丢失,生产者可以选择重发消息。如果消息写入leader副本并返回成功响应给生产者,且在被其他follower副本拉取之前leader副本崩溃,那么此时消息还是会丢失,因为新选举的leader副本中并没有这条对应的消息。acks设置为1,是消息可靠性和吞吐量之间的折中方案。
- acks = 0, 生产者发送消息之后不需要等待任何服务的相应。如果在消息从发送到写入kafka的过程中出现某些异常,导致kafka并没有收到这条消息,那么生产者也无从得知,消息也就丢失了。在其他配置环境相同的情况下,acks设置为0可以达到最大的吞吐量。
- acks = -1 或acks = all。 生产者在消息发送之后,需要等待ISR中的所有副本都成功写入消息之后才能够对来自服务端的成功响应。在其他配置环境相同的情况下,acks设置为-1(all)可以达到最强的可靠性。但这并不意味着消息就一定可靠,因为ISR中可能只有leader副本,这样就退化成了acks = 1 的情况。要获得更高的消息可靠性需要配合min.insync.replicas等参数的联动。
2. max.request.size: 用来限制生产者客户端能发送的消息的最大值,默认为1048576B,即1MB。
3. retries和retry.bakcoff.ms: retries参数用来配置生产者重试的次数。默认值为0,即在发生异常的时候不进行任何重试动作。retry.backoff.ms默认值为100,用来设置两次重试之间的时间间隔。避免无效的频繁重试。
4. compression.type:这个参数用来指定消息的压缩方式,默认值为“none”,默认情况下,消息不会被压缩。可配置为“gzip”、“snappy”、和“lz4”。
5. connections.max.idle.ms: 用来指定在多久之后关闭闲置的连接,默认值是540000(ms),及9分钟。
6. linger.ms: 用来指定生产者发送ProducerBatch之前等待更多消息(ProducerRecord)加入ProducerBatch的时间,默认值为0.生产者客户端会在ProducerBatch被填满或等待时间超过linger.ms值时发送出去。
7. receive.buffer.bytes: 用来设置Socket接收消息缓冲区(SO_RECBUF)的大小,默认值为131072(B),即32KB。
8. send.buffer.bytes: 用来设置Socket发送消息缓冲区(SO_SNDBUF)的大小,默认值为131072(B),即32KB。
9. request.timeout.ms: 用来配置Producer等待请求响应的最长时间,默认值为30000(ms)。请求超时之后可以选择重试。注意: 这个参数需要比broker端参数raplica.lag.time.max.ms的值要大,这样可以减少因客户端重试而引起的消息重复的概率。