批量发送
生产者
Kafka 的做法是:提供了一个 RecordAccumulator 消息收集器,将发送给相同 Topic 的相同 Partition 分区的消息们,缓冲一下,当满足条件时候,一次性批量将缓冲的消息提交给 Kafka Broker 。
主要涉及的参数 ,三个条件,满足任一即会批量发送:
batch-size :超过收集的消息数量的最大量。默认16KB buffer-memory :超过收集的消息占用的最大内存 , 默认32M linger.ms :超过收集的时间的最大等待时长,单位:毫秒。
消费者
spring.kafka.listener.type 默认Single
配置文件
spring.kafka.bootstrap-servers=192.168.21.120:9092 spring.kafka.producer.acks=1 spring.kafka.producer.retries=3 spring.kafka.producer.key-serializer=org.apache.kafka.common.serialization.StringSerializer spring.kafka.producer.value-serializer=org.springframework.kafka.support.serializer.JsonSerializer # 每次批量发送消息的最大数量 单位 字节 默认 16K spring.kafka.producer.batch-size=16384 # 每次批量发送消息的最大内存 单位 字节 默认 32M spring.kafka.producer.buffer-memory=33554432 #批处理延迟时间上限。这里配置为 5 * 1000 ms 过后, # 不管是否消息数量是否到达 batch-size 或者消息大小到达 buffer-memory 后,都直接发送一次请求。 spring.kafka.properties.linger.ms=5000 spring.kafka.consumer.auto-offset-reset=earliest spring.kafka.consumer.key-deserializer=org.apache.kafka.common.serialization.StringDeserializer spring.kafka.consumer.value-deserializer=org.springframework.kafka.support.serializer.JsonDeserializer spring.kafka.consumer.properties.spring.json.trusted.packages=com.smile.domain # poll 一次拉取的阻塞的最大时长,单位:毫秒。这里指的是阻塞拉取需要满足至少 fetch-min-size 大小的消息 spring.kafka.consumer.fetch-max-wait=10000 # poll 一次消息拉取的最小数据量,单位:字节 spring.kafka.consumer.fetch-min-size=10 # poll 一次消息拉取的最大数量 spring.kafka.consumer.max-poll-records=100 #消费监听接口监听的主题不存在时,默认会报错。所以通过设置为 false ,解决报错 spring.kafka.listener.missing-topics-fatal=false # 监听器类型,默认为SINGLE ,只监听单条消息。这里我们配置 BATCH ,监听多条消息,批量消费 spring.kafka.listener.type=batch logging.level.org.springframework.kafka=ERROR logging.level.org.apache.kafka=ERROR
发送消息
public ListenableFuture<SendResult<String, Object>> sendBatchMessageAsync() { int i = new Random().nextInt(1000); Order order = Order.builder().orderId(10000L + i).memberId(10002L).payType("WeChat").payTime(new Date()).build(); ListenableFuture<SendResult<String, Object>> result = kafkaTemplate.send(ORDER_BATCH_TOPIC, order); return result; }
消费消息
@Slf4j @Component public class CommentBatchConsumer { private static final String COMMENT_GROUP = "comment-batch-group"; @KafkaListener(topics = ORDER_BATCH_TOPIC, groupId = COMMENT_GROUP) public void onMessage(List<Order> orders) { log.info("【评论】批处理消息内容:{}", orders); } }
测试
@Test public void testBatchAsyncSend() throws InterruptedException { for (int i = 0; i < 2; i++) { orderProducer.sendBatchMessageAsync().addCallback(new ListenableFutureCallback<SendResult<String, Object>>() { @Override public void onFailure(Throwable ex) { log.info("发送消息异常:{}", ex); } @Override public void onSuccess(SendResult<String, Object> result) { log.info("回调结果 Result = topic:[{}] , partition:[{}], offset:[{}]", result.getRecordMetadata().topic(), result.getRecordMetadata().partition(), result.getRecordMetadata().offset()); } }); } Thread.currentThread().join(10000); }
立志如山 静心求实
浙公网安备 33010602011771号