Spring Cloud: Overview 概述

超悠閒發表於2020-12-15

Spring Cloud: Overview 概述

簡介

經過一些前後端專案的洗禮,也經歷過幾次使用 SpringBoot 開發後端伺服器,搭配 mybatis + mysql 資料庫、redis 快取等技術。接下來從本篇開始將要開始進入微服務的架構。

Spring 全家桶繼 SpringBoot 之後最火的技術便是 SpringCloud 微服務架構。有關什麼是微服務可以檢視參考連結,網路上也有很多對於微服務的說明和討論,接下來我們就來縱覽 Spring Cloud 到底有哪些成員以及功能吧!

備註:推薦讀者可以先去看看參考連結二的視訊再回來本篇的說明,會有更清晰的認識

參考

什麼是微服務架構?https://www.zhihu.com/question/65502802
The Beginner’s Guide To Spring Cloud - Ryan Baxterhttps://www.youtube.com/watch?v=aO3W-lYnw-o&t=3538s
Spring Cloudhttps://spring.io/projects/spring-cloud
SpringCloud之Eureka註冊中心原理及其搭建https://www.cnblogs.com/jing99/p/11576133.html
分散式配置——Spring Cloud Configurationhttps://www.jianshu.com/p/b43f41cdcbe2
從0開始構建你的api閘道器--Spring Cloud Gateway閘道器實戰及原理解析https://www.cnblogs.com/davidwang456/p/10411451.html
斷路器(Curcuit Breaker)模式https://www.cnblogs.com/chry/p/7278853.html
Spring Cloud Pipeline–契約測試(Contracts Test)http://huhanlin.com/2018/06/06/spring-cloud-pipeline-%E5%A5%91%E7%BA%A6%E6%B5%8B%E8%AF%95%EF%BC%88contracts-test%EF%BC%89/

正文

什麼是 Spring Cloud?

我先假設讀者都查過微服務是個啥東西了(還不知道的先去查一查吧),那麼話說這個 Spring Cloud 又是個啥東西呢?很多人的第一印象就是(包括我也是):哦就是 Spring 全家桶中關於微服務架構的專案

嗯你要這樣理解也沒錯,不過有些過於籠統了。Spring Cloud 跟 Spring Boot 不一樣,並不是單一個核心專案組成的框架。我們知道想要寫 MVC 風格的 web 伺服器,那就用 spring-boot-starter-web 作為核心依賴,再根據資料庫和採用技術的需要搭上相應的 JDBC 就行了。

然而 Spring Cloud 卻是指眾多依賴的集合,各個依賴分別實現微服務架構所需要的各個核心功能,多個功能共同作用才組成我們所謂的微服務架構

核心模組

既然我們瞭解了 Spring Cloud 其實是一堆依賴的集合,接下來我們就來介紹 Spring Cloud 的核心特性(feature),每個特性可能存在多個依賴都能發揮類似的作用(例如 Hibernate 與 Mybatis 都作為資料庫連結的抽象層依賴使用),首先根據官方解釋可分為一下幾種特性:

FeaturesUsage
Distributed/versioned configuration分散式/版本配置
Service registration and discovery服務註冊&發現
Routing路由
Service-to-service calls服務間呼叫
Load balancing負載均衡
Circuit Breakers斷路器
Global locks全域性鎖
Leadership election and cluster state叢集控制&選拔
Distributed messaging分散式訊息通知

相關的主要專案(main projects)有下列這些:

Spring Cloud ConfigSpring Cloud NetflixSpring Cloud BusSpring Cloud Cloudfoundry
Spring Cloud Open Service BrokerSpring Cloud ClusterSpring Cloud ConsulSpring Cloud Security
Spring Cloud SleuthSpring Cloud Data FlowSpring Cloud StreamSpring Cloud Stream App Starters
Spring Cloud TaskSpring Cloud Task App StartersSpring Cloud ZookeeperSpring Cloud Connectors
Spring Cloud StartersSpring Cloud CLISpring Cloud ContractSpring Cloud Gateway
Spring Cloud OpenFeignSpring Cloud PipelinesSpring Cloud Function

相關社群實在是非常活躍,專案也是一個接一個的冒出來hhh,剛入門的時候真的是眼花繚亂。所以我們稍微重新劃分整理一下,並挑出幾個不敢說一定是最核心但勢必是最具代表性的幾個模組來解說(也是參考連結二的視訊):

