Springboot專案中使用Kafka

溪源的奇思妙想發表於2020-08-05

Springboot專案中使用Kafka

第一步:安裝好Kafka伺服器

具體可參考: https://blog.csdn.net/weixin_40990818/article/details/107793976

第二步:建立Kafka生產者

a.引入依賴

<!--Kafka依賴-->
<dependency>
    <groupId>org.springframework.kafka</groupId>
    <artifactId>spring-kafka</artifactId>
</dependency>

b.spring-kafka-producer.xml:以XML的方式配置生產者

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
       http://www.springframework.org/schema/beans/spring-beans.xsd">

    <!-- 定義producer的引數 -->
    <bean id="producerProperties" class="java.util.HashMap">
        <constructor-arg>
            <map>
                <entry key="bootstrap.servers" value="127.0.0.1:9092"/>
                <!-- acks表示所有需同步返回確認的節點數,all或者‑1表示分割槽全部備份節點均需響應,可靠性最
                高,但吞吐量會相對降低;
                1表示只需分割槽leader節點響應;
                0表示無需等待服務端響應;
                大部分業務建議配置1,風控或安全建議配置0 -->
                <entry key="acks" value="1"/>
                <!-- retries表示重試次數,如果配置重試請保證消費端具有業務上冪等,根據業務需求配置  -->
                <entry key="retries" value="1"/>
                <!-- 傳送訊息請求的超時時間,規範2000 -->
                <entry key="request.timeout.ms" value="2000"/>
                <!-- 如果傳送方buffer滿或者獲取不到後設資料時最大阻塞時間,規範2000 -->
                <entry key="max.block.ms" value="2000"/>
                <entry key="key.serializer" value="org.apache.kafka.common.serialization.StringSerializer"/>
                <entry key="value.serializer" value="org.apache.kafka.common.serialization.StringSerializer"/>
            </map>
        </constructor-arg>
    </bean>


    <!-- 建立kafkaTemplate需要使用的producerFactory bean -->
    <bean id="defaultKafkaProducerFactory" class="org.springframework.kafka.core.DefaultKafkaProducerFactory">
        <constructor-arg ref="producerProperties"/>
    </bean>


    <!-- 建立kafkaTemplate傳送模版 -->
    <bean id="kafkaTemplate" class="org.springframework.kafka.core.KafkaTemplate">
        <constructor-arg ref="defaultKafkaProducerFactory"/>
        <!-- autoFlush=true表示與kafka同步互動,可靠性高但吞吐量較差,核心場景可以配置true,一般設為false -->
        <constructor-arg name="autoFlush" value="false"/>
    </bean>
</beans>

c.在啟動類引入spring-kafka-producer.xml配置類

@SpringBootApplication(exclude = {DataSourceAutoConfiguration.class})
@ImportResource("classpath:*spring-kafka-producer.xml")
public class UsermanageAPP extends SpringBootServletInitializer {
    private static Logger logger= LogManager.getLogger(LogManager.ROOT_LOGGER_NAME);

    @Override
    protected SpringApplicationBuilder configure(SpringApplicationBuilder application) {
        return application.sources(UsermanageAPP.class);
    }

    /**
     * 專案的啟動方法
     * @param args
     */
    public static void main(String[] args) {
        SpringApplication.run(UsermanageAPP.class, args);
        logger.info("======服務已經啟動========");
    }
}

d.使用kafkaTemplate傳送訊息

@RestController
public class UserManageController {

    @Autowired
    private KafkaTemplate kafkaTemplate;

    public static final String TOPIC_NAME = "my-replicated-topic";

    @RequestMapping("/hello")
    public void test(){
        kafkaTemplate.send(TOPIC_NAME, "123");
    }

}

e.訪問127.0.0.1:8080/hello後,進入kafka中進行驗證
在這裡插入圖片描述

第二步:建立Kafka消費者

a.引入依賴

<!--Kafka依賴-->
<dependency>
    <groupId>org.springframework.kafka</groupId>
    <artifactId>spring-kafka</artifactId>
</dependency>

