SpringCloud 2020.0.4 系列之 Stream 訊息出錯重試 與 死信佇列 的實現

追風人聊Java發表於2021-11-17

1. 概述

老話說的好:出錯不怕,怕的是出了錯,卻不去改正。如果屢次出錯,無法改對,就先記下了,然後找援軍解決。

 

言歸正傳,今天來聊一下 Stream 元件的 出錯重試 和 死信佇列。

 

RabbitMQ 映象模式叢集的搭建,可參見我的另一篇文章《RabbitMQ 3.9.7 映象模式叢集的搭建》(https://www.cnblogs.com/w84422/p/15356202.html

 

在早期的 SpringCloud 版本中常使用 @Input、@Output、@EnableBinding 和 @StreamListener 註解開發生產者與消費者。

官方原文:Deprecated as of 3.1 in favor of functional programming model。

SpringCloud 2020.0.4 版本中,已經不推薦這麼開發了,因此這裡我們也使用新的寫法(函數語言程式設計方式) 開發。

 

閒話不多說,直接上程式碼。

 

2. 訊息出錯重試

2.1 主要依賴 

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        <!-- 健康檢查 -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-actuator</artifactId>
        </dependency>

        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-stream-rabbit</artifactId>
        </dependency>

 

2.2 訊息實體類

@Setter
@Getter
public class MyMessage implements java.io.Serializable {

    // 訊息體
    private String payload;
}

 

2.3 生產者

    // 訊息出錯重試
    @GetMapping("/retry")
    public String sendRetryMessage(@RequestParam("body") String body) {

        MyMessage myMessage = new MyMessage();
        myMessage.setPayload(body);

        // 生產訊息
        // 第一個引數是繫結名稱,格式為:自定義的繫結名稱-out-0,myRetry是自定義的繫結名稱,out代表生產者,0是固定寫法
        // 自定義的繫結名稱必須與消費方法的方法名保持一致
        // 第二個引數是傳送的訊息實體
        streamBridge.send("myRetry-out-0", myMessage);
        return "SUCCESS";
    }

 

2.4 消費者

    // 訊息出錯重試
    @Bean
    public Consumer<MyMessage> myRetry() {  // 方法名必須與生產訊息時自定義的繫結名稱一致

        return message -> {
            log.info("接收訊息:{}", message.getPayload());
            throw new RuntimeException("消費報錯");
        };
    }

 

2.5 application.yml 配置

spring:
  application:
    name: my-stream-new
  rabbitmq:   # RabbitMQ 配置
    addresses: 192.168.1.12:5672
    username: guest
    password: guest
    virtual-host: /
    connection-timeout: 16000
  cloud:
    function:
      # 定義消費者,多個用分號分隔,當存在大於1個的消費者時,不定義不會生效
      definition: myRetry
    stream:
      bindings:
        # 訊息出錯重試
        myRetry-in-0:
          destination: my-retry-topic
          # 配置重試次數(本機重試)
          # 次數等於 1 ,相當於不重試
          consumer:
            max-attempts: 3
        myRetry-out-0:
          destination: my-retry-topic

 

2.6 驗證訊息出錯重試

傳送訊息介面:

Get http://localhost:49000/stream/retry?body=出錯重試訊息

 

自動生成的 Exchange

 

 

 

自動生成的 Queue

 

 

 

消費情況

 

 

3. 死信佇列

3.1 生產者

    // 死信佇列
    @GetMapping("/dlq")
    public String sendDlqMessage(@RequestParam("body") String body) {

        MyMessage myMessage = new MyMessage();
        myMessage.setPayload(body);

        // 生產訊息
        // 第一個引數是繫結名稱,格式為:自定義的繫結名稱-out-0,myDlq是自定義的繫結名稱,out代表生產者,0是固定寫法
        // 自定義的繫結名稱必須與消費方法的方法名保持一致
        // 第二個引數是傳送的訊息實體
        streamBridge.send("myDlq-out-0", myMessage);
        return "SUCCESS";
    }

 

3.2 消費者

    // 死信佇列
    @Bean
    public Consumer<MyMessage> myDlq() {  // 方法名必須與生產訊息時自定義的繫結名稱一致

        return message -> {
            log.info("接收訊息:{}", message.getPayload());
            throw new RuntimeException("消費報錯");
        };
    }

 

3.3 application.yml 配置

spring:
  application:
    name: my-stream-new
  rabbitmq:   # RabbitMQ 配置
    addresses: 192.168.1.12:5672
    username: guest
    password: guest
    virtual-host: /
    connection-timeout: 16000
  cloud:
    function:
      # 定義消費者,多個用分號分隔,當存在大於1個的消費者時,不定義不會生效
      definition: myRetry;myDlq
    stream:
      bindings:       
        # 訊息出錯重試
        myRetry-in-0:
          destination: my-retry-topic
          # 配置重試次數(本機重試)
          # 次數等於 1 ,相當於不重試
          consumer:
            max-attempts: 3
        myRetry-out-0:
          destination: my-retry-topic

        # 死信佇列
        myDlq-in-0:
          destination: my-dlq-topic
          group: dlq-group
          # 配置重試次數(本機重試)
          # 次數等於 1 ,相當於不重試
          consumer:
            max-attempts: 3
        myDlq-out-0:
          destination: my-dlq-topic

      rabbit:
        bindings:
          # 死信佇列
          myDlq-in-0:
            consumer:
              autoBindDlq: true   # 自動繫結死信佇列,會自動建立一個預設的死信佇列
          myDlq-out-0:
            producer:
              autoBindDlq: true   # 自動繫結死信佇列,會自動建立一個預設的死信佇列

 

3.4 驗證死信佇列

傳送訊息介面:

GET http://localhost:49000/stream/dlq?body=死信佇列

 

自動生成的 Exchange

 

 

 

自動生成的 Queue

 

 

 

消費情況

 

 

死信佇列情況

 

 

4. 綜述

今天聊了一下 SpringCloud Stream 元件 訊息出錯重試 與 死信佇列 的實現 ,希望可以對大家的工作有所幫助。

歡迎幫忙點贊、評論、轉發、加關注 :)

關注追風人聊Java,每天更新Java乾貨。

 

5. 個人公眾號

追風人聊Java,歡迎大家關注

 

相關文章