批量发送

生产者

       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);
    }

 

posted on 2022-01-09 15:33  溪水静幽  阅读(458)  评论(0)    收藏  举报