SpringCloud Stream消息驅動

一、概述

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

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章