最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

SpringBoot整合Kafka生產(chǎn)環(huán)境標(biāo)準(zhǔn)配置

 更新時(shí)間:2026年04月16日 08:26:17   作者:別掉進(jìn)我的異常  
本文介紹了在SpringBoot 3.x項(xiàng)目中集成Apache Kafka的完整方案,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧

一、環(huán)境準(zhǔn)備

組件版本說明
Java17+Spring Boot 3.x 需 Java 17+
Apache Kafka3.6.x下載地址:Kafka 官網(wǎng)
Spring Boot3.1.0+通過 Spring Initializr 生成項(xiàng)目
Maven/Gradle最新項(xiàng)目構(gòu)建工具

啟動(dòng) Kafka 服務(wù)(本地開發(fā)示例):

# 啟動(dòng) Zookeeper(Kafka 3.0+ 已內(nèi)置)
bin/zookeeper-server-start.sh config/zookeeper.properties
# 啟動(dòng) Kafka 服務(wù)
bin/kafka-server-start.sh config/server.properties

二、項(xiàng)目搭建(Maven 依賴)

1. 添加 Spring Kafka 依賴

<dependency>
    <groupId>org.springframework.kafka</groupId>
    <artifactId>spring-kafka</artifactId>
    <version>3.1.0</version>
</dependency>

?? 關(guān)鍵點(diǎn):Spring Boot 3.x 已移除 spring-boot-starter-kafka,直接使用 spring-kafka。

三、YAML 配置(application.yml)

重點(diǎn):YAML 配置替代 properties,支持對(duì)象序列化器配置

spring:
  kafka:
    bootstrap-servers: localhost:9092
    producer:
      key-serializer: org.apache.kafka.common.serialization.StringSerializer
      value-serializer: com.example.config.AttendanceSerializer # 自定義序列化器
      batch-size: 16384 # 批量發(fā)送優(yōu)化
      linger-ms: 100 # 批量發(fā)送延遲
      retries: 3
      acks: all
    consumer:
      group-id: attendance-group
      key-deserializer: org.apache.kafka.common.serialization.StringDeserializer
      value-deserializer: com.example.config.AttendanceDeserializer # 自定義反序列化器
      auto-offset-reset: earliest
      enable-auto-commit: true
      max-poll-records: 500
      isolation.level: read_committed
      # 事務(wù)配置(可選)
      transaction-id-prefix: attendance-trans

