使用Spring Cloud Stream和RabbitMQ實現事件驅動的微服務
讓我們展示如何使用Spring Cloud Stream來設計事件驅動的微服務。首先,Spring Cloud Stream首先有什麼好處?因為Spring AMPQ提供了訪問AMPQ工件所需的一切。如果您不熟悉Spring AMPQ,請檢視此repo,其中包含許多有用的示例。那麼為什麼要使用Spring Cloud Stream ......?
Spring Cloud Stream概念
- Spring Cloud Stream透過Binder概念將使用過的訊息代理與Spring Integration訊息通道繫結在一起。支援RabbitMQ和Kafka。
- Spring Cloud Stream將基礎架構配置從程式碼中分離為屬性檔案。這意味著即使您更改了底層代理,您的Spring Integration程式碼也將是相同的!
示例中的Spring Cloud Stream概念(RabbitMQ)
讓我們有一個名為streamInput的交換,它有兩個佇列streamInput.cities和streamInput.persons。現在讓我們將這兩個佇列插入兩個訊息通道citiesChannel和personsChannel來消費來自它的傳入訊息。使用Spring AMPQ,您需要建立SimpleMessageListenerContainer並在程式碼中連線基礎結構。但這有很多樣板程式碼。使用Spring Cloud Stream,您可以將AMPQ配置分離到屬性檔案:
spring.cloud.stream.bindings.citiesChannel.destination=streamInput spring.cloud.stream.bindings.citiesChannel.group=cities spring.cloud.stream.rabbit.bindings.citiesChannel.consumer.durableSubscription=true spring.cloud.stream.rabbit.bindings.citiesChannel.consumer.bindingRoutingKey=cities spring.cloud.stream.bindings.personsChannel.destination=streamInput spring.cloud.stream.bindings.personsChannel.group=persons spring.cloud.stream.rabbit.bindings.personsChannel.consumer.durableSubscription=true spring.cloud.stream.rabbit.bindings.personsChannel.consumer.bindingRoutingKey=persons |
配置詳細資訊
在類路徑上使用RabbitMQ Binder,每個目標都對映到TopicExchange。在示例中,我建立了名為streamInput的TopicExchange, 並將其附加到兩個訊息通道citiesChannel和personsChannel。
spring.cloud.stream.bindings.citiesChannel.destination = streamInput spring.cloud.stream.bindings.personsChannel.destination = streamInput |
現在您需要了解RabbitMQ繫結器的靈感來自Kafka,佇列的消費者被分組到消費者組中,其中只有一個消費者將獲得訊息。這是有道理的,因為您可以輕鬆擴充套件消費者。
因此,讓我們建立兩個佇列streamInput.persons和streamInput.cities並將它們附加到streamInput TopicExchange和提到的訊息通道
# This will create queue "streamInput.cities" connected to message channel citiesChannel where input messages will land. spring.cloud.stream.bindings.citiesChannel.group=cities # Durable subscription, of course. spring.cloud.stream.rabbit.bindings.citiesChannel.consumer.durableSubscription=true # AMPQ binding to exchange (previous spring.cloud.stream.bindings.<channel name>.destination settings). # Only messages with routingKey = 'cities' will land here. spring.cloud.stream.rabbit.bindings.citiesChannel.consumer.bindingRoutingKey=cities spring.cloud.stream.bindings.personsChannel.group=persons spring.cloud.stream.rabbit.bindings.personsChannel.consumer.durableSubscription=true spring.cloud.stream.rabbit.bindings.personsChannel.consumer.bindingRoutingKey=persons |
連線屬性到Spring Integration
好的,到目前為止我建立了兩個佇列。StreamInput.cities繫結到citiesChannel。StreamInput.persons繫結到peopleChannel。
<destination>.<group>是Spring Cloud Stream約定的佇列命名,現在讓我們將它連線到Spring Integration:
package com.example.spring.cloud.configuration; import org.springframework.cloud.stream.annotation.Input; import org.springframework.messaging.SubscribableChannel; /** * Created by tomask79 on 30.03.17. */ public interface SinkRabbitAPI { String INPUT_CITIES = "citiesChannel"; String INPUT_PERSONS = "personsChannel"; @Input(SinkRabbitAPI.INPUT_CITIES) SubscribableChannel citiesChannel(); @Input(SinkRabbitAPI.INPUT_PERSONS) SubscribableChannel personsChannel(); } |
Spring Boot啟動時載入這個屬性
package com.example.spring.cloud; import com.example.spring.cloud.configuration.SinkRabbitAPI; import com.example.spring.cloud.configuration.SourceRabbitAPI; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.cloud.stream.annotation.EnableBinding; import org.springframework.scheduling.annotation.EnableScheduling; @SpringBootApplication @EnableBinding({SinkRabbitAPI.class}) public class StreamingApplication { public static void main(String[] args) { SpringApplication.run(StreamingApplication.class, args); } } |
在此之後,我們可以建立消費者從繫結的訊息通道中的佇列接收訊息:
import com.example.spring.cloud.configuration.SinkRabbitAPI; import com.example.spring.cloud.configuration.SourceRabbitAPI; import org.springframework.cloud.stream.annotation.StreamListener; import org.springframework.integration.support.MessageBuilder; import org.springframework.messaging.MessageChannel; import org.springframework.messaging.handler.annotation.SendTo; import org.springframework.stereotype.Service; import javax.annotation.Resource; /** * Created by tomask79 on 30.03.17. */ @Service public class ProcessingAMPQEndpoint { @StreamListener(SinkRabbitAPI.INPUT_CITIES) public void processCity(final String city) { System.out.println("Trying to process input city: "+city); } @StreamListener(SinkRabbitAPI.INPUT_PERSONS) public void processPersons(final String person) { System.out.println("Trying to process input person: "+person); } } |
RabbitMQ繫結器和代理配置
Spring Cloud Stream如何知道在哪裡尋找訊息中介軟體?如果在類路徑中找到RabbitMQ繫結器,則使用預設RabbitMQ主機(localhost)和埠(5672)連線到RabbitMQ伺服器。如果您的訊息中介軟體配置在不同埠,則需要配置屬性:
spring: cloud: stream: bindings: ... binders: rabbitbinder: type: rabbit environment: spring: rabbitmq: host: rabbitmq port: 5672 username: XXX password: XXX |
測試訊息消費
- 安裝並執行RabbitMQ代理
- git clone https://tomask79@bitbucket.org/tomask79/spring-cloud-stream-rabbitmq.git
- mvn clean install
- java -jar target / streaming-0.0.1-SNAPSHOT.jar
- 現在使用路由鍵'cities'或'persons'在streamInput Exchange上釋出訊息...輸出應該是:
Started StreamingApplication in 6.513 seconds (JVM running for 6.92) Trying to process input city: sdjfjljksdflkjsdflkjsdfsfd Trying to process input person: sdjfjljksdflkjsdflkjsdfsfd |
使用Spring Cloud Stream重新傳遞訊息
您通常希望在進入DLX交換之前再次嘗試接收訊息。首先,讓我們配置Spring Cloud Stream嘗試重新傳送失敗訊息的次數:
spring.cloud.stream.bindings.personsChannel.consumer.maxAttempts = 6 |
這意味著如果從streamInput.persons佇列接收的訊息出錯,那麼Spring Cloud Stream將嘗試重新傳送六次。讓我們試試,首先讓我們修改接收端點以模擬接收崩潰:
@StreamListener(SinkRabbitAPI.INPUT_PERSONS) public void processPersons(final String person) { System.out.println("Trying to process input person: "+person); throw new RuntimeException(); } |
如果我現在嘗試使用人員路由鍵將某些內容釋出到streamInput交換中,那麼這應該是輸出:
Trying to process input person: sfsdfsdfsd Trying to process input person: sfsdfsdfsd Trying to process input person: sfsdfsdfsd Trying to process input person: sfsdfsdfsd Trying to process input person: sfsdfsdfsd Trying to process input person: sfsdfsdfsd Retry Policy Exhausted at org.springframework.amqp.rabbit.retry.RejectAndDontRequeueRecoverer.recover (RejectAndDontRequeueRecoverer.java:45) ~[spring-rabbit-1.7.0.RELEASE.jar! /:na] at org.springframework.amqp.rabbit.config.StatelessRetryOperationsInterc |
建議將Spring Cloud Stream 用於事件驅動的MicroServices,因為它可以節省時間,而且您不需要為Java中的AMPQ基礎架構編寫樣板程式碼。
相關文章
- 訊息驅動式微服務:Spring Cloud Stream & RabbitMQ微服務SpringCloudMQ
- 使用Spring Cloud Stream和Spring State Machine建立事件驅動的微服務案例SpringCloudMac事件微服務
- springCloud學習5(Spring-Cloud-Stream事件驅動)SpringGCCloud事件
- 事件驅動的微服務-事件驅動設計事件微服務
- Spring Cloud Stream微服務訊息框架SpringCloud微服務框架
- 使用Apache Kafka實現從單體到事件驅動微服務 - swlhApacheKafka事件微服務
- 如何在Java中實現事件驅動的微服務架構Java事件微服務架構
- 基於Spring Boot和Spring Cloud實現微服務架構Spring BootCloud微服務架構
- 使用Redis/RabbitMQ/EventStore實現事件溯源CQRS微服務應用 - Aram KoukiaRedisMQ事件微服務
- (十七) 整合spring cloud雲架構 -訊息驅動 Spring Cloud StreamSpringCloud架構
- spring cloud 微服務實戰SpringCloud微服務
- 結合領域事件和微服務的實現領域驅動設計 - Alagarsamy事件微服務
- 深度解析spring cloud分散式微服務的實現SpringCloud分散式微服務
- Spring Cloud構建微服務架構:訊息驅動的微服務(消費組)【Dalston版】SpringCloud微服務架構
- 基於spring實現事件驅動Spring事件
- spring cloud 和 阿里微服務spring cloud AlibabaSpringCloud阿里微服務
- 基於Spring Cloud Netflix的TCC柔性事務和EDA事件驅動示例SpringCloud事件
- Spring Cloud Stream事件路由 - spring.ioSpringCloud事件路由
- 微服務事件驅動架構演進微服務事件架構
- 【Spring Cloud】Eureka實現微服務釋出與呼叫SpringCloud微服務
- Spring Cloud Alibaba微服務實戰SpringCloud微服務
- Spring Cloud 微服務專案實現總架構一SpringCloud微服務架構
- 業務流程的新實現:微服務和事件編排微服務事件
- Spring Cloud微服務基礎元件實戰SpringCloud微服務元件
- 福利|Spring Cloud 微服務實戰速成指南SpringCloud微服務
- 為什麼微服務應該是事件驅動?微服務事件
- Spring Cloud 終結篇之訊息驅動--stream 大集合SpringCloud
- 帶你自定義實現Spring事件驅動模型Spring事件模型
- 詳解Spring Cloud和Docker的微服務架構SpringCloudDocker微服務架構
- GitHub - soooban/AxonDemo: 使用Axon/Spring Cloud實現事件溯源和CQRS案例GithubSpringCloud事件
- 事件驅動的微服務-建立第三方庫事件微服務
- 微服務Spring Cloud17_Spring Cloud概述3微服務SpringCloud
- Spring:事件驅動Spring事件
- Spring IO 2019大會上Axon+Spring的事件驅動微服務和CQRS原始碼專案Spring事件微服務原始碼
- Spring Cloud 微服務的那點事SpringCloud微服務
- 基於Spring Cloud的微服務落地SpringCloud微服務
- 微服務閘道器實戰——Spring Cloud Gateway微服務SpringCloudGateway
- Spring Cloud 微服務實戰詳細筆記SpringCloud微服務筆記