/**
* 创建Producer
* @return
*/
@Override
public Producer createProducer() {
//获取kafka配置信息,根据自己所需,也可写死
String kafkaConfigStr = dmpSysConfigService.getkafkaConfig();
String[] param = kafkaConfigStr.split(",");
Properties kafkaConf = new Properties();
//此处配置的是kafka的端口
kafkaConf.put("metadata.broker.list",nodes);
//配置value的序列化类
kafkaConf.put("serializer.class", "kafka.serializer.StringEncoder");
//配置key的序列化类
kafkaConf.put("key.serializer.class","kafka.serializer.StringEncoder");
if (null != param && param.length ==4){
kafkaConf.put("request.required.acks",param[0]);
kafkaConf.put("batch.size",Integer.parseInt(param[1]));
kafkaConf.put("linger.ms",Integer.parseInt(param[2]));
kafkaConf.put("buffer.memory",Integer.parseInt(param[3]));
}else {
kafkaConf.put("request.required.acks","0");
kafkaConf.put("batch.size",50000);
kafkaConf.put("linger.ms",500);
kafkaConf.put("buffer.memory",33554432);
}
Producer producer =
new Producer(new ProducerConfig(kafkaConf));
return producer;
}
0:这意味着生产者producer不等待来自broker同步完成的确认继续发送下一条(批)消息。
此选项提供最低的延迟但最弱的耐久性保证(当服务器发生故障时某些数据会丢失,如leader已死,但producer并不知情,发出去的信息broker就收不到)。
1:这意味着producer在leader已成功收到的数据并得到确认后发送下一条message。
此选项提供了更好的耐久性为客户等待服务器确认请求成功(被写入死亡leader但尚未复制将失去了唯一的消息)。
-1:这意味着producer在follower副本确认接收到数据后才算一次发送完成。
此选项提供最好的耐久性,我们保证没有信息将丢失,只要至少一个同步副本保持存活。
三种机制,性能依次递减 (producer吞吐量降低),数据健壮性则依次递增。
acks |
含义 |
0 | Producer 往集群发送数据不需要等到集群的返回,不确保消息发送成功。安全性最低但是效率最高。 |
1 | Producer 往集群发送数据只要 Leader 应答就可以发送下一条,只确保 Leader 接收成功。 |
-1 或 all | Producer 往集群发送数据需要所有的ISR Follower 都完成从 Leader 的同步才会发送下一条,确保 Leader 发送成功和所有的副本都成功接收。安全性最高,但是效率最低。 |
Kafka的客户端发送数据到服务器,不是来一条就发一条,而是经过缓冲的,也就是说,通过KafkaProducer发送出去的消息都是先进入到客户端本地的内存缓冲里,然后把很多消息收集成一个一个的Batch,再发送到Broker上去的,这样性能才可能高。
buffer.memory的本质就是用来约束KafkaProducer能够使用的内存缓冲的大小的,默认值32MB。
如果buffer.memory设置的太小,可能导致的问题是:消息快速的写入内存缓冲里,但Sender线程来不及把Request发送到Kafka服务器,会造成内存缓冲很快就被写满。而一旦被写满,就会阻塞用户线程,不让继续往Kafka写消息了。
所以“buffer.memory”参数需要结合实际业务情况压测,需要测算在生产环境中用户线程会以每秒多少消息的频率来写入内存缓冲。经过压测,调试出来一个合理值。
每个Batch要存放batch.size大小的数据后,才可以发送出去。比如说batch.size默认值是16KB,那么里面凑够16KB的数据才会发送。
理论上来说,提升batch.size的大小,可以允许更多的数据缓冲在里面,那么一次Request发送出去的数据量就更多了,这样吞吐量可能会有所提升。
但是batch.size也不能过大,要是数据老是缓冲在Batch里迟迟不发送出去,那么发送消息的延迟就会很高。
一般可以尝试把这个参数调节大些,利用生产环境发消息负载测试一下。
一个Batch被创建之后,最多过多久,不管这个Batch有没有写满,都必须发送出去了。
比如说batch.size是16KB,但是现在某个低峰时间段,发送消息量很小。这会导致可能Batch被创建之后,有消息进来,但是迟迟无法凑够16KB,难道此时就一直等着吗?
当然不是,假设设置“linger.ms”是50ms,那么只要这个Batch从创建开始到现在已经过了50ms了,哪怕他还没满16KB,也会被发送出去。
所以“linger.ms”决定了消息一旦写入一个Batch,最多等待这么多时间,他一定会跟着Batch一起发送出去。
linger.ms配合batch.size一起来设置,可避免一个Batch迟迟凑不满,导致消息一直积压在内存里发送不出去的情况。