Spring Cloud 快速入門(八)訊息系統整合框架 Spring Cloud Stream
1. 簡介
1.1 官網
【原文】A lightweight event-driven microservices framework to quickly build applications that can connect to external systems. Simple declarative(聲名式的) model to send and receive messages using Apache Kafka or RabbitMQ between Spring Boot apps.
【翻譯】一個輕量級的事件驅動微服務框架,用於快速構建可連線到外部系統的應用程式。在 Spring Boot 應用程式之間使用 Kafka 或 RabbitMQ 傳送和接收訊息的簡單宣告式模型。
1.2 綜合
Spring Cloud Stream 是一個用來為微服務應用構建訊息驅動能力的框架。通過使用Spring Cloud Stream,可以有效簡化開發人員對訊息中介軟體的使用複雜度,讓系統開發人員可以有更多的精力關注於核心業務邏輯的處理。但是目前 Spring Cloud Stream 只支援RabbitMQ 和 Kafka 的自動化配置。
2 程式模型
spring cloud 官網首頁中點選相應版本的參考文件。
應用程式的核心部分(Application Core)通過 inputs 與 outputs 管道,與中介軟體連線,而管道是通過繫結器 Binder 與中介軟體相繫結的。
3. stream kafka 微服務
3.1 總步驟
(1) 建立生產者步驟
- 匯入 spring-cloud-stream-binder-kafka 依賴
- 建立生產者類。在生產者類上新增@EnableBinding()註解,並宣告管道
- 定義處理器,在處理器中呼叫訊息生產者,使其傳送訊息
- 在配置檔案中註冊 kafka 叢集,並指定管道所繫結的主題及型別
(2) 建立消費者步驟
- 匯入 spring-cloud-stream-binder-kafka 依賴
- 建立消費者類。在消費者類上新增@EnableBinding()註解,並宣告管道。
- 在消費者類中定義消費方法,在方法上新增相應的註解。
- 在配置檔案中註冊 kafka 叢集,並指定管道所繫結的主題
3.2 訊息傳送給一個主題的生產者
(1) 建立工程 08-stream-kafka-8080
任意複製前面的一個提供者或消費者工程,將其中的除啟動類之外的其它程式碼全部刪除。這裡複製 02-consumer-8080 工程,並命名為 08-stream-kafka-8080。
修改啟動類類名ApplicationStreamKafka8080。
(2) 匯入依賴
僅需再新增一個 Spring Cloud Stream Kafka 相關的依賴即可。
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-stream-binder-kafka</artifactId>
</dependency>
整個 pom.xml 檔案的內容如下:
<groupId>com.abc</groupId>
<artifactId>08-stream-kafka-8080</artifactId>
<version>0.0.1-SNAPSHOT</version>
<properties>
<java.version>1.8</java.version>
<spring-cloud.version>Hoxton.SR1</spring-cloud.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-stream-binder-kafka</artifactId>
</dependency>
<!--actuator依賴-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
<!--eureka客戶端依賴-->
<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.projectlombok</groupId>
<artifactId>lombok</artifactId>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
<exclusions>
<exclusion>
<groupId>org.junit.vintage</groupId>
<artifactId>junit-vintage-engine</artifactId>
</exclusion>
</exclusions>
</dependency>
</dependencies>
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-dependencies</artifactId>
<version>${spring-cloud.version}</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
(3) 建立生產者類
@Component
// 將MQ與生產者類通過訊息管道相繫結
// org.springframework.cloud.stream.messaging.Source
@EnableBinding(Source.class)
public class SomeProducer {
// 必須使用byName方式的自動注入
// 系統中還定義了名稱為nullChannel和errorChannel的兩個同型別管道
@Autowired
@Qualifier(Source.OUTPUT)//Source.OUTPUT="output"
private MessageChannel channel;
public String sendMessage(String msg) {
// 通過訊息管道傳送訊息,即將訊息寫入到訊息管道,再通過訊息管道寫入到MQ
channel.send(MessageBuilder.withPayload(msg).build());
return msg;
}
}
(4) 建立處理器
@RestController
public class SomeController {
// 將生產者注入
@Autowired
private SomeProducer producer;
@PostMapping("/msg/send")
public String sendHandler(@RequestParam("message") String msg) {
// 生產者傳送訊息
return producer.sendMessage(msg);
}
}
(5) 建立配置檔案
spring:
application:
name: abcmsc-consumer-depart
cloud:
stream:
kafka:
binder:
# 指定要連線的kafka叢集
brokers: kafkaOS1:9092,kafkaOS2:9092,kafkaOS3:9092
# 指定是否自動建立主題
auto-create-topics: true
bindings:
# 指定要繫結的輸出管道,及要輸出到單管道中的訊息主題及型別
output:
destination: persons # 主題
content-type: text/plain
eureka:
client:
service-url:
defaultZone: http://localhost:8000/eureka
(6) 演示
kafka消費者先用命令列方式:
因為我機器上已經有persons主題了,為了演示自動建立主題,換成names:
傳送多次:
3.3 訊息傳送給多個主題的生產者
前面工程中通過 Source 的 MessageChannel 完成了將訊息傳送給某個指定主題的功能,若要將訊息傳送給多個主題,則需要自定義 Channel。
(1) 建立工程 08-stream-kafka2-8080
複製前面的 08-stream-kafka-8080,重新命名為 08-stream-kafka2-8080。
修改啟動類類名ApplicationStreamKafka28080。
(2) 定義 Source 介面
模擬 Source 介面自定義一個 Source 介面。
/**
* 自定義管道
*/
public interface CustomSource {
//管道名稱
String CHANNEL_NAME = "xxx";
@Output(CustomSource.CHANNEL_NAME)
MessageChannel output();
}
(3) 修改釋出者類
@Component
// 將MQ與生產者類通過訊息管道相繫結
@EnableBinding({Source.class, CustomSource.class})
public class SomeProducer {
// 必須使用byName方式的自動注入
@Autowired
@Qualifier(Source.OUTPUT)
private MessageChannel channel;
@Autowired
@Qualifier(CustomSource.CHANNEL_NAME)
private MessageChannel customChannel;
public String sendMessage(String msg) {
// 將訊息寫入到兩個管道,將會寫入到兩個主題
channel.send(MessageBuilder.withPayload(msg).build());
customChannel.send(MessageBuilder.withPayload(msg).build());
return msg;
}
}
(4) 修改配置檔案
在配置檔案中新增如下輸出目標。
spring:
application:
name: abcmsc-consumer-depart
cloud:
stream:
kafka:
binder:
# 指定要連線的kafka叢集
brokers: kafkaOS1:9092,kafkaOS2:9092,kafkaOS3:9092
# 指定是否自動建立主題
auto-create-topics: true
bindings:
# 指定要繫結的輸出管道,及要輸出到單管道中的訊息主題及型別
output:
destination: names
content-type: text/plain
xxx:
destination: cities
content-type: text/plain
eureka:
client:
service-url:
defaultZone: http://localhost:8000/eureka
(5) 效果
傳送訊息:dddddd、eeeeee、fffff
結果:
3.4 建立訊息消費者 – @PostConstruct 方式
Spring Cloud Stream 提供了三種建立消費者的方式,這三種方式的都是在消費者類的“消費”方法上新增註解。只要有新的訊息寫入到了管道,該“消費”方法就會執行。只不過三種註解,其底層的實現方式不同。即當新訊息到來後,觸發“消費”方法去執行的實現方式不同。
- @PostConstruct:以釋出/訂閱方式實現
- @ServiceActivator:新的訊息啟用服務方式實現
- @StreamListener:以監聽方式實現
為了簡單起見,這裡就不再單獨建立消費者工程了,都直接定義在前面的生產者工程中。
(1) 建立消費者類
@Component
@EnableBinding(Sink.class) //和生產者Source註解類似,繫結了一個輸入通道
public class SomeConsumer {
@Autowired
@Qualifier(Sink.INPUT)
private SubscribableChannel channel;
@PostConstruct //以釋出/訂閱方式實現
public void printMessage() {
//為輸入通道註冊訊息處理程式。
channel.subscribe(msg -> {
// MessageHeaders headers = msg.getHeaders();
System.out.println(new String((byte[])msg.getPayload()));
});
}
}
(2) 修改配置檔案
spring:
application:
name: abcmsc-consumer-depart
cloud:
stream:
kafka:
binder:
# 指定要連線的kafka叢集
brokers: kafkaOS1:9092,kafkaOS2:9092,kafkaOS3:9092
# 指定是否自動建立主題
auto-create-topics: true
bindings:
# 指定要繫結的輸出管道,及要輸出到單管道中的訊息主題及型別
output:
destination: names
content-type: text/plain
xxx:
destination: cities
content-type: text/plain
# 指定要繫結的輸入管道,及要消費的管道中的訊息主題
input:
destination: names
eureka:
client:
service-url:
defaultZone: http://localhost:8000/eureka
(3) 效果
3.5 建立訊息消費者 – @ServiceActivator 方式
該註解所標註的方法是以服務的形式出現的,只要管道中的資料發生了變化就會啟用該服務。
(1) 註釋掉前面的消費者
將前面的消費者類註釋掉,其將不會出現在 Spring 容器。
(2) 建立消費者類
@Component
@EnableBinding(Sink.class)//繫結一個輸入通道
public class SomeConsumer2 {
//指示方法能夠處理訊息或訊息有效負載。
//註釋為@Serviceactivator的方法可以接受型別
//為{@link org.springframework.messaging.Message}或預期訊息有效負載型別的引數。
//如果需要,{@link org.springframework.beans.SimpleTypeConverter}支援的任何型別
//轉換都將應用於訊息有效負載。通過使
//用{@link org.springframework.messaging.handler.annotation.Header @Header}引數註解
//訊息頭的值也可以作為訊息引數傳遞。
//註釋方法的返回值可以是任何型別。如果返回值不是訊息,則將以該物件作為其有效負載建立應答訊息。
@ServiceActivator(inputChannel = Sink.INPUT)
public void printMessage(Object msg) {
System.out.println(msg);
}
}
3.6 建立訊息消費者 – @SteamListener 方式
該方式是以監聽的方式實現,只要管道中的流資料發生變化,其就會觸發該註解所標註的方法的執行。
(1) 註釋掉前面的消費者
(2) 建立消費者類
@Component
@EnableBinding(Sink.class)//繫結一個輸入通道
public class SomeConsumer3 {
//將一個方法標記為通過{@link EnableBinding}(例如通道)宣告的輸入的偵聽器的註解。
@StreamListener(Sink.INPUT)
public void printMessage(Object msg) {
System.out.println(msg);
}
}
相關文章
- Spring Cloud Stream微服務訊息框架SpringCloud微服務框架
- (十七) 整合spring cloud雲架構 -訊息驅動 Spring Cloud StreamSpringCloud架構
- RocketMQ 整合 Spring Cloud StreamMQSpringCloud
- 最完整的 Spring Cloud 元件-訊息中介軟體 Spring Cloud Stream 使用教程SpringCloud元件
- 訊息驅動式微服務:Spring Cloud Stream & RabbitMQ微服務SpringCloudMQ
- Spring Cloud Stream如何處理訊息重複消費?SpringCloud
- Spring Cloud Stream如何消費自己生產的訊息?SpringCloud
- Spring Cloud Gateway 入門SpringCloudGateway
- Spring Cloud 整合SpringCloud
- Spring Cloud Gateway入門 - spring.ioSpringCloudGateway
- Spring Cloud Stream事件路由 - spring.ioSpringCloud事件路由
- Spring Cloud Gateway 入門案例SpringCloudGateway
- Spring Cloud Alibaba入門篇SpringCloud
- Spring Cloud 終結篇之訊息驅動--stream 大集合SpringCloud
- spring cloud 整合 nacosSpringCloud
- 整合spring cloud雲架構 - Gateway的基本入門SpringCloud架構Gateway
- 整合spring cloud雲架構 --spring cloud分散式系統中實現分散式鎖SpringCloud架構分散式
- Spring Cloud Stream 體系及原理介紹SpringCloud
- Spring Boot整合Spring Cloud Netflix元件Spring BootCloud元件
- Spring Cloud Gateway (一)入門篇SpringCloudGateway
- Spring Cloud Gateway---GlobalFilter(入門)SpringCloudGatewayFilter
- Spring Cloud Alibaba(1)---入門篇SpringCloud
- spring cloud config 整合svnSpringCloud
- java版spring cloud+spring cloud 工程管理系統原始碼JavaSpringCloud原始碼
- Spring Cloud(八)高可用的分散式配置中心 Spring Cloud ConfigSpringCloud分散式
- 跟我學SpringCloud | 第八篇:Spring Cloud Bus 訊息匯流排SpringGCCloud
- spring Cloud Gateway 入門簡單使用SpringCloudGateway
- 一文入門 Spring Cloud TencentSpringCloud
- Spring Cloud(二):Spring Cloud ConfigSpringCloud
- Kafka入門(構建TB級非同步訊息系統)及Spring整合KafkaKafka非同步Spring
- Spring Cloud OpenFeign整合Protocol BufferSpringCloudProtocol
- java B2B2C Springboot多租戶電子商城系統-Spring Cloud Stream(訊息驅動)JavaSpring BootCloud
- Spring Cloud Bus 訊息匯流排介紹SpringCloud
- Spring Cloud Stream如何深度支援Apache Kafka?SpringCloudApacheKafka
- [Spring Cloud Tutorial翻譯系列二]Spring Cloud Config Server與git整合SpringCloudServerGit
- 快速突擊 Spring Cloud GatewaySpringCloudGateway
- (十六) 整合spring cloud雲架構 -使用spring cloud Bus重新整理配置SpringCloud架構
- spring框架快速入門筆記Spring框架筆記