(由於排版問題模組順序和位置不具意義,以下列介紹順序為準)

接下來我們就一個個來介紹各個模組的意義和可用專案(可用專案名統一省略 Spring Cloud 字首)吧。

Service Discovery 服務發現

代表專案:Netflix Eureka、Zookeeper、Consul

首先按照微服務的構建程式,我第一個想介紹的服務是 Service Discovery(服務發現)。其實這個服務的完整說法應該參照官方的分類:Service registration and discovery 服務的註冊和查詢

微服務相當於將過於龐大的系統按照服務切分為多個獨立的服務分別開發、部署、應用,也就是我們一直在說的微服務(microservice)。所謂的服務發現就是將眾多的微服務作為獨立的服務客戶端(client),向一個或多個註冊中心(register center)註冊自己所能提供的服務資訊,如下圖所示。

而每次需要查詢系統內其他微服務的時候,只需要從註冊中中心查詢服務註冊資訊就能夠找到對應的服務客戶端了,而不需要記住實際的位置資訊。

甚至我們還能夠透過複製註冊中心來實現服務發現的高可用性(註冊中心死掉之後可以自動推舉出新的註冊中心,避免系統崩潰)

Configuration 服務配置

代表專案:Config

第二個模組是服務配置,當我們建立出多個微服務(microservice)之後,必然需要為每個服務進行相應的配置,可能有些配置需要每個服務一致(公共配置)、也可能是各個服務獨有的配置(私有配置),因此將會差生許多配置檔案如下圖

這時候會差生一個問題,很多時候我們可能只是想根據執行模式、部署模式等原因修改配置,但是由於配置項跟專案原始碼繫結在一起且在啟動時固定引入了。每次進行單純的配置修改就需要整個專案重新打包、整合、部署 blablabla 的,即便整個流程自動化依舊會嚴重影響效率。

Configuration 服務配置便提供這樣一個功能:將服務配置和服務本身分離,統一交由一個配置中心(config center)來管理,至於配置檔案的來源就由配置中心決定,對於服務本身是不可見的,可以是本地 / git 倉庫 / svn / 檔案系統等多種資料來源

Routing & Messaging 路由 & 訊息傳遞

代表專案:Netflix Ribbon、Open Feign(Routing & Load Balancing)、RabbitMQ、Kafka(Messaging)

接著回到第一個模組提到的,我們的微服務中可能會差生服務間呼叫(service-to-service calls)。如果我們就這麼放任它直接簡單的透過 HTTP 請求/響應的話,那就與一般外部使用者的呼叫一樣。這樣不是不行,但是既然屬於內部的服務呼叫,我們就應該對它有進一步的控制。

對於服務間呼叫我們可以使用某種訊息佇列(Message Queue)來進行訊息傳遞,藉此與外部一般請求做區分,也能夠對內部呼叫有更進一步的掌控(如請求排序、優先順序等判斷),這就是 Messaging 訊息傳遞 在做的事

同時我們還可以在此基礎上對這些服務間呼叫實現負載均衡(Load Balancing),將呼叫平均分配給多個例項提高利用率和效能。

API Gateway 服務閘道器

代表專案:Netflix Zuul、Gateway

在安全性方面,本來所有服務寫在同一個 Spring Boot 專案的時候,我們可以使用 Spring Security 來統一管理控制訪問 API 的許可權、跨域、流量控制等問題;當我們將服務切分成微服務時勢必也需要類似的角色來統一處理這些事情(如果我們將閘道器分散到各個服務內部會使得整個服務體系許可權管理混亂不堪,同時極有可能因此多出太多不必要的檢查引發效能問題),這個角色在 Spring Cloud 裡面就是由 API Gateway 服務閘道器來負責(圖中稍微加入前面的幾個服務)

Circuit Breakers 斷路器

代表專案:Netflix Hystrix

下一個比較特別,是關於服務錯誤處理和恢復。上面幾個服務已經能夠組合成基本的微服務架構了,然而我們能注意到服務間呼叫存在一個盲區,當前的內部呼叫沒辦法檢查服務的可用狀態,僅僅只是“呼叫”而已。所以當服務因為某些原因不可用(資料庫錯誤、服務過載、主動停用等),呼叫方並不知道服務已經無效了還是會不斷的呼叫直到超時(timeout)