?? YAML 配置優(yōu)勢(shì)

  • 層級(jí)清晰,避免 . 重復(fù)
  • 支持嵌套配置(如 producer.batch-size
  • 與 Spring Boot 3.x 完美兼容

四、自定義序列化器(核心代碼)

1. 定義消息實(shí)體(AttendanceStatisticsSingleDto)

package jnpf.model.attendance.event;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
import javax.validation.constraints.NotBlank;
import javax.validation.constraints.NotNull;
import java.io.Serializable;
import java.util.Date;
@Data
@Builder
@AllArgsConstructor
@NoArgsConstructor
public class AttendanceStatisticsSingleDto implements Serializable {
    private static final long serialVersionUID = 1L;
    @NotBlank(message = "租戶Id不能為空")
    private String tenantId;
    @NotBlank(message = "考勤組Id不能為空")
    private String groupId;
    @NotBlank(message = "用戶Id不能為空")
    private String userId;
    @NotNull(message = "日期不能為空")
    private Date day;
}

2. 創(chuàng)建序列化器(AttendanceSerializer.java)

package com.example.config;
import com.fasterxml.jackson.databind.ObjectMapper;
import jnpf.model.attendance.event.AttendanceStatisticsSingleDto;
import org.apache.kafka.common.serialization.Serializer;
import java.util.Map;
public class AttendanceSerializer implements Serializer<AttendanceStatisticsSingleDto> {
    private final ObjectMapper objectMapper = new ObjectMapper();
    @Override
    public void configure(Map<String, ?> configs, boolean isKey) {
        // 配置方法,無需額外操作
    }
    @Override
    public byte[] serialize(String topic, AttendanceStatisticsSingleDto data) {
        try {
            return objectMapper.writeValueAsBytes(data);
        } catch (Exception e) {
            throw new RuntimeException("序列化失敗: " + data, e);
        }
    }
    @Override
    public void close() {
        // 無需關(guān)閉資源
    }
}

3. 創(chuàng)建反序列化器(AttendanceDeserializer.java)

package com.example.config;
import com.fasterxml.jackson.databind.ObjectMapper;
import jnpf.model.attendance.event.AttendanceStatisticsSingleDto;
import org.apache.kafka.common.serialization.Deserializer;
import java.util.Map;
public class AttendanceDeserializer implements Deserializer<AttendanceStatisticsSingleDto> {
    private final ObjectMapper objectMapper = new ObjectMapper();
    @Override
    public void configure(Map<String, ?> configs, boolean isKey) {
        // 配置方法,無需額外操作
    }
    @Override
    public AttendanceStatisticsSingleDto deserialize(String topic, byte[] data) {
        try {
            return objectMapper.readValue(data, AttendanceStatisticsSingleDto.class);
        } catch (Exception e) {
            throw new RuntimeException("反序列化失敗: " + topic, e);
        }
    }
    @Override
    public void close() {
        // 無需關(guān)閉資源
    }
}

?? 為什么需要自定義序列化器?
Spring Kafka 默認(rèn)只支持 String/byte[],復(fù)雜對(duì)象必須通過序列化器轉(zhuǎn)換為字節(jié)數(shù)組。

五、完整集成示例

1. 生產(chǎn)者服務(wù)(發(fā)送 AttendanceStatisticsSingleDto)

package com.example.service;
import com.example.config.AttendanceSerializer;
import jnpf.model.attendance.event.AttendanceStatisticsSingleDto;
import org.apache.kafka.common.serialization.StringSerializer;
import org.springframework.kafka.core.KafkaTemplate;
import org.springframework.stereotype.Service;
@Service
public class AttendanceProducer {
    private final KafkaTemplate<String, AttendanceStatisticsSingleDto> kafkaTemplate;
    public AttendanceProducer(KafkaTemplate<String, AttendanceStatisticsSingleDto> kafkaTemplate) {
        this.kafkaTemplate = kafkaTemplate;
    }
    public void sendAttendanceData(AttendanceStatisticsSingleDto attendance) {
        // 發(fā)送消息到主題 attendance-topic
        kafkaTemplate.send("attendance-topic", attendance.getUserId(), attendance);
        System.out.println("? 消息發(fā)送成功: " + attendance.getUserId() + " | " + attendance.getDay());
    }
}

2. 消費(fèi)者服務(wù)(接收 AttendanceStatisticsSingleDto)

package com.example.consumer;
import com.example.config.AttendanceDeserializer;
import jnpf.model.attendance.event.AttendanceStatisticsSingleDto;
import org.apache.kafka.common.header.Headers;
import org.apache.kafka.common.header.internals.RecordHeaders;
import org.springframework.kafka.annotation.KafkaListener;
import org.springframework.kafka.support.Acknowledgment;
import org.springframework.stereotype.Service;
@Service
public class AttendanceConsumer {
    @KafkaListener(
        topics = "attendance-topic",
        groupId = "attendance-group",
        containerFactory = "kafkaListenerContainerFactory"
    )
    public void listen(AttendanceStatisticsSingleDto attendance, 
                      Acknowledgment ack,
                      Headers headers) {
        // 獲取 Kafka 元數(shù)據(jù)
        int partition = Integer.parseInt(headers.lastHeader("partition").value().toString());
        long offset = headers.lastHeader("offset").value().toString().getBytes()[0];
        System.out.println("? 消息消費(fèi)成功 | 分區(qū): " + partition + 
                          " | 偏移量: " + offset + 
                          " | 用戶: " + attendance.getUserId());
        // 手動(dòng)提交偏移量(可選)
        ack.acknowledge();
    }
}

3. 配置 Kafka 監(jiān)聽器容器工廠(關(guān)鍵?。?/h3>
package com.example.config;
import org.apache.kafka.common.serialization.StringDeserializer;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.kafka.config.ConcurrentKafkaListenerContainerFactory;
import org.springframework.kafka.config.ContainerCustomizer;
import org.springframework.kafka.core.ConsumerFactory;
import org.springframework.kafka.core.DefaultKafkaConsumerFactory;
import org.springframework.kafka.support.serializer.DeserializationException;
@Configuration
public class KafkaConfig {
    @Bean
    public ConsumerFactory<String, AttendanceStatisticsSingleDto> consumerFactory() {
        // 配置消費(fèi)者工廠
        return new DefaultKafkaConsumerFactory<>(
            Map.of(
                "bootstrap.servers", "localhost:9092",
                "group.id", "attendance-group",
                "key.deserializer", StringDeserializer.class.getName(),
                "value.deserializer", AttendanceDeserializer.class.getName()
            )
        );
    }
    @Bean
    public ConcurrentKafkaListenerContainerFactory<String, AttendanceStatisticsSingleDto> kafkaListenerContainerFactory() {
        ConcurrentKafkaListenerContainerFactory<String, AttendanceStatisticsSingleDto> factory = 
            new ConcurrentKafkaListenerContainerFactory<>();
        factory.setConsumerFactory(consumerFactory());
        factory.setCommonErrorHandler(new DefaultErrorHandler(
            new FixedBackOff(1000L, 3), // 重試3次,間隔1秒
            new TopicPartitionOffset("attendance-topic.DLQ", 0) // 死信隊(duì)列
        ));
        // 啟用自動(dòng)提交
        factory.getContainerProperties().setAckMode(ContainerProperties.AckMode.MANUAL);
        return factory;
    }
}

?? 關(guān)鍵配置說明

  • setCommonErrorHandler:實(shí)現(xiàn)自動(dòng)重試 + 死信隊(duì)列
  • setAckMode(ContainerProperties.AckMode.MANUAL):手動(dòng)提交偏移量(推薦)
  • AttendanceDeserializer:與生產(chǎn)者序列化器嚴(yán)格匹配

六、測(cè)試用例(JUnit 5)

package com.example;
import com.example.service.AttendanceProducer;
import jnpf.model.attendance.event.AttendanceStatisticsSingleDto;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import java.util.Date;
@SpringBootTest
public class KafkaIntegrationTest {
    @Autowired
    private AttendanceProducer producer;
    @Test
    public void testSendAttendanceData() {
        AttendanceStatisticsSingleDto attendance = AttendanceStatisticsSingleDto.builder()
            .tenantId("tenant_001")
            .groupId("group_001")
            .userId("user_001")
            .day(new Date())
            .build();
        producer.sendAttendanceData(attendance);
        // 實(shí)際測(cè)試需等待消費(fèi)者處理(此處簡(jiǎn)化)
        System.out.println("? 測(cè)試消息已發(fā)送");
    }
}

測(cè)試執(zhí)行流程

  1. 啟動(dòng) Kafka 服務(wù)
  2. 運(yùn)行 Spring Boot 應(yīng)用
  3. 執(zhí)行測(cè)試用例
  4. 消費(fèi)者控制臺(tái)輸出日志

七、最佳實(shí)踐與配置優(yōu)化

場(chǎng)景配置說明
批量發(fā)送優(yōu)化spring.kafka.producer.batch-size=16384
spring.kafka.producer.linger-ms=100
提升吞吐量 30%+
消費(fèi)者線程控制spring.kafka.consumer.max-poll-records=500防止單次拉取過多消息
事務(wù)保障spring.kafka.consumer.transaction-id-prefix=attendance-trans確保消息與數(shù)據(jù)庫(kù)操作原子性
死信隊(duì)列error-handler.dlq-topic=attendance-topic.DLQ消費(fèi)失敗消息自動(dòng)移至 DLQ
監(jiān)控指標(biāo)micrometer.kafka.enabled=true集成 Prometheus 監(jiān)控

八、常見問題排查(YAML 配置特有)

問題現(xiàn)象解決方案
序列化器未生效ClassCastException: String cannot be cast to AttendanceStatisticsSingleDto檢查 value-serializer 配置路徑是否正確
YAML 縮進(jìn)錯(cuò)誤Invalid configuration嚴(yán)格使用 2 空格縮進(jìn)(避免 Tab)
死信隊(duì)列未創(chuàng)建消息未進(jìn)入 DLQ手動(dòng)創(chuàng)建主題:kafka-topics.sh --create --topic attendance-topic.DLQ --partitions 1 --replication-factor 1
日期格式異常Invalid format for Date在 AttendanceStatisticsSingleDto 中添加 @JsonFormat 注解
消費(fèi)者無法啟動(dòng)No available broker檢查 bootstrap-servers 是否可訪問

九、總結(jié):Spring Boot + Kafka 核心流程

? 關(guān)鍵結(jié)論:

  1. YAML 配置更清晰:避免 properties 中的 spring.kafka.consumer.group-id 拼寫錯(cuò)誤
  2. 自定義序列化器是核心:必須與消息實(shí)體嚴(yán)格匹配
  3. 死信隊(duì)列是生產(chǎn)必備:任何消費(fèi)者都應(yīng)配置 DLQ
  4. 手動(dòng)提交偏移量:避免消息丟失(AckMode.MANUAL)

?? 立即實(shí)踐:

  1. 創(chuàng)建 AttendanceStatisticsSingleDto 實(shí)體
  2. 實(shí)現(xiàn) AttendanceSerializer/AttendanceDeserializer
  3. 配置 application.yml 中的序列化器路徑
  4. 啟動(dòng) Kafka + Spring Boot 服務(wù)
  5. 發(fā)送測(cè)試消息 → 查看消費(fèi)者日志

到此這篇關(guān)于SpringBoot整合Kafka生產(chǎn)環(huán)境標(biāo)準(zhǔn)配置的文章就介紹到這了,更多相關(guān)SpringBoot整合Kafka生產(chǎn)環(huán)境配置內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • Spring Boot 配置文件從基礎(chǔ)語法到驗(yàn)證碼實(shí)戰(zhàn)

    Spring Boot 配置文件從基礎(chǔ)語法到驗(yàn)證碼實(shí)戰(zhàn)

    本文詳細(xì)解析了SpringBoot配置文件的作用及其主流格式,包括Properties和YAML(YML)的語法差異、優(yōu)先級(jí)及適用場(chǎng)景,并通過@Value與@ConfigurationProperties注解的代碼實(shí)戰(zhàn),演示了如何將配置項(xiàng)優(yōu)雅地集成到實(shí)際業(yè)務(wù)中,感興趣的朋友跟隨小編一起看看吧
    2025-12-12
  • springboot的pom.xml配置方式

    springboot的pom.xml配置方式

    這篇文章主要介紹了springboot的pom.xml配置方式,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2022-12-12
  • SpringCloud+Nacos實(shí)現(xiàn)環(huán)境切換與配置管理最佳實(shí)踐

    SpringCloud+Nacos實(shí)現(xiàn)環(huán)境切換與配置管理最佳實(shí)踐

    本文介紹了在SpringBoot項(xiàng)目中,如何通過SpringProfiles、Nacos配置中心及Maven構(gòu)建工具實(shí)現(xiàn)環(huán)境切換和配置管理,需要的朋友可以參考下
    2026-04-04
  • java中ReentrantLock實(shí)現(xiàn)公平鎖和非公平鎖

    java中ReentrantLock實(shí)現(xiàn)公平鎖和非公平鎖

    在Java里,公平鎖和非公平鎖是多線程編程中用于同步的兩種鎖機(jī)制,它們的主要差異在于獲取鎖的順序規(guī)則,下面就來詳細(xì)的介紹一下,感興趣的可以了解一下
    2025-12-12
  • 使用kotlin編寫spring cloud微服務(wù)的過程

    使用kotlin編寫spring cloud微服務(wù)的過程

    這篇文章主要介紹了使用kotlin編寫spring cloud微服務(wù)的相關(guān)知識(shí),本文給大家提到配置文件的操作代碼,給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下
    2021-09-09
  • 解決JDK21中用不了TimeUtild問題

    解決JDK21中用不了TimeUtild問題

    在使用TimeUtil時(shí),可能因?yàn)镮DE版本不兼容導(dǎo)致問題,升級(jí)IDEA到2023.2以上版本可解決此問題,詳細(xì)步驟可以通過評(píng)論區(qū)索取安裝包或直接從官網(wǎng)下載,分享個(gè)人經(jīng)驗(yàn),希望對(duì)大家有幫助
    2024-10-10
  • 基于Java實(shí)現(xiàn)Redis多級(jí)緩存方案

    基于Java實(shí)現(xiàn)Redis多級(jí)緩存方案

    這篇文章主要介紹了Redis多級(jí)緩存方案分享,傳統(tǒng)緩存方案、多級(jí)緩存方案、JVM本地緩存,舉例說明這些方案,具有一定的參考價(jià)值,需要的小伙伴可以參考一下
    2022-03-03
  • Java加解密工具類源碼示例

    Java加解密工具類源碼示例

    最近在項(xiàng)目中接觸到了數(shù)據(jù)加解密的業(yè)務(wù),數(shù)據(jù)加密技術(shù)是網(wǎng)絡(luò)中最基本的安全技術(shù),這篇文章主要給大家介紹了關(guān)于Java加解密工具類源碼的相關(guān)資料,需要的朋友可以參考下
    2023-11-11
  • Java實(shí)現(xiàn)的文本字符串操作工具類實(shí)例【數(shù)據(jù)替換,加密解密操作】

    Java實(shí)現(xiàn)的文本字符串操作工具類實(shí)例【數(shù)據(jù)替換,加密解密操作】

    這篇文章主要介紹了Java實(shí)現(xiàn)的文本字符串操作工具類,可實(shí)現(xiàn)數(shù)據(jù)替換、加密解密等操作,涉及java字符串遍歷、編碼轉(zhuǎn)換、替換等相關(guān)操作技巧,需要的朋友可以參考下
    2017-10-10
  • Java實(shí)現(xiàn)使用Websocket發(fā)送消息詳細(xì)代碼舉例

    Java實(shí)現(xiàn)使用Websocket發(fā)送消息詳細(xì)代碼舉例

    這篇文章主要給大家介紹了關(guān)于Java實(shí)現(xiàn)使用Websocket發(fā)送消息的相關(guān)資料,WebSocket是一種協(xié)議,用于在Web應(yīng)用程序和服務(wù)器之間建立實(shí)時(shí)、雙向的通信連接,文中通過代碼介紹的非常詳細(xì),需要的朋友可以參考下
    2024-05-05

最新評(píng)論

三江| 宾阳县| 九江市| 大足县| 海阳市| 南投县| 高尔夫| 翁牛特旗| 临西县| 澄城县| 高淳县| 卢氏县| 林周县| 安多县| 崇文区| 根河市| 铜川市| 临城县| 手机| 翁牛特旗| 四子王旗| 平武县| 华亭县| 策勒县| 白水县| 乌拉特后旗| 台前县| 桐乡市| 洞口县| 运城市| 长丰县| 崇信县| 黄骅市| 牙克石市| 丰都县| 色达县| 拜城县| 乳山市| 阿克陶县| 沅江市| 镇巴县|