一、概述
1、簡介
Spring Cloud Stream是一個框架,用於構建與共享消息系統連接的高度可擴展的事件驅動型微服務。該框架提供了一個靈活的編程模型,該模型建立在已經建立並熟悉的Spring習慣用法和最佳實踐的基礎上,包括對持久性pub / sub語義,使用者組和有狀態分區的支持。可以屏蔽底層消息中間件的差異,降低切換成本,統一消息的編程模型。官方文檔地址:https://cloud.spring.io/spring-cloud-static/spring-cloud-stream/3.0.3.RELEASE/reference/html/ 。
2、設計思想
通過定義綁定器作爲中間件,實現應用程序與消息中間件細節之間的隔離,遵循發佈/訂閱模式。架構如下:
說明:
組成 | 說明 |
---|---|
Middleware | 中間件,目前只支持RibbitMQ和Kafaka |
Binder | Binder是應用與消息中間件之間的封裝,目前實行了Kafka和RabbitMQ的Binder,通過Binder可以很方便的連接中間件,可以動態的改變消息類型(對應於Kafka的topic,RabbitMQ的exchange),這些都可以通過配置文件來實現。 |
@Input | 註解標識輸入通道,通過該輸入通道接收到的消息進入應用程序 |
@Output | 註解標識輸出通道,發佈的消息將通過該通道離開應用程序 |
@StreamListener | 監聽隊列,用於消費者的隊列的消息接收 |
@EnableBinding | 指信道channel和exchange綁定在一起 |
二、實現步驟
1、生產者配置
-
新建一個模塊,在pom中添加以下依賴;
<dependencies> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-stream-rabbit</artifactId> </dependency> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId> </dependency> <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.boot</groupId> <artifactId>spring-boot-devtools</artifactId> <scope>runtime</scope> <optional>true</optional> </dependency> <dependency> <groupId>org.projectlombok</groupId> <artifactId>lombok</artifactId> <optional>true</optional> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-test</artifactId> <scope>test</scope> </dependency> </dependencies>
-
配置application.yml文件
server: port: 8801 spring: application: name: cloud-stream-provider cloud: stream: binders: #配置需要綁定的rabbitmq 的服務信息 defaultRabbit: #表示定義的名稱,用於與binding整合 type: rabbit #消息組件類型 environment: #設置rabbitmq的相關環境 spring: rabbitmq: host: localhost port: 5672 username: guest password: guest bindings: #服務的整合處理 output: #通道名稱 destination: studyExchange #要使用的Exchange名稱定義 content-type: application/json #設置消息類型 binder: defaultRabbit #設置要綁定的消息服務的具體設置 eureka: client: service-url: defaultZone: http://localhost:7001/eureka instance: lease-renewal-interval-in-seconds: 2 #設置心跳的間隔時間(默認30秒) lease-expiration-duration-in-seconds: 5 #間隔時間 instance-id: sned-8801.com #信息列表顯示主機名稱 prefer-ip-address: true #顯示ip地址
-
定義一個消息推送類;
@EnableBinding(Source.class)//定義消息的推送管道 public class MessageProviderImpl implements IMessageProvider { @Resource private MessageChannel output;//消息發送管道 public String send() { String serial = UUID.randomUUID().toString(); output.send(MessageBuilder.withPayload(serial).build()); System.out.println("************"+serial); return serial; } }
-
控制類調用上面的消息推送類;
@Resource private IMessageProvider messageProvider; @GetMapping("/sendMessage") public String sendMessage(){ return messageProvider.send(); }
2、消費者配置
-
新建一個模塊,在pom中添加依賴(同生產者一樣);
-
配置application.yml文件,只需修改 output 爲 input;
server: port: 8802 spring: application: name: cloud-stream-consumer cloud: stream: binders: #配置需要綁定的rabbitmq 的服務信息 defaultRabbit: #表示定義的名稱,用於與binding整合 type: rabbit #消息組件類型 environment: #設置rabbitmq的相關環境 spring: rabbitmq: host: localhost port: 5672 username: guest password: guest bindings: #服務的整合處理 input: #通道名稱 destination: studyExchange #要使用的Exchange名稱定義 content-type: application/json #設置消息類型 binder: defaultRabbit #設置要綁定的消息服務的具體設置 eureka: client: service-url: defaultZone: http://localhost:7001/eureka instance: lease-renewal-interval-in-seconds: 2 #設置心跳的間隔時間(默認30秒) lease-expiration-duration-in-seconds: 5 #間隔時間 instance-id: receive-8802.com #信息列表顯示主機名稱 prefer-ip-address: true #顯示ip地址
-
消費者業務類編寫,需要開啓綁定,定義消息接收管道 @EnableBinding(Sink.class),使用@StreamListener(Sink.INPUT) 監聽隊列,用於消費者的隊列的消息接收。
@Component @EnableBinding(Sink.class) public class ReceiveMessageListenerController { @Value("${server.port}") private String serverPort; @StreamListener(Sink.INPUT) public void input(Message<String> message){ System.out.println("消費者1號,--------------接收到的消息:"+message.getPayload()+"\t port"+serverPort); } }
3、分組消費與持久化
在集羣服務中,一個消息可能會被消費多次,將其放入同一個group中,就能夠保證消息只會被其中一個應用消費一次。不同的組是可以消費的,同一個組內會發生競爭關係,只有其中一個可以消費。只需要自定義分組就可以完成分組與持久化,在客戶端加上配置 group。
spring:
application:
name: cloud-stream-consumer
cloud:
stream:
bindings: #服務的整合處理
input: #通道名稱
destination: studyExchange #要使用的Exchange名稱定義
content-type: application/json #設置消息類型
binder: defaultRabbit #設置要綁定的消息服務的具體設置
group: groupA #自定義分組
案例代碼地址:https://github.com/xhanglog/springcloud-learning