試想一下如果短時間重複傳送請求或是多層呼叫,那隻需要簡單的幾個請求就足以在超時過程中使伺服器過載或是異常的延遲(一等就是天荒地老,或是因為內部呼叫累加使得所有服務都超時)

這時候我們就能夠藉由 Circuit Breakers 斷路器模式的實現,在一定次數的失敗之後進入(trip)熔斷狀態(breaker open),也就是宣告服務失效,等待服務重啟或是其他方法重置(reset)才能再次提供服務(breaker close)

最後我們給出通用場景下,普通的斷路器模式(circuit breaker)實現狀態轉移圖(上圖中的 trip 操作即為下圖中請求 Fail 執行的狀態轉移)

Tracing 服務追蹤

代表專案:Sleuth、Zipkin

Tracing 服務追蹤的場景在於開發過程以及後期維護時,用於記錄並追蹤服務呼叫路徑日誌,方便程式設計師 debug。在原本的單體 Sprint Boot 應用中,我們可以直接從專案中找的確切的服務呼叫順序(包括 Service 層的互動呼叫);至於在 Spring Cloud 中服務間呼叫(service-to-service calls)主要是依賴於 HTTP 或其他通訊協議的跨伺服器呼叫,我們就需要配置一個統一記錄並追蹤所有內部服務呼叫的類似日誌模組(Logger)的功能(可能是一般日誌形式,甚至能夠表示成圖資料結構並視覺化展示)。

CI Pipeline & Testing 自動化整合 & 測試

代表專案:Pipelines、Contract

前面的各項特性從構建專案、架構、配置、服務可用性到服務追蹤等,在整個軟體開發的生命週期中就只剩下整合、測試到部署等,而這也正是最後一個特性所支援的。在微服務架構下,CI/CD 以及測試所面臨問題與一般單體應用不大相同:

  • 單體應用:在一般單體應用中自動化整合、測試等工具已經足夠成熟,原始碼開發完成後只要東東手指就能一鍵完成整合和部署
  • 微服務架構:在微服務架構中當然你也可以把一個個服務分別構建(build)然後再部署(deploy),這樣一個自動化構建和單元測試的流程就是 Pipeline 流水線提供的功能,如下圖

然而這卻會引發一些問題,例如當我們更新某個服務的版本,即便構建成功也透過單元測試(僅測試微服務內部單元),但是卻依舊有可能與現存的其他微服務不相容(邏輯衝突甚至破壞介面)

這時候你會說那就在最後加上一個整合測試(E2E = End-to-End Test)吧,這樣在整合測試的時候就能夠提前發現服務不相容的問題

然而實際上這樣做的後果就失去了微服務的意義了,因為不管是哪個服務的更新都要重新進行所有服務的整合測試,相當於整個微服務架構只是一個看起來分開的大型應用罷了。

也就是說在微服務架構中的持續交付(CD)重點擺在微服務的獨立交付問題上。既然都切分成了一個個的微服務,我們當然希望能各個模組獨立(劃重點)的整合、測試、交付。也就是說實際上我們的整合測試應該要長成這幅模樣

這邊的重點在於新的整合測試策略是每個服務交付時自己進行一次 E2E 測試(注意版本號,都是與當前最新通過測試的版本來做 E2E)。這時候會遺留一個問題,如果上圖中兩個 E2E 都通過了,還是有可能在部署後產生 v2.0 與 v3.0 的衝突,於是就要輪到契約測試(Contract Test)的登場了

  • 契約測試 Contract Test

由於契約測試的不同實現相差較多,所以這邊略微提一下通用概念就行了。

所謂的契約就是在每次整合時會根據微服務兩兩生成一個通過版本,之後的每一次契約測試都需要對現有“契約”進行測試,並更新契約,圖示如下

有關微服務(分散式)的整合和測試還是一塊非常大的領域,這邊就不展開詳細說明(就不跟專業的獻醜了hhh

結語

終於寫完了hhh,本來想著看看視訊寫寫概念再來開始實踐專案,但是實際上為了寫這一篇就幾乎快把每個服務的用法跟常用的依賴的概念和程式碼都快看了一遍才寫得出來,也側面證明實踐才是幫助理解最快的途徑。

下面幾篇將開始實踐 Spring Cloud 各個模組的服務和不同依賴的使用,敬請期待。

相關文章