b.spring-kafka-consumer.xml:以XML的方式配置消費者
groupId:consumer group是kafka提供的可擴充套件且具有容錯性的消費者機制。一個組可以有多個消費者或消費者例項(consumer instance),它們共享一個公共的ID,即group ID。
組內的所有消費者協調在一起來消費訂閱主題(subscribed topics)的所有分割槽(partition)。當然,每個分割槽只能由同一個消費組內的一個consumer來消費,從而保證訊息不會被重複消費。

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:context="http://www.springframework.org/schema/context"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
       http://www.springframework.org/schema/beans/spring-beans.xsd
       http://www.springframework.org/schema/context
       http://www.springframework.org/schema/context/spring-context.xsd">


<!-- 定義consumer的引數 -->
    <bean id="consumerProperties" class="java.util.HashMap">
        <constructor-arg>
            <map>
                <entry key="bootstrap.servers" value="127.0.0.1:9092" />
                <!--關閉自動提交,使用spring實現的提交方案-->
                <entry key="enable.auto.commit" value="false" />
                <entry key="key.deserializer" value="org.apache.kafka.common.serialization.StringDeserializer" />
                <entry key="value.deserializer" value="org.apache.kafka.common.serialization.StringDeserializer" />
            </map>
        </constructor-arg>
    </bean>

    <!-- 建立consumerFactory bean -->
    <bean id="consumerFactory"
          class="org.springframework.kafka.core.DefaultKafkaConsumerFactory">
        <constructor-arg ref="consumerProperties"/>
    </bean>


    <!-- 這裡以收單為例 -->
    <!-- start 收單 -->
    <!-- 訊息監聽器,實際執行訊息消費的類  收單-->
    <bean id="tradeprodMessageListener" class="com.luo.nacos.kafka.TradeprodMessageListener" />
    <!-- 消費者容器配置資訊 收單-->
    <bean id="tradeprodProperties" class="org.springframework.kafka.listener.ContainerProperties">
        <constructor-arg value="my-replicated-topic" />
        <!-- 每接收到一條訊息ack一次,可靠性最高 -->
        <property name="ackMode" value="RECORD" />
        <property name="groupId" value="my-replicated-topic" />
        <!--  訊息監聽器  -->
        <property name="messageListener" ref="tradeprodMessageListener" />
    </bean>
    <!--消費者容器 -->
    <bean id="tradeprodListenerContainer" class="org.springframework.kafka.listener.ConcurrentMessageListenerContainer"
          init-method="doStart">
        <constructor-arg ref="consumerFactory" />
        <constructor-arg ref="tradeprodProperties" />
        <!-- 多執行緒消費 -->
        <property name="concurrency" value="3" />
    </bean>
    <!-- end 收單 -->


</beans>

c.啟動類引入spring-kafka-consumer.xml配置檔案

@SpringBootApplication(exclude = {DataSourceAutoConfiguration.class})
@ImportResource("classpath:*spring-kafka-consumer.xml")
public class NacosApp extends SpringBootServletInitializer {
    private static Logger logger= LogManager.getLogger(LogManager.ROOT_LOGGER_NAME);

    @Override
    protected SpringApplicationBuilder configure(SpringApplicationBuilder application) {
        return application.sources(NacosApp.class);
    }
    /**
     * 專案的啟動方法
     * @param args
     */
    public static void main(String[] args) {
        SpringApplication.run(NacosApp.class, args);
        logger.info("======服務已經啟動========");
    }
}

d.TradeprodMessageListener :訊息消費的類要實現MessageListener介面,重寫onMessage方法

public class TradeprodMessageListener implements MessageListener<String, String> {

    @Override
    public void onMessage(ConsumerRecord<String, String> record) {
        try {
            if (record != null && record.value() != null) {
                System.out.println("收到kafka訊息:"+ record.value());
            }
        } catch (Exception e) {
            System.out.println("消費kafka訊息失敗,失敗原因:"+ e.getMessage());
        }
    }
}

e.利用生產者產生訊息進行驗證
在這裡插入圖片描述

在這裡插入圖片描述

相關文章