kafka实现异步发送_关于高并发下kafka producer send异步发送耗时问题的分析

最近开发网关服务的过程当中,需要用到kafka转发消息与保存日志,在进行压测的过程中由于是多线程并发操作kafka producer 进行异步send,发现send耗时有时会达到几十毫秒的阻塞,很大程度上上影响了并发的性能,而在后续的测试中发现单线程发送反而比多线程发送效率高出几倍。所以就对kafka API send 的源码进行了一下跟踪和分析,在此总结记录一下。

首先看springboot下 kafka producer 的使用

在config中进行配置,向IOC容器中注入DefaultKafkaProducerFactory生产者工厂的实例

@Beanpublic ProducerFactoryproducerFactory() {return new DefaultKafkaProducerFactory<>(producerConfigs());

}

创建producer

this.producer = producerFactory.createProducer();

大家都知道springboot下IOC容器管理的实例默认都是单例模式;而DefaultKafkaProducerFactory本身也是一个单例工厂

@Overridepublic ProducercreateProducer() {if (this.transactionIdPrefix != null) {returncreateTransactionalProducer();

}if (this.producer == null) {synchronized (this) {if (this.producer == null) {this.producer = new CloseSafeProducer(createKafkaProducer());

}

}

}return this.producer;

}

我们创建的producer也是个单例。

接下来就是具体的发送,用过kafka的小伙伴都知道producer.send是个异步操作,会返回一个Future 类型的结果。那么为什么单线程和多线程send效率会较大的差距呢,我们进入KafkaProducer内部看下producer.send的具体源码实现来找下答案

private Future doSend(ProducerRecordrecord, Callback callback) {

TopicPartition tp= null;try{//保证主题的元数据可用

ClusterAndWaitTime clusterAndWaitTime =waitOnMetadata(record.topic(), record.partition(), maxBlockTimeMs);long remainingWaitMs = Math.max(0, maxBlockTimeMs -clusterAndWaitTime.waitedOnMetadataMs);

Cluster cluster=clusterAndWaitTime.cluster;byte[] serializedKey;try{//序列化key

serializedKey =keySerializer.serialize(record.topic(), record.headers(), record.key());

}catch(ClassCastException cce) {throw new SerializationException("Can't convert key of class " + record.key().getClass().getName() +

" to class " + producerConfig.getClass(ProducerConfig.KEY_SERIALIZER_CLASS_CONFIG).getName() +

" specified in key.serializer", cce);

}byte[] serializedValue;try{//序列化Value

serializedValue =valueSerializer.serialize(record.topic(), record.headers(), record.value());

}catch(ClassCastException cce) {throw new SerializationException("Can't convert value of class " + record.value().getClass().getName() +

" to class " + producerConfig.getClass(ProducerConfig.VALUE_SERIALIZER_CLASS_CONFIG).getName() +

" specified in value.serializer", cce);

}//计算出具体的partition

int partition =partition(record, serializedKey, serializedValue, cluster);

tp= newTopicPartition(record.topic(), partition);

setReadOnly(record.headers());

Header[] headers=record.headers().toArray();int serializedSize =AbstractRecords.estimateSizeInBytesU

  • 1
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Kafka支持异步发送消息的方式。在使用Kafka发送消息时,可以选择使用异步发送方式,以提高消息发送的吞吐量和效率。 要使用异步发送消息,你可以创建一个Kafka生产者,并使用`send()`方法发送消息。该方法会立即返回一个`Future`对象,而不会等待消息发送完成。通过检查`Future`对象的状态,可以判断消息是否成功发送。 以下是一个示例代码,展示了如何使用Kafka异步发送消息: ```java import org.apache.kafka.clients.producer.*; import java.util.Properties; import java.util.concurrent.ExecutionException; public class KafkaAsyncProducer { public static void main(String[] args) throws ExecutionException, InterruptedException { // 配置Kafka生产者 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"); // 创建Kafka生产者 Producer<String, String> producer = new KafkaProducer<>(props); // 创建消息 ProducerRecord<String, String> record = new ProducerRecord<>("my_topic", "my_key", "my_message"); // 发送消息,并获取Future对象 Future<RecordMetadata> future = producer.send(record); // 检查消息是否发送成功 if (future.isDone()) { RecordMetadata metadata = future.get(); System.out.println("Message sent to partition " + metadata.partition() + " with offset " + metadata.offset()); } else { System.out.println("Failed to send message"); } // 关闭Kafka生产者 producer.close(); } } ``` 在上述示例中,我们创建了一个`KafkaProducer`对象,并使用`send()`方法发送消息。通过检查`Future`对象的状态,我们可以判断消息是否成功发送,并获取发送结果(如分区和偏移量)。 希望能对你有所帮助!如果你有其他问题,请继续提问。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值