kafka-producer开发

kafka producer即生产者,信息的生产方,发送到kafka后,供消费者(consumer)消费。
每个Producer都是独立工作,彼此之间没有关联。

producer发送过程:
1.使用一个线程将消息封装进一个ProdecerRecord类实例。
2.序列化后发送给partitioner,找到分区leader副本所在的broker,确定目标分区后发送到producer程序中的一块内存缓冲区。
3.sender线程从缓冲区中取出封装进一个批次,发送给对应的broker。

producer实例

public class ProducerEG {
	public static void main(String[] args) throws Exception{
	Properties props = new Properties();
	props.put("bootstrap.servers", "localhost:9092");
	props.put("key.serializer","org.apache.kafka.common.serialization.StringSerializer");
	props.put("value.serializer","org.apache.kafka.common.serialization.StringSerializer");
	props.put("acks","-1");
	props.put("retries",3);
	props.put("batch.size", 323840);
	props.put("linger.ms", 10);
	props.put("buffer.memory", 33554432);
	props.put("max.block.ms", 3000);

	Producer<String,String> producer = new KafkaProducer<>(props);
	for(int i = 0; i < 100; i++) {
	producer.send(new ProducerRecord<>("test-topic", Integer.toString(i), Integer.toString(i)));
	producer.close();
}
}

bootstrap.servers,key.serializer,value.serializer3个属性必须指定。

1.构造properties对象
bootstrap.servers:指定一组host:port对,可以指定多个,如host1:9092,host2:9092,host3:9093。

集群中broker很多时,指定部分即可,producer会获取到集群中的列表而拿到所有boker,指定多个的目的是为了故障转移,其中一台挂掉时,producer仍可通过其他节点加入集群,如host1:9092挂掉时,仍可根据host2:9092,host2:9093拿到清单加入集群。

如果broker端没有显式配置listeners使用Ip地址,那么建议参数也配置成主机名而非ip.

key.serializer: 指定消息key的序列化器,无默认值,可自定义序列化器(实现Serializer接口)。

value.serializer: 指定消息value的序列化器,与key.serializer可以为不同值。

2.构造KafkaProdeucer对象
Producer<String, String> producer = new KafkaProducer<>(props);
同时,上面通过properties指定序列化器的方式也可改为:
Serializer keySerializer = new StringSerializer();
Serializer valueSerializer = new StringSerializer();
Producer<String, String> producer = new KafkaProducer<>(props, keySerializer, valueSerializer);

3.构造ProducerRedord对象
new ProducerRecord<>(“test-topic”, Integer.toString(i), Integer.toString(i));
里面的参数依次代表:topic名称,消息的Key,消息的value。

4.发送消息
producer消息发送机制分为不等待副本响应便返回及等待leader副本确认写入后返回成功。

通过调用send方法进行发送。
producer发送消息通过Future实现了同步发送和异步发送:

**同步发送:**
ProducerRecord<String, String> record = new ProducerRecord<>("test-topic", Integer.toString(i), Integer.toString(i));
producer.send(record).get();
异步发送:
producer.send(record, new Callback() {
	@Override
	public void onCompletion(RecordMetada metadata, Exception exception) {
		if(exception == null) {
		//发送成功
		} else {
		//发送失败
		}
}
})

发送信息失败时会返回错误,分为可重试错误和不可重试错误。
可重试异常:
LeaderNotAvailableException:分区leader副本不可用,通常是leader换届。
NotControllerException:controller当前不可用。
NetworkException:网络瞬时故障
以上为通过重试可能恢复的异常,若超过重试次数,仍会被封装进exception中,此时就需自行处理。可重试异常继承自org.apache.kafka.common.errors.RetriableException抽象类。

不可重试异常:
RecordTooLargeException:消息尺寸超过规定上限。
SerializationException:序列化失败。
KafkaException:其他异常。
不可重试异常未继承自RetriableException。

因此,在Callback()函数中,可能根据返回的不同的异常类型,做不同的处理。
上面例子中的
producer.send(new ProducerRecord<>(“test-topic”, Integer.toString(i), Integer.toString(i)));
为只发送信息,而不关注是否发送成功,某些相对不重要的数据而数据量较大需要效率的场景下可能会使用到,如日志采集定。

确定分区的方式:
1.消息如果指定了key,那么partitioner会根据key的哈希值来确定分区。
2.否则以轮询的方式确认目标分区。
3.producer允许用户自定义分区策略来进行不同的分区发送(不使用默认的patitioner)。

关闭producer
close():处理完之前的发送请求后,关闭退出。
close(timeout):producer等Timeout时间后强制退出(即timeout时间后,未处理完的发送请求不在处理,强制退出)。

producer其他主要参数
producer除了以上3个必须指定的参数外,还有其他几个很重要的参数,对于producer的性能调优具有影响作用,主要如下:
acks:控制producer发送信息后,是否等待leader broker响应的处理方式。

acks发送策略
“0”不关注发送结果,发送完信息立即开始下次发送,回调失效,吞吐量最高,允许消息丢失
“1”只关注消息接收broker是否写入成功,而不关注ISR是否写入成功,吞吐量适中,broker保持存活则无数据丢失
“all” or “-1”同时关注broker和ISR是否写入成功,吞吐量最低,ISR至少有一个副本存活最消息无丢失

buffer.memory:指定producer端用于缓存消息的缓冲区大小,单位字节,默认33554432,即32MB。
producer会创建一块内存用于保存等待发送的消息,然后由另一个线程从缓冲区中读取进行真正的发送,当写入缓存的速度大于读取发送的速度一段时间后,producer会停止手上的工作等待发送I/O线程追赶上来,如果一段时间后仍不能追赶上,则会抛出异常。
当producer需要给多个分区发消息时,需要加大这个参数防止缓冲区过小降低吞吐量。

compression.type:指定producer端是否压缩消息,默认none。压缩消息带来的好处是显著降低网络I/O传输,提高吞吐量。坏处是会带来额外的CPU开销,包括producer端和broker端。
1.0.0支持的压缩算法为:GZIP、Snappy、LZ4,三者LZ4性能最好。

retries:指定在遇到可重试异常(leader选举等)导致发送失败时,producer自动发送重试的次数,默认为0,推荐实际中该值大于0。
但是发送重试,可能带来2个问题:消息重复发送和消息的乱序,因此需要在consumer端执行去重处理。避免乱序可通过设置max.in.flight.requests.per.connection为1来让producer同一时刻只能发送一个请求。
retry.backoff.ms可以指定重试之间等待的时间,默认100。
实际使用中可通过测试leader选举的平均时间来指定retries和retry.backff.ms的值。

producer可优化的点:
1.将某些producer发送的消息固定发送到相同机架上的分区,减少网络开销。
2.将某些需要保证时序性的统一性质消息(如对通一条数据的更新操作)发到统一分区中,保证执行的时序性。

参考书籍:《Apache Kafka实战》
continue…

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值