微服務

雲原生時代下微服務架構演進之路 (10)

透過本篇文章您可以瞭解到以下內容:

  • 回顧
  • Spring Cloud Stream簡介
  • Spring Cloud Stream深入介紹
  • 總結

回顧

首先讓我們做一個簡單的回顧:

在上一篇文章中我們深入的瞭解了Spring Cloud。 我們知道Spring Cloud提供了一系列開箱即用的元件,開發者只需要透過配置簡單的註解以及編寫少量的yaml 就可以完成快速開發的工作。

這些元件解決的是微服務架構中常見的、共融性的一些問題,比如閘道器、負載均衡、監控、應用層面的高可用(熔斷、降級、限流)。 但是我們會發現這些解決方案中並不包括對消息中間件(Message Queue)的解決方案。 例如有的專案使用Kafka,有的專案使用RabbitMQ等等,那麼對於這些消息中間件(Message Queue)的整合,Spring Cloud又會給出怎樣的解決方案呢?  這時候Spring Cloud Stream就登場了。

Spring Cloud Stream 簡介

在文章的開始,首先讓我們看看官方對於Spring Cloud Stream的定義和介紹:

透過上述的介紹,不難看出,首先Spring關於對數據的集成是始於Spring Integration專案的。 透過其程式設計模型,提供了對開發人員來說一致的開發體驗。

但是在雲時代下,微服務架構就變的尤為重要,幾乎所有的Java開發人員都會使用Spring Boot作為微服務開發框架的首選。

此外在現有專案Spring Integration的基礎上進行再次封裝,並與Spring Boot體系進行融合,也就形成了一個新的專案,即Spring Cloud Stream 。

透過Spring Cloud Stream 開發者又會具備哪些優勢呢?

  • 獨立,隔離似的建構、測試和部署以數據為中心的應用程式。
  • 應用現代微服務架構模式,包括透過消息傳遞的組合。
  • 將應用程式職責與以事件為中心的思想分離。 事件可以表示及時發生的事情,下游消費者應用程式可以對其做出反應,而不知道事件的起源或生產者的身份。
  • 將業務邏輯移植到消息代理上(例如RabbitMQ, Apache Kafka, Amazon Kinesis)。
  • 依賴於框架對常見用例的自動內容類型支援。 使得擴展到不同的數據轉換類型變得可能。

通俗一點來講,比如在我們實際生產的業務系統中用到了Kafka和RabbitMQ等元件,眾所周知的是Kafka和RabbitMQ這兩個消息中間件(Message Queue) 在架構上是不盡相同的。 舉個例子,如果因為業務需要,將現有的Kafka遷移到RabbitMQ那麼勢必會面臨大量代碼以及配置修改的問題。 這無疑對於開發人員來說是非常複雜的。 而Spring Cloud Stream的出現恰恰很好的解決了這個問題。

Spring Cloud Stream是一個建構消息驅動微服務的框架。 對應的應用程式中需要透過Inputs亦或 Outputs來與Spring Cloud Stream中的Binder 進行交互即可。

透過指定對應消息中間件(Message Queue) 例如kafka 或者RabbitMQ的Binder實現與外部代理連結,業務開發人員可以不再關注具體消息中間件(Message Queue) ,只需要關注Binder 提供的抽象概念來使用與之對應的消息中間件(Message Queue) 即可。

Spring Cloud Stream 深入介紹

首先讓我們對Spring Cloud Stream的核心概念有一個全面的認知:

目標活頁夾

負責提供與外部消息傳遞系統集成的元件。

裝訂

外部消息傳遞系統和應用程式提供的消息生產者和消費者(由目標綁定器創建)之間的橋樑。

從上圖中可以看出,Binding等同於連接應用程式和消息中間件(Message Queue) 的橋樑,用於生產消息和對消息進行消費。

在沒有Binding時,我們使用Spring Boot應用要直接與消息中間件(Message Queue) 直接打交道,透過Bingding作為中間層,可以完美實現了應用程式與消息中間件(Message Queue) 細節的隔離和遮罩。 Spring Cloud Stream對消息中間件(Message Queue) 進行了進一步的封裝,可與做到代碼層面的無感知,可以使得開發者動態切換消息中間件(Message Queue) (例如從Kafka切換到RabbitMQ )這樣就做到了高度解耦,使得每一個服務更加關注自己的業務流程。 此外Input對應消費者,Output對應生產者。

Message:

這個相對好理解,即生產者和消費者用於與目標綁定器(以及透過外部消息傳遞系統與其他應用程式)通訊的規範數據結構。

接下來讓我們看下Spring Cloud Stream架構以及常用註解:

@EnableBinding

該註解本身使用@Configuration進行元註釋,觸發Spring Cloud Stream基礎架構的配置。

@StreamListner

用於消費者的佇列進行消息的接收。

中間件

消息中間件(Message Queue) ,可以理解為RabbitMQ或者Kafka等。

@Input

此注解表示輸入的管道,即透過該輸入管道接收到消息。

@Output

此注解表示輸出的管道,即發佈的消息透過此管道從該應用程式發送出去。

除了以上註解以外,Spring Cloud Stream有兩種消費類型,分別是推送模式,以及拉取模式。

推送模式

一旦新的消息出現,會立即發送給消費者。

拉取模式

消費者會主動從消息中間件(Message Queue) 拉取消息,此場景適用於如果希望控制消息的消費速度。

再瞭解完消息的消費類型以後,讓我們看看關於Spring Cloud Stream對分區方面的支援,這裡面值得注意的是,無論整合的中間件是否支援分區,例如Kafka本身支援分區。 Spring Cloud Stream中都能夠使用分區的功能,這裡Spring Cloud Stream對各種分區實現做出了抽象的處理。 它會將消息傳遞給媒介,例如Kafka的Topic,對於RabbitMQ就是Exchange。

值得注意的是,在使用分區處理的時候,需要同時對Producer端和Consumer端進行配置。

與此同時在Spring Cloud Stream中也存在消費組的概念。 對於處於同一消費組中的多個應用出現爭搶時,那麼該消息只會被消費組中的一個實例消費。

我們可以透過spring.cloud.stream.bindings. <channelName>.group參數來聲明當前應用所屬的消費組。 當然如果不進行設置,Spring Cloud Stream會預設創建一個。

最後關於Spring Cloud Stream的例子,大家可以參考如下連結:

https://github.com/spring-cloud/spring-cloud-stream-samples

總結

回顧全篇內容,整體包括以下內容:

  • 首先在開篇我們對Spring Cloud元件進行了回顧。
  • 其次對Spring Cloud Stream進行了宏觀的介紹,包括該專案的由來,解決了什麼問題等。
  • 對Spring Cloud Stream進行了深入介紹

在下一篇文章中我們會對Spring Native進行深入的介紹,敬請期待!

參考連結:

  1. https://spring.io/projects/spring-cloud-stream
  2. https://github.com/spring-cloud/spring-cloud-stream-samples

作者簡介

李剛,VMware 大中華區應用現代化部門高級系統架構師,資深企業級軟體開發和軟體系統架構師。 Spring Cloud開源社區項目貢獻者、Netflix開源社區貢獻者。 近幾年,參與並主導了許多大型企業客戶的應用現代化數位轉型專案,涉及物流、製造、金融等諸多領域。 特別對微服務實現方法、現代化應用架構設計、雲原生實施落地、開源軟體技術等方面有著豐富經驗。