Kafka批量消息发送

Kafka批量消息发送

1、pom.xml

xml 复制代码
<!-- 引入spring-kafka的依赖 -->
<dependency>
    <groupId>org.springframework.kafka</groupId>
    <artifactId>spring-kafka</artifactId>
</dependency>

2、application.properties 配置

properties 复制代码
# Kafka 配置参数
ecp.sim.kafka.topic=sim-topic

# Spring Kafka Producer 批量发送配置
spring.kafka.bootstrap-servers=192.168.0.191:9092,192.168.0.192:9092,192.168.0.193:9092
spring.kafka.producer.retries=3
spring.kafka.producer.batch-size=16384
spring.kafka.producer.buffer-memory=33554432
spring.kafka.producer.key-serializer=org.apache.kafka.common.serialization.StringSerializer
spring.kafka.producer.value-serializer=org.apache.kafka.common.serialization.StringSerializer
spring.kafka.producer.acks=1

# Spring Kafka Consumer 批量消费配置
spring.kafka.consumer.group-id=simulator-group
spring.kafka.consumer.enable-auto-commit=false
spring.kafka.consumer.auto-offset-reset=earliest
spring.kafka.consumer.key-deserializer=org.apache.kafka.common.serialization.StringDeserializer
spring.kafka.consumer.value-deserializer=org.apache.kafka.common.serialization.StringDeserializer
spring.kafka.consumer.max-poll-records=500
spring.kafka.listener.type=batch
spring.kafka.listener.ack-mode=manual

3、生产者和消费者

3.1、生产者

java 复制代码
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.kafka.core.KafkaTemplate;
import org.springframework.stereotype.Service;

import java.util.List;
import java.util.UUID;

/**
 * Kafka 生产者实现,支持批量发送
 */
@Service
public class KafkaProducerImpl {

    private static final Logger logger = LoggerFactory.getLogger(KafkaProducerImpl.class);

    @Autowired
    private KafkaTemplate<String, String> kafkaTemplate;

    /**
     * 发送单条消息
     *
     * @param topic 目标 topic
     * @param message 消息内容
     */
    public void sendMessage(String topic, String message) {
        // TODO 消息ID需要处理一下,保证全局唯一
        String messageId = UUID.randomUUID().toString();
        logger.info("发送单条消息, topic: {}, messageId: {}, message: {}", topic, messageId, message);
        kafkaTemplate.send(topic, messageId, message);
    }

    /**
     * 批量发送消息
     *
     * @param topic 目标 topic
     * @param messages 消息列表
     */
    public void sendMessagesBatch(String topic, List<String> messages) {
        if (messages == null || messages.isEmpty()) {
            return;
        }
        logger.info("批量发送消息, topic: {}, 数量: {}", topic, messages.size());
        for (String message : messages) {
            // TODO 消息ID需要处理一下,保证全局唯一
            String messageId = UUID.randomUUID().toString();
            kafkaTemplate.send(topic, messageId, message);
        }
    }
}

3.2、消费者

java 复制代码
import org.apache.kafka.clients.consumer.ConsumerRecord;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.kafka.annotation.KafkaListener;
import org.springframework.kafka.support.Acknowledgment;
import org.springframework.stereotype.Service;

import java.util.List;

/**
 * Kafka 消费者实现,支持批量消费
 */
@Service
public class KafkaConsumerImpl {

    private static final Logger logger = LoggerFactory.getLogger(KafkaConsumerImpl.class);

    /**
     * 批量消费消息
     *
     * @param records 消息记录列表
     * @param acknowledgment 手动提交 ack
     */
    @KafkaListener(topics = "${ecp.sim.kafka.topic:sim-topic}", containerFactory = "kafkaListenerContainerFactory")
    public void consumeBatch(List<ConsumerRecord<String, String>> records, Acknowledgment acknowledgment) {
        if (records == null || records.isEmpty()) {
            return;
        }
        logger.info("开始批量消费消息, 本批次数量: {}", records.size());
        
        try {
            for (ConsumerRecord<String, String> record : records) {
                logger.info("消费单条消息: topic = {}, partition = {}, offset = {}, key = {}, value = {}",
                        record.topic(), record.partition(), record.offset(), record.key(), record.value());
                // TODO: 添加实际的业务处理逻辑
            }
            
            // 业务处理成功后手动提交 offset
            if (acknowledgment != null) {
                acknowledgment.acknowledge();
                logger.info("本批次消息消费成功, offset 已提交");
            }
        } catch (Exception e) {
            logger.error("批量消费消息时发生异常", e);
            // 发生异常时可以根据业务需求决定是否重试、记录死信队列或不提交 ack
        }
    }
}
相关推荐
圆山猫8 小时前
[Virtualization](四):Linux KVM/RISC-V 的 vCPU 运行路径
java·linux·risc-v
城管不管8 小时前
ReAct、Plan-and-Execute、Reflection 三大智能 Agent 范式核心区别
java·人工智能·算法·spring·ai·动态规划
IT小白杨8 小时前
从环境制备到自动化工作流:多账号运营的工程化架构拆解
java·经验分享·自动化·安全架构·指纹浏览器
豆瓣鸡9 小时前
算法日记 - Day3
java·开发语言·算法
萧瑟余晖9 小时前
Java深入解析篇九之NIO详解
java·网络·nio
The Chosen One9859 小时前
高进度算法模板速记(待完善)
java·前端·算法
独行侠影a11 小时前
APScheduler+Redis 分布式定时任务:解决多实例任务重复执行
数据库·redis·分布式
极光代码工作室12 小时前
基于SpringBoot的课程预约系统
java·springboot·web开发·后端开发
Leighteen12 小时前
`try-finally` 里的 `return`:为什么 `finally` 会悄悄改掉返回值、吞掉异常
java·开发语言
名字还没想好☜13 小时前
Go 的 time.After 在 select 循环里内存泄漏:定时器堆积原理与 timer.Reset 正确姿势
java·数据库·golang·go·goroutine