Kafka的生产者原理及重要参数说明

当然你也可以指定一个key,作用之后会说明:

ProducerRecord<String, String> record = new ProducerRecord<>(

“test-topic”, “test-key”, “test-value”)

发送消息

带有一个回调函数,如果没有异常就返回消息发送成功。

// 这是异步发送的模式

producer.send(record, new Callback() {

@Overridepublic void onCompletion(RecordMetadata metadata, Exception exception) { if(exception == null) {

// 消息发送成功

System.out.println(“消息发送成功”);

} else {

// 消息发送失败,需要重新发送

}}});Thread.sleep(10 * 1000);

// 这是同步发送的模式(是一般不会使用的,性能很差,测试可以使用)

// 你要一直等待人家后续一系列的步骤都做完,发送消息之后

// 有了消息的回应返回给你,你这个方法才会退出来

producer.send(record).get();

关闭连接

producer.close();

干货时间:调优部分的代码

================================================================================

区分是不是一个勤于思考的打字员的部分其实就是在1那里还没有讲到的那部分调优,一个个拿出来单独解释,就是下面这一大串。

props.put(“acks”, “-1”);

props.put(“retries”, 3);

props.put(“batch.size”, 32384);

props.put(“linger.ms”, 100);

props.put(“buffer.memory”, 33554432);

props.put(“max.block.ms”, 3000);

acks 消息验证

=============================================================================

props.put(“acks”, “-1”);

Kafka的生产者原理及重要参数说明

这个acks参数有3个值,分别是-1,0,1,设置这3个不同的值会成为kafka判断消息发送是否成功的依据。Kafka里面的分区是有副本的,如果acks为-1.则说明消息在写入一个分区的leader partition后,这些消息还需要被另外所有这个分区的副本同步完成后,才算发送成功(对应代码就是输出System.out.println(“消息发送成功”)),此时发送数据的性能降低。

如果设置acks为1,需要发送的消息只要写入了leader partition,即算发送成功,但是这个方式存在丢失数据的风险,比如在消息刚好发送成功给leader partition之后,这个leader partition立刻宕机了,此时剩余的follower无论选举谁成为leader,都不存在刚刚发送的那一条消息。

如果设置acks为0,消息只要是发送出去了,就默认发送成功了。啥都不管了。

retries 重试次数(重要)

====================================================================================

这个参数还是非常重要的,在生产环境中是必须设置的参数,为设置消息重发的次数。

props.put(“retries”, 3);

在Kafka中可能会遇到各种各样的异常(可以直接跳到下方的补充异常类型),但是无论是遇到哪种异常,消息发送此时都出现了问题,特别是网络突然出现问题,但是集群不可能每次出现异常都抛出,可能在下一秒网络就恢复了呢,所以我们要设置重试机制。

这里补充一句:设置了retries之后,集群中95%的异常都会自己乘风飞去,我真没开玩笑!

代码中我配置了3次,其实设置5~10次都是合理的,补充说明一个,如果我们需要设置隔多久重试一次,也有参数,没记错的话是retry.backoff.ms,下面我设置了100毫秒重试一次,也就是0.1秒。

props.put(“retry.backoff.ms”,100);

batch.size 批次大小

===================================================================================

批次的大小默认是16K,这里设置了32K,设置大一点可以稍微提高一下吞吐量,设置这个批次的大小还和消息的大小有关,假设一条消息的大小为16K,一个批次也是16K,这样的话批次就失去意义了。所以我们要事先估算一下集群中消息的大小,正常来说都会设置几倍的大小。

props.put(“batch.size”, 32384);

linger.ms 发送时间限制

====================================================================================

比如我现在设置了批次大小为32K,而一条消息是2K,此时已经有了3条消息发送过来,总大小为6K,而生产者这边就没有消息过来了,那在没够32K的情况下就不发送过去集群了吗?显然不是,linger.ms就是设置了固定多长时间,就算没塞满Batch,也会发送,下面我设置了100毫秒,所以就算我的Batch迟迟没有满32K,100毫秒过后都会向集群发送Batch。

props.put(“linger.ms”, 100);

buffer.memory 缓冲区大小

=======================================================================================

当我们的Sender线程处理非常缓慢,而生产数据的速度很快时,我们中间的缓冲区如果容量不够,生产者就无法再继续生产数据了,所以我们有必要把缓冲区的内存调大一点,缓冲区默认大小为32M,其实基本也是合理的。

props.put(“buffer.memory”, 33554432);

那应该如何去验证我们这时候应该调整缓冲区的大小了呢,我们可以用一般Java计算结束时间减去开始时间的方式测试,当结束时间减去开始时间大于100ms,我们认为此时Sender线程处理速度慢,需要调大缓冲区大小。

当然一般情况下我们是不需要去设置这个参数的,32M在普遍情况下已经足以应付了。

Long startTime=System.currentTime();

producer.send(record, new Callback() {

@Override

public void onCompletion(RecordMetadata metadata, Exception exception) {

if(exception == null) {

// 消息发送成功

System.out.println(“消息发送成功”);

} else {

// 消息发送失败,需要重新发送

}

}

});

Long endTime=System.currentTime();

If(endTime - startTime > 100){//说明内存被压满了

说明有问题

}

compression.type压缩方式

========================================================================================

compression.type,默认是none,不压缩,但是也可以使用lz4压缩,效率还是不错的,压缩之后可以减小数据量,提升吞吐量,但是会加大producer端的CPU开销。

props.put(“compression.type”, lz4);

max.block.ms

================================================================================

留到源码时候说明,是设置某几个方法的阻塞时间。

props.put(“max.block.ms”, 3000);

max.request.size最大消息大小

==========================================================================================

max.request.size:这个参数用来控制发送出去的消息的大小,默认是1048576字节,也就1M,这个一般太小了,很多消息可能都会超过1mb的大小,所以需要自己优化调整,把它设置更大一些(企业一般设置成10M),不然程序跑的好好的突然来了一条2M的消息,系统就报错了,那就得不偿失。

props.put(“max.request.size”, 1048576);

request.timeout.ms请求超时

==========================================================================================

request.timeout.ms:这个就是说发送一个请求出去之后,他有一个超时的时间限制,默认是30秒,如果30秒都收不到响应(也就是上面的回调函数没有返回),那么就会认为异常,会抛出一个TimeoutException来让我们进行处理。如果公司网络不好,要适当调整此参数。

总结

这个月马上就又要过去了,还在找工作的小伙伴要做好准备了,小编整理了大厂java程序员面试涉及到的绝大部分面试题及答案,希望能帮助到大家

在这里插入图片描述

在这里插入图片描述

================================

request.timeout.ms:这个就是说发送一个请求出去之后,他有一个超时的时间限制,默认是30秒,如果30秒都收不到响应(也就是上面的回调函数没有返回),那么就会认为异常,会抛出一个TimeoutException来让我们进行处理。如果公司网络不好,要适当调整此参数。

总结

这个月马上就又要过去了,还在找工作的小伙伴要做好准备了,小编整理了大厂java程序员面试涉及到的绝大部分面试题及答案,希望能帮助到大家

[外链图片转存中…(img-6kLeGrW6-1719278875501)]

[外链图片转存中…(img-2V6WT6Pr-1719278875502)]

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值