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,歡迎大家關注