原文《微服務架構技術設計方案》WORD格式,主要從微服務架構思維設計、微服務系統架構設計、開發階段等進行建設。
來源網絡,旨在交流學習,如有侵權,聯系速删,更多參考公衆号:優享智庫
微服務的選用
微服務架構從本質上說其實就是分布式架構,與其說是一種新架構,不如說是一種微服務架構風格。
簡單來說,微服務架構風格是要開發一種由多個小服務組成的應用。每個服務運作于獨立的程序,并且采用輕量級互動。多數情況下是一個HTTP的資源API。這些服務具備獨立業務能力并可以通過自動化部署方式獨立部署。這種風格使最小化集中管理,進而可以使用多種不同的程式設計語言和資料存儲技術。
對于微服務架構系統,由于其服務粒度小,子產品化清晰,是以首先要做的是對系統整體進行功能、服務規劃,優先考慮如何在傳遞過程中,從工程實踐出發,組織好代碼結構、配置、測試、部署、運維、監控的整個過程,進而有效展現微服務的獨立性與可部署性。
為了與高速公路建設投資總公司的現有資訊系統架構無縫連接配接,本系統采用微服務技術架構來實作。
架構設計
思維設計
微服務架構設計的根本目的是實作價值傳遞,系統遵循DevOps的開發理念。
實作微服務技術架構,系統在技術上的要求以及相關配套服務的實作,主要包括如下:
一、技術上要求:
1、前後端分離,web前端通過Http/Https協定調用微服務的API網關,由API網關再經過路由服務調用相應的微服務
2、不同微服務之間通過REST方式互相調用
3、微服務之間通過消息中間件實作消息互動機制
二、配套服務與功能實作 :
1、需要進行相應的自動化服務實作,包括自動化建構、自動化安裝部署、自動化測試、自動化平台釋出(Docker實作)
2、管理服務,對于微服務架構,必須配套相應的監控與管理服務、日志管理服務等
3、協作服務,運用DevOps思想提升開發、測試、運維的高效溝通與協作,實作開發與運維的一體化
系統架構設計
架構圖1
1、我們把整個系統根據業務拆分成若幹個子系統或微服務。
2、每個子系統可以部署多個應用,多個應用之間使用負載均衡。
3、需要一個服務注冊中心Eureka,所有的服務都在注冊中心注冊,負載均衡也是通過在注冊中心注冊的服務來使用一定政策來實作。Eureka可部署多個,進行高可用保證。
4、所有的用戶端都通過同一個網關位址通路背景的服務,通過路由配置ZUUL網關來判斷一個URL請求由哪個服務處理。請求轉發到服務上的時候使用負載均衡Ribbon。
5、服務之間采用feign進行調用。
6、使用斷路器hystrix,及時處理服務調用時的逾時和錯誤,防止由于其中一個服務的問題而導緻整體系統的癱瘓。
7、還需要一個監控功能,監控每個服務調用花費的時間等。
8、使用SpringCloud Config進行統一的配置管理,需要考慮與高管局現有的spring Cloud平台的配置管理平台如何配合使用。
9、Hystrix,監控和斷路器。需要在服務接口上添加Hystrix标簽,就可以實作對這個接口的監控和斷路器功能。
10、Hystrix Dashboard,監控面闆,提供了一個界面,可以監控各個服務上的服務調用所消耗的時間等。
11、Turbine,監控聚合,使用Hystrix監控,我們需要打開每一個服務執行個體的監控資訊來檢視。而Turbine可以幫助我們把所有的服務執行個體的監控資訊聚合到一個地方統一檢視。這樣就不需要挨個打開一個個的頁面一個個檢視。
架構的可靠性保證:
在關鍵節點做主備、叢集部署,防止單點故障。
設計階段
總體設計
1、功能規劃:對産品功能進行拆分,拆分為若幹個微服務;一個功能可以建立多個微服務并部署在多個伺服器節點上,以便進行負載均衡。
2、設計原子服務層,梳理和抽取核心應用、公共應用,作為獨立的服務下沉到核心和公共能力層,逐漸形成穩定的服務中心,使應用能更快速的響應多變的客戶需求。
3、為每個服務設計API接口(REST方式)
4、為不同的服務進行分類,不同類型的服務需要的資源不同,可以配置不同的資源,包括CPU、記憶體、存儲等。
服務拆分原則
1、粒度微小:
根據業務功能劃分服務粒度,總的原則是服務内部高内聚,服務之間低耦合。
2、責任單一:
每個服務隻做一件事,即單一職責原則。
3、隔離性原則:
每個服務互相隔離,且不互相影響
4、業務無關優先原則:
基礎服務,是一些基礎元件,與具體的業務無關。比如:短信服務、郵件服務。這裡的服務最容易劃分出來做微服務,也是我們第一優先級分離出來的服務。
服務規劃
為實作負載均衡,允許相同的服務在多個節點注冊相同的服務名,不同的端口。如果沒有前期的規劃,不同的服務提供者可能會注冊相同的服務名,導緻消費者調用服務時産生調用混亂。
是以,需進行服務名的統一規劃:
1、規劃期統一制定每個服務提供者的服務名或者子產品标示。
2、服務名的命名規則:ModuleName_ServiceName,且所有字元小寫,不同單詞之間以下劃線分隔。如使用者管理子產品提供了擷取使用者資訊的服務,則命名為:user_get_info。
3、新增服務名時,需要提出申請,審批通過後方可使用,為減少審批複雜度,可隻審批ModuleName,即在子產品内部可以自由增加服務名,不需要進行審批。
開發政策
總體原則:不同的微服務需進行實體隔離。
1、編譯政策:代碼編譯時,各個微服務獨立編譯、打包,杜絕直接的依賴;
2、工程建構:代碼開發時,各微服務建立獨立的工程,工程之間不能産生直接依賴
3、持續內建:每個微服務獨立執行持續內建。
資料庫設計原則
每個微服務都有自己獨立的資料庫,那麼背景管理的聯合查詢會非常困難。目前通用有四種處理方案。
1)嚴格按照微服務的劃分來做,微服務互相獨立,各微服務資料庫也獨立,背景需要展示資料時,調用各微服務的接口來擷取對應的資料,再進行資料處理後展示出來,這是标準的用法,也是最麻煩的用法。
2) 将業務高度相關的表放到一個庫中,将業務關系不是很緊密的表嚴格按照微服務模式來拆分,這樣既可以使用微服務,也避免了資料庫分散導緻背景系統統計功能難以實作,是一個折中的方案。
3)MySQL+MHA高可用架構 、MySQL分布式Proxy水準擴充架構、 MySQL緩存高并發讀架構、 MySQL小檔案系統大字段存取架構、MySQL Inforbright/Greenplum統計分析架構。
4)資料庫嚴格按照微服務的要求來切分,以滿足業務高并發,實時或者準實時将各微服務資料庫資料同步到NoSQL資料庫中,在同步的過程中進行資料清洗,用來滿足背景業務系統的使用,推薦使用MongoDB、HBase等。
根據系統的實際需求,我們目前采用第二種設計方案。
負載均衡
不再采用一般的增加負載均衡伺服器的方式進行負載均衡,如F5、Nginx、LVS等,而是把負載均衡的功能以庫的方式內建到服務消費方的程序内,這種方案稱為軟負載均衡(Soft Load Balancing)或者用戶端負載均衡。在Spring Cloud中配合Eureka的服務注冊功能,Ribbon子項目則為REST用戶端實作了負載均衡。
使用Ribbon進行負載均衡,其工作原理可以概括為下面四個步驟:
- Ribbon首先根據其所在Zone優先選擇一個負載較少的Eureka Server;
- 定期從Eureka Server更新并過濾服務執行個體清單;
- 根據指定的負載均衡政策,從可用的伺服器清單中選擇一個服務執行個體的位址;
- 然後通過RestClient進行服務調用。
Ribbon本身提供了下面幾種負載均衡政策:
- RoundRobinRule: 輪詢政策,Ribbon以輪詢的方式選擇伺服器,這個是預設值。是以示例中所啟動的兩個服務會被循環通路;
- RandomRule: 随機選擇,也就是說Ribbon會随機從伺服器清單中選擇一個進行通路;
- BestAvailableRule: 最大可用政策,即先過濾出故障伺服器後,選擇一個目前并發請求數最小的;
- WeightedResponseTimeRule: 帶有權重的輪詢政策,對各個伺服器響應時間進行權重處理,然後在采用輪詢的方式來擷取相應的伺服器;
- AvailabilityFilteringRule: 可用過濾政策,先過濾出故障的或并發請求大于門檻值一部分服務執行個體,然後再以線性輪詢的方式從過濾後的執行個體清單中選出一個;
- ZoneAvoidanceRule: 區域感覺政策,先使用主過濾條件(區域負載器,選擇最優區域)對所有執行個體過濾并傳回過濾後的執行個體清單,依次使用次過濾條件清單中的過濾條件對主過濾條件的結果進行過濾,判斷最小過濾數(預設1)和最小過濾百分比(預設0),最後對滿足條件的伺服器則使用RoundRobinRule(輪詢方式)選擇一個伺服器執行個體。
性能政策
1、網絡優化:優化組網結構,提升網絡間通訊性能;
2、配置優化:優化Spring Cloud元件集以及其他元件的配置資訊,使得性能最大化。
開發階段
服務的調用
AIP網關調用
所有服務通過Zuul網關進行調用,不允許直接調用微服務提供者。
Zuul可能會成為系統瓶頸,複雜時可考慮為Zuul進行主備或負載均衡處理。
同步調用
采用HTTP REST方式進行調用,針對業務需求可以進行負載均衡,負載均衡的調用方式有兩種:
1、FeignClient
2、RestTemplate
系統使用FeignClient方式進行服務調用。
不管是什麼方式,都是通過REST接口調用服務的http接口,參數和結果預設都是通過Jackson序列化和反序列化。因為Spring MVC的RestController定義的接口,傳回的資料都是通過Jackson序列化成JSON資料。
異步調用
系統采用RabbitMQ消息中間件來實作。
RabbitMQ 即一個消息隊列,主要是用來實作應用程式的異步和解耦,同時也能起到消息緩沖,消息分發的作用。
服務間調用的權限驗證
系統中的API接口都需要某種授權才能通路,登陸成功以後,然後通過token或者cookie等方式才能調用接口。
系統在登入的時候,把登入請求轉發到相應的使用者服務上,登入成功後,會設定cookie或header token等。然後用戶端接下來的請求就會帶着這些驗證資訊,從Zuul網關傳到相應的服務上進行驗證。
服務的熔斷處理
在服務之間進行調用時,由于各種原因會導緻遠端服務不可用或壓力過載等異常導緻的故障蔓延,此時需要有一種機制進行保護處理。系統通過Netflix的Hystrix元件實作熔斷和降級處了解決此問題。斷路器(Cricuit Breaker)是一種能夠在遠端服務不可用時自動熔斷(打開開關),并在遠端服務恢複時自動恢複(閉合開關)的設施,通過Netflix的Hystrix元件提供斷路器、資源隔離與自我修複功能。
統一日志管理
不同微服務部署在不同節點上,登入每個節點檢視日志是比較麻煩的,同時對于需要關聯多個微服務日志聯合檢視分析的情況将更加麻煩。伴随節點數量的增加,如果沒有合适的管理機制與工具,定位問題、發現問題的複雜性将越來越大,将成指數級增長,是以需要進行統一日志管理。
1、建立統一的日志管理規範;
2、開發并使用統一的日志元件,為所有微服務提供統一的日志服務,由slf4j封裝;
3、在每個服務節點上部署日志采集Agent元件,由此Agent進行日志的采集與轉發;
4、建立統一的日志中心,所有日志寫入日志中心。
統一監控管理
使用Hystrix元件進行服務的監控,使用Nagios進行伺服器等資源的監控。
1、Hystrix,監控和斷路器。我們隻需要在服務接口上添加Hystrix标簽,就可以實作對這個接口的監控和斷路器功能。
2、Hystrix Dashboard,監控面闆,他提供了一個界面,可以監控各個服務上的服務調用所消耗的時間等。
3、Turbine,監控聚合,使用Hystrix監控,我們需要打開每一個服務執行個體的監控資訊來檢視。而Turbine可以幫助我們把所有的服務執行個體的監控資訊聚合到一個地方統一檢視。這樣就不需要挨個打開一個個的頁面一個個檢視。
統一配置管理
實作各微服務的統一參數配置以及版本管理,采用Spring Cloud Config配置中心。
Spring Cloud Config配置中心
Spring Cloud Config就是我們通常意義上的配置中心。Spring Cloud Config-把應用原本放在本地檔案的配置抽取出來放在中心伺服器,本質是配置資訊從本地遷移到雲端。進而能夠提供更好的管理、釋出能力。
Spring Cloud Config分服務端和用戶端,服務端負責将git中存儲的配置檔案釋出成REST接口,用戶端可以從服務端REST接口擷取配置。但用戶端并不能主動感覺到配置的變化,進而主動去擷取新的配置,這需要每個用戶端通過POST方法觸發各自的/refresh。
為解決配置資訊能及時通知到各服務,同時減少每個微服務處理配置資訊更新的複雜度,為此我們通過消息總線來解決此問題,方案如下:
- Git倉庫、Config Server、以及微服務“Service A”、 “Service B”的執行個體中都引入了Spring Cloud Bus,是以他們都連接配接到了RabbitMQ的消息總線上。
- 從Git倉庫中配置的修改到發起/bus/refresh的POST請求這一步可以通過Git倉庫的Web Hook來自動觸發。
- /bus/refresh請求不再發送到具體服務執行個體上,而是發送給Config Server,并通過destination參數來指定需要更新配置的服務或執行個體。
- 由于所有連接配接到消息總線上的應用都會接受到更新請求,是以在Web Hook中就不需要維護所有節點内容來進行更新,進而解決了通過Web Hook來逐個進行重新整理的問題。
分布式緩存
采用Redis作為緩存資料庫,采用三主三從的叢集模式,3個節點分擔通路和計算壓力,每個節點的主備雙機,保證高可用。
REST資源響應結構
rest全稱Representational State Transfer, 是一種實作web service構架方式, 在這種架構下面, 對資源的通路和操作都是通過URI(Uniform Resource Identifiers)來實作的。
rest service具有簡單, 輕量, 快速等特點。主要展現在:
- 對資源的通路通過URI來完成, 用戶端的內建簡單, 我們用浏覽器就可以來對rest service進行通路操作。
- 統一的接口, rest service的操作用的是統一的http請求請求方式: PUT,GET, POST and DELETE。PUT操作用來添加的資源GET操作用來擷取已有的資源POST操作用來對資源進行狀态轉換DELETE用來删除已有的資源
- 靈活的消息解釋格式. rest service的架構讓service的實作獨立于消息格式. 我們對service的通路可以用xml格式, json格式甚至plain text格式, 隻需要在http請求header說明即可。
- 無狀态請求. rest service提供的操作本身是無狀态操作, 無狀态的意思是每個操作自身是一個獨立完整的操作, 架構不保留接下來的操作與之前的操作狀态上的關系
測試
- 單元測試:
由開發人員實作。
采用Mock方式進行測試模拟,由持續內建進行自動化單元測試的執行以及結果輸出。
- 業務測試:
将多個服務或業務單元進行串聯,測試一個完整的業務,甚至是不同業務之間組成的系統測試。
持續內建
1、持續內建:每個微服務獨立執行持續內建。
2、版本內建:由統一的內建工具,将所有微服務內建到統一的版本釋出包中。
3、持續內建可制作多種場景的版本,包括測試環境、開發環境、生産環境。
4、統計測試覆寫率等名額資料。
持續部署
1、通過持續內建自動制作釋出版本的Docker鏡像;
2、将docker鏡像自動上傳到docker容器中。