基于SpringBoot、SpringCloud、Docker的微服務系統架構實踐
由于最近公司業務需要,需要搭建基于Spring Cloud的微服務系統。遍訪各大搜尋引擎,發現國内資料少之又少,也難怪,國内Dubbo正統治着天下。但是,一個技術總有它的瓶頸,Dubbo也有它捉襟見肘的地方。所幸霸主Spring也推出了一整套微服務解決方案,各個子項目也巧妙地解決了分布式系統開發過程中的各種各樣的問題。看了很多國内的資料,最早的幾份文檔也是互相借用,恐怕究竟是什麼都說不清楚了。撸主在github上面發現幾個很好的相關項目,就想翻譯來看看。這篇其實是項目說明,但是裡面很多知識點是百度找不到的,下面就來看看吧,想要部署來看看的可以去下載下傳:
這個項目的名字叫:Piggy Metrics,一個供個人處理财務的解決方案。
簡介
這是一款概念性的應用程式,基于Spring Boot,Spring Cloud和Docker 簡單示範了微服務的架構模式,順便說一句,它還有一個非常漂亮整潔的使用者界面。下面是它的界面示範:

PiggyMetrics被分解為三個核心微服務。這些服務都是圍繞某些業務能力組織的可獨立部署的應用程式。
賬戶服務
包含一般使用者輸入邏輯和驗證:收入/費用項目,儲蓄和帳戶設定。
Method
Path
Description
User authenticated
Available from UI
GET
/accounts/{account}
擷取指定的帳戶資料
/accounts/current
擷取目前帳戶資料
×
/accounts/demo
擷取模拟賬戶資料(預填收入/費用項目等)
PUT
儲存目前帳戶資料
POST
/accounts/
注冊新帳号
統計服務
對主要統計參數執行計算,并為每個帳戶的時間序列。資料點包含基準貨币和時間段的值。此資料用于跟蹤帳戶生命周期中的現金流動動态(尚未在UI中實作的花式圖表)。
/statistics/{account}
擷取指定的帳戶統計資訊
/statistics/current
擷取目前帳戶統計資訊
/statistics/demo
擷取模拟帳戶統計資訊
建立或更新指定帳戶的時間序列資料點
通知服務
存儲使用者聯系資訊和通知設定(如提醒和備份頻率)。計劃從業人員從其他服務收集所需的資訊,并向訂閱的客戶發送電子郵件。
/notifications/settings/current
擷取目前的帳戶通知設定
儲存目前帳戶通知設定
**小結:
每個微服務都有自己的資料庫,是以沒有辦法繞過API和直接通路資料庫。
在這個項目中,使用MongoDB作為每個服務的主資料庫。它是支援多種程式設計語言持久性架構(包括最适合服務需求的資料庫類型)。
Service-to-service的通信是相當簡單的:各個微服務之間的通信隻使用同步的REST API。在現實世界中通常的做法是使用互動風格的組合。例如,執行同步GET請求以檢索資料,并通過消息代理使用異步方法進行建立/更新操作,以便分離服務和緩沖消息,這為我們帶來了一緻性。
在分布式系統中有一些常見的架構,這可以幫助我們了解核心服務的工作原理。Spring Cloud提供了強大的工具來增強基于Spring Boot的應用程式,以此來實作這些架構。
Config service
Spring Cloud Config是用于分布式系統的水準可擴充的集中式配置服務。支援本地存儲、Git和Subversion。
在這個項目中,使用<code>native profile</code>,它從本地類路徑加載配置檔案。可以檢視<code>shared</code>在Config服務資源中的目錄。現在,當通知服務請求其配置時,配置服務以<code>shared/notification-service.yml</code>和<code>shared/application.yml</code>響應(在所有用戶端應用程式之間共享)。
用戶端使用
隻需建構具有<code>spring-cloud-starter-config</code>依賴的Spring Boot應用程式,自動配置将完成其餘所有工作。
現在,不需要在應用程式中使用任何嵌入式屬性。隻需提供<code>bootstrap.yml</code>應用程式名稱和配置服務url:
使用Spring Cloud Config,可以動态地更新配置。
例如,EmailService bean已注釋<code>@RefreshScope</code>。這意味着,可以更改電子郵件文本和主題,而不需要重新部署啟動通知服務。
首先,在Config伺服器中更改所需的屬性。然後,對Notification服務執行重新整理請求:<code>curl -H "Authorization: Bearer #token#" -XPOST http://127.0.0.1:8000/notifications/refresh</code>
此外,也可以使用Repository webhooks自動執行此過程
動态更新有一些限制。<code>@RefreshScope</code>不與<code>@Configuration</code>類一起使用,并且不影響<code>@Scheduled</code>方法
<code>fail-fast</code>屬性意味着Spring Boot如果它無法連接配接到Config
Service就将啟動失敗,這在批量啟動時非常有用。
安全注意事項請往下看
Auth service
授權的責任完全抽取到單獨的伺服器,它為後端資源服務授予OAuth2令牌。Auth伺服器用于使用者授權以及在外圍内的安全的機器對機器通信。
在這個項目中,我使用Password credentials授權類型的使用者授權(因為它隻由本地PiggyMetrics UI使用)和Client Credentials授予微服務權限。
Spring雲安全提供了友善的注釋和自動配置,使得從伺服器端和用戶端端都很容易實作。您可以在文檔中了解更多資訊,并在Auth Server代碼中檢查配置詳細資訊。
從用戶端,一切工作與傳統的基于會話的授權完全相同。您可以Principal從請求中檢索對象,檢查使用者的角色和其他使用基于表達式的通路控制和@PreAuthorize注釋的東西。
PiggyMetrics(帳戶服務,統計服務,通知服務和浏覽器)中的每個用戶端都有一個範圍:server用于後端服務,以及ui- 用于浏覽器。是以,我們還可以保護控制器免受外部通路,例如:
API Gateway
可以看到,有三個核心服務,它們向用戶端公開外部API。在現實世界的系統中,這個數字可以快速增長以及整個系統的複雜性。實際上,上百個服務可能涉及到渲染一個複雜的網頁。
在理論上,用戶端可以直接向每個微伺服器送出請求。但是顯然,這個選項有挑戰和限制,如需要知道所有端點位址,分别執行每個資訊的http請求,在用戶端合并結果。另一個問題是非web友好的協定,可能在後端使用。
通常一個更好的方法是使用API網關。它是進入系統的單個入口點,用于通過将它們路由到适當的後端服務來處理請求,或者通過調用多個後端服務并聚合結果。此外,它可以用于身份驗證,洞察,壓力和金絲雀測試,服務遷移,靜态響應處理,主動流量管理。
Netflix打開了這樣一個邊緣服務,現在使用Spring Cloud,我們可以使用一個@EnableZuulProxy注釋啟用它。在這個項目中,我使用Zuul來存儲靜态内容(ui應用程式),并将請求路由到适當的微服務。這是一個簡單的基于字首的路由配置Notification服務:
這意味着所有開始的請求/notifications都将路由到Notification服務。沒有寫死的位址,你可以看到。Zuul使用服務發現機制來定位通知服務執行個體,以及斷路器和負載平衡器,如下所述。
Service discovery
另一個公知的架構模式是服務發現。它允許自動檢測服務執行個體的網絡位置,由于自動擴充,故障和更新,可能會動态配置設定位址。
服務發現的關鍵部分是系統資料庫。我在這個項目中使用Netflix Eureka。當用戶端負責确定可用服務執行個體(使用系統資料庫伺服器)和負載平衡請求的位置時,Eureka是用戶端發現模式的一個很好的例子。
使用Spring Boot,您可以輕松地使用spring-cloud-starter-eureka-server依賴關系,@EnableEurekaServer注釋和簡單配置屬性來建構Eureka系統資料庫。
支援@EnableDiscoveryClient注釋的用戶端支援bootstrap.yml應用程式名稱:
現在,在應用程式啟動時,它将注冊到Eureka伺服器并提供中繼資料,如主機和端口,運作狀況訓示器URL,首頁等。Eureka從屬于一個服務的每個執行個體接收心跳消息。如果心跳故障切換到可配置的時間表,則執行個體将從系統資料庫中删除。
此外,Eureka提供了一個簡單的界面,您可以跟蹤運作的服務和可用執行個體數: http://localhost:8761
負載均衡器,斷路器和Http用戶端
Netflix OSS提供了另一個偉大的工具集。
Ribbon
Ribbon是一個用戶端負載均衡器,它為您提供了對HTTP和TCP用戶端行為的大量控制。與傳統的負載均衡器相比,每個線上調用不需要額外的跳躍 - 您可以直接聯系所需的服務。
開箱即用,它與Spring Cloud和服務發現本身內建。Eureka Client提供了可用伺服器的動态清單,以便Ribbon可以在它們之間進行平衡。
Hystrix
Hystrix是斷路器模式的實作,它提供了對通過網絡通路的依賴性的延遲和故障的控制。主要思想是在具有大量微服務的分布式環境中停止級聯故障。這有助于快速失敗,并盡快恢複 - 自愈的容錯系統的重要方面。
除了斷路器控制,使用Hystrix,您可以添加一個後備方法,在主指令失敗的情況下調用該方法以擷取預設值。
此外,Hystrix生成每個指令的執行結果和延遲的名額,我們可以用它來監視系統行為。
Feign
Feign是一個聲明式Http用戶端,它與Ribbon和Hystrix無縫內建。實際上,使用一個spring-cloud-starter-feign依賴項和@EnableFeignClients注釋,您擁有一組完整的負載平衡器,斷路器和Http用戶端,并具有合理的即用型預設配置。
以下是帳戶服務的示例:
你需要的隻是一個接口
你可以用@RequestMapping在Spring MVC控制器和Feign方法之間共享部分
上面的示例指定隻需要的服務id -
statistics-service,由于通過Eureka自動發現(但顯然,您可以通路任何資源與特定的網址)
監視儀表闆
在這個項目配置中,Hystrix的每個微服務通過Spring Cloud Bus(使用AMQP代理)将名額推送到Turbine。監控項目隻是一個小的Spring啟動應用程式與渦輪和Hystrix儀表闆。
看下面如何讓它運作。
讓我們看看我們的系統在負載下的行為:帳戶服務調用統計服務,它的響應具有不同的模仿延遲。響應逾時門檻值設定為1秒。
<code>0 ms delay</code>
<code>500 ms delay</code>
<code>800 ms delay</code>
<code>1100 ms delay</code>
表現良好的系統。吞吐量約為22請求/秒。統計服務中的活動線程數較少。中位服務時間約為50 ms。
活動線程的數量在增加。我們可以看到紫色線程池拒絕的數量,是以約30-40%的錯誤,但電路仍然關閉。
半開狀态:故障指令的比率大于50%,斷路器啟動。在睡眠視窗的時間後,下一個請求被允許通過。
100%的請求失敗。電路現在永久打開。在睡眠時間後重試不會再次閉合電路,因為單個請求太慢。
日志分析
當嘗試在分布式環境中識别問題時,集中式日志記錄可能非常有用。Elasticsearch,Logstash和Kibana堆棧使您可以輕松搜尋和分析您的日志,使用率和網絡活動資料。我的其他項目中描述的即開即用 Docker配置。
安全
進階安全配置超出了此概念驗證項目的範圍。對于真實系統的更真實的模拟,考慮使用https,JCE密鑰庫加密微服務密碼和配置伺服器屬性内容(有關詳細資訊,請參閱文檔)。
部署微服務及其互相依賴性,比部署單片應用程式要複雜得多。擁有完全自動化的基礎設施非常重要。我們可以通過持續傳遞方法實作以下優勢:
随時釋放軟體的能力
任何建構可能最終都是釋出
建構工件一次 - 根據需要部署
這裡是一個簡單的連續傳遞工作流,在這個項目中實作:
在此配置中,Travis CI為每個成功的git push建立标記的映像。是以,latest對于Docker Hub上的每個微服務總有圖像,并且用git送出哈希标記的舊圖像。它很容易部署任何一個,并快速復原,如果需要。
如何運作所有的東西?
記住,你要啟動8個Spring Boot應用程式,4個MongoDB執行個體和RabbitMq。確定您4 Gb的計算機上有可用的RAM。您可以始終運作重要的服務,雖然:網關,系統資料庫,配置,Auth服務和帳戶服務。
在你開始之前
- 安裝Docker和Docker Compose。
- 出口環境變量:CONFIG_SERVICE_PASSWORD,NOTIFICATION_SERVICE_PASSWORD,STATISTICS_SERVICE_PASSWORD,ACCOUNT_SERVICE_PASSWORD,MONGODB_PASSWORD
生産模式
在這種模式下,所有最新的圖像将從Docker Hub中提取。隻需複制docker-compose.yml和打docker-compose up -d。
開發模式
如果你想自己建構圖像(例如在代碼中有一些變化),你必須使用maven克隆所有的倉庫和建構工件。然後,運作docker-compose -f docker-compose.yml -f docker-compose.dev.yml up -d
docker-compose.dev.yml繼承docker-compose.yml具有在本地建構映像的額外可能性,并公開所有容器端口以友善開發。
重要端口
小結
所有Spring Boot應用程式都需要運作Config Server進行啟動。但是我們可以同時啟動所有容器,因為fail-fastSpring Boot屬性和docker restart: always-compose選項。這意味着所有依賴的容器将嘗試重新啟動,直到Config Server啟動并運作。
此外,在所有應用程式啟動後,服務發現機制需要一些時間。任何服務都不可用于用戶端發現,直到執行個體,Eureka伺服器和用戶端都在其本地緩存中具有相同的中繼資料,是以可能需要3個心跳。預設心跳周期為30秒。