0
  • 聊天消息
  • 系統(tǒng)消息
  • 評論與回復
登錄后你可以
  • 下載海量資料
  • 學習在線課程
  • 觀看技術視頻
  • 寫文章/發(fā)帖/加入社區(qū)
會員中心
創(chuàng)作中心

完善資料讓更多小伙伴認識你,還能領取20積分哦,立即完善>

3天內(nèi)不再提示

微服務可靠性設計

lhl545545 ? 來源:電子發(fā)燒友網(wǎng) ? 2018-02-09 09:21 ? 次閱讀

1. 背景

微服務化之后,系統(tǒng)分布式部署,傳統(tǒng)單個流程的本地API調(diào)用被拆分成多個微服務之間的跨網(wǎng)絡調(diào)用,由于引入了網(wǎng)絡通信、序列化和反序列化等操作,系統(tǒng)發(fā)生故障的概率提高了很多。微服務故障,有些是由于業(yè)務自身設計或者編碼不當導致,有些是底層的微服務化框架容錯能力不足導致。在實際項目中,需要從業(yè)務和平臺兩方面入手,提升微服務的可靠性。

1.1. 無處不在的故障

1.1.1. 分布式部署和調(diào)用傳統(tǒng)單體架構一個完整的業(yè)務流程往往在同一個進程內(nèi)部完成處理,不需要進行分布式協(xié)作,它的工作原理如下所示:

微服務可靠性設計

圖1-1 傳統(tǒng)單體架構本地方法調(diào)用

微服務化之后,不同的微服務采用分布式集群部署方式,服務的消費者和提供者通常運行在不同的進程中,需要跨網(wǎng)絡做RPC調(diào)用,它的工作原理如下所示:

微服務可靠性設計

圖1-2 微服務分布式RPC調(diào)用

分布式調(diào)用之后,相比于傳統(tǒng)單體架構的本地方法調(diào)用,主要引入了如下潛在故障點:

序列化與反序列化:微服務的請求和應答都需要經(jīng)過序列化和反序列化,做消息的跨網(wǎng)絡通信,由于數(shù)據(jù)結構不一致、不支持的數(shù)據(jù)類型、對方編解碼錯誤等都會導致序列化和反序列化失敗,進而導致微服務調(diào)用失敗。

網(wǎng)絡問題:常見的包括網(wǎng)絡超時、網(wǎng)絡閃斷、網(wǎng)絡單通、網(wǎng)絡擁塞等,都可能會導致微服務遠程調(diào)用的失敗。

1.1.2. 大型系統(tǒng)微服務進程內(nèi)合設

理想情況下,每個微服務都獨立打包和部署,微服務之間天然就支持進程級隔離,但事實上,對于一個大規(guī)模的企業(yè)IT系統(tǒng)、或者大型網(wǎng)站,是由成百上千個微服務組成的,在實踐中,微服務通常是不可能做到百分之百獨立部署的,原因如下:

1、方便開發(fā):通常會按照業(yè)務域劃分團隊,同一個業(yè)務域往往包含多個微服務,由一個團隊負責開發(fā)。為了方便CI/CD,同一業(yè)務域的微服務往往打包和部署在一起,而不是每個微服務獨立打包部署。

2、方便運維:海量的微服務進程(以1000個微服務 * 10個進程實例為例),會增加部署、數(shù)據(jù)采集(性能KPI和日志等)、告警、問題定位等成本,如果運維自動化程度不高,很難支撐大規(guī)模的微服務獨立部署。

3、提升性能:一些業(yè)務對時延非常敏感,如果該業(yè)務鏈上的所有微服務調(diào)用都跨網(wǎng)絡通信,時延往往無法滿足業(yè)務要求。通過將微服務合設在同一個進程之內(nèi),利用路由短路,把RPC調(diào)用轉(zhuǎn)化成本地方法調(diào)用,可以極大的提升性能。

4、簡化分布式事務處理:分布式部署之后,會帶來分布式事務問題。有時候業(yè)務為了簡化分布式事務的處理,將事務相關的微服務部署在同一個進程中,把分布式事務轉(zhuǎn)換成本地事務,簡化事務處理。

不同的微服務合設在同一個進程之中,就會引入一系列潛在的故障點,例如:處理較慢的微服務會阻塞其它微服務

某個微服務故障蔓延,可能導致整個進程不可用

低優(yōu)先級的微服務,搶占高優(yōu)先級微服務的資源

1.1.3. 微服務健康度

傳統(tǒng)情況下,往往使用服務注冊中心檢測微服務的狀態(tài),當檢測到服務提供者不可用時,會將故障的服務信息廣播到集群所有節(jié)點,消費者接收到服務故障通知消息之后,根據(jù)故障信息中的服務名稱、IP地址等信息,對故障節(jié)點進行隔離。它的工作原理如下所示:

微服務可靠性設計

圖1-3 微服務狀態(tài)檢測

使用基于心跳或者會話的微服務狀態(tài)檢測,可以發(fā)現(xiàn)微服務所在進程宕機、網(wǎng)絡故障等問題,但在實際業(yè)務中,微服務并非“非死即活”,它可能處于“亞健康狀態(tài)”,服務調(diào)用

失敗率很高,但又不是全部失敗?;蛘呶⒎找呀?jīng)處于過負荷流控狀態(tài),業(yè)務質(zhì)量受損,但是又沒有全部中斷。使用簡單的微服務狀態(tài)檢測,很難應對上述這些場景。通過對微服務的運行質(zhì)量建模,利用微服務健康度模型,根據(jù)采集的各種指標對微服務健康度實時打分,依據(jù)打分結果采取相應的可靠性對策,可以更有針對性的保障系統(tǒng)的可靠性。

1.1.4. 同步的I/O操作

在整個微服務調(diào)用過程中,主要會涉及到三類I/O操作:

網(wǎng)絡I/O操作,涉及到網(wǎng)絡讀寫

磁盤I/O操作,主要是記錄日志、話單、寫本地文件等

數(shù)據(jù)庫訪問,例如Java使用JDBC驅(qū)動進行數(shù)據(jù)庫操作

微服務可靠性設計

圖1-4 微服務涉及的主要I/O操作

凡是涉及到I/O操作的,如果I/O操作是同步阻塞模式,例如Java的BIO、文件File的讀寫操作、數(shù)據(jù)庫訪問的JDBC接口等,都是同步阻塞的。只要訪問的網(wǎng)絡、磁盤或者數(shù)據(jù)庫實例比較慢,都會導致調(diào)用方線程的阻塞。由于線程是Java虛擬機比較重要的資源,當大量微服務調(diào)用線程被阻塞之后,系統(tǒng)的吞吐量將嚴重下降。

1.1.5. 第三方SDK API調(diào)用

在微服務中,調(diào)用第三方SDK API,也可能會引入新的故障點,例如通過FTP客戶端訪問遠端的FTP服務,或者使用MQ客戶端訪問MQ服務,如果這些客戶端API的容錯性設計不好,也會導致調(diào)用方的級聯(lián)故障,這些故障是潛在和隱性的,在設計的時候往往容易被忽視,但它帶來的風險和危害是巨大的。

1.2. 微服務可靠性

軟件可靠性是指在給定時間內(nèi),特定環(huán)境下軟件無錯運行的概率。軟件可靠性包含了以下三個要素:

1) 規(guī)定的時間:軟件可靠性只是體現(xiàn)在其運行階段,所以將運行時間作為規(guī)定的時間的度量。運行時間包括軟件系統(tǒng)運行后工作與掛起(啟動但空閑)的累計時間。由于軟件運行的環(huán)境與程序路徑選取的隨機性,軟件的失效為隨機事件,所以運行時間屬于隨機變量。

2) 規(guī)定的環(huán)境條件:環(huán)境條件指軟件的運行環(huán)境。它涉及軟件系統(tǒng)運行時所需的各種支持要素,如支持硬件、操作系統(tǒng)、其它支持軟件、輸入數(shù)據(jù)格式和范圍以及操作規(guī)程等。

3) 規(guī)定的功能:軟件可靠性還與規(guī)定的任務和功能有關。由于要完成的任務不同,則調(diào)用的子模塊就不同(即程序路徑選擇不同),其可靠性也就可能不同。所以要準確度量軟件系統(tǒng)的可靠性必須首先明確它的任務和功能。

1.2.1. 關鍵的可靠性因素微服務的運行質(zhì)量,除了自身的可靠性因素之外,還受到其它因素的影響,包括網(wǎng)絡、數(shù)據(jù)庫訪問、其它相關聯(lián)的微服務運行質(zhì)量等。微服務的可靠性設計,需要考慮上述綜合因素,總結如下:

微服務可靠性設計

圖1-5 微服務可靠性設計模型

2. 異步I/O操作

2.1. 網(wǎng)絡I/O

2.1.1. 使用同步阻塞I/O的問題以Java為例,在JDK 1.4推出JAVA NIO1.0之前,基于JAVA的所有Socket通信都采用了同步阻塞模式(BIO),這種一請求一應答的通信模型簡化了上層的應用開發(fā),但是在可靠性和性能方面存在巨大的弊端:

微服務可靠性設計

2-1 傳統(tǒng)Java 同步阻塞I/O模型

采用BIO通信模型的服務端,通常由一個獨立的Acceptor線程負責監(jiān)聽客戶端的連接,接收到客戶端連接之后為客戶端連接創(chuàng)建一個新的線程處理請求消息,處理完成之后,返回應答消息給客戶端,線程銷毀,這就是典型的一請求一應答模型。該架構最大的問題就是不具備彈性伸縮能力,當并發(fā)訪問量增加后,服務端的線程個數(shù)和并發(fā)訪問數(shù)成線性正比,由于線程是JAVA虛擬機非常寶貴的系統(tǒng)資源,當線程數(shù)膨脹之后,系統(tǒng)的性能急劇下降,隨著并發(fā)量的繼續(xù)增加,可能會發(fā)生句柄溢出、線程堆棧溢出等問題,并導致服務器最終宕機。

2.1.2.

使用非阻塞I/O通信微服務進行遠程通信時,通過使用非阻塞I/O,可以解決由于網(wǎng)絡時延大、高并發(fā)接入等導致的服務端線程數(shù)膨脹或者線程被阻塞等問題。

以Java為例,從JDK1.4開始,JDK提供了一套專門的類庫支持非阻塞I/O,可以在java.nio包及其子包中找到相關的類和接口。JDK1.7之后,又提供了NIO2.0類庫,支持異步I/O操作。

利用JDK的異步非阻塞I/O,可以實現(xiàn)一個I/O線程同時處理多個客戶端鏈路,讀寫操作不會因為網(wǎng)絡原因被阻塞,I/O線程可以高效的并發(fā)處理多個客戶端鏈路,實現(xiàn)I/O多路復用,它的工作原理如下所示:

微服務可靠性設計

2-2 Java非阻塞I/O模型

使用非阻塞I/O進行通信,以Java語言為例,建議策略如下:

1) TCP私有協(xié)議:建議直接基于Netty開發(fā)。

2) HTTP/Restful/SOAP等:選擇支持非阻塞I/O的Web框架。也可以選擇基于Netty構建的開源應用層協(xié)議??蚣埽缰С之惒絉estful的RestExpress。

2.2. 磁盤I/O

微服務對磁盤I/O的操作分為兩類:

直接文件操作:例如調(diào)用File的open、write、read等接口,進行文件操作。

間接文件操作:例如調(diào)用日志類庫寫日志,雖然微服務并沒有直接操作日志文件,但是日志類庫底層還是會進行文件的讀寫等操作。

在實際項目中,最容易被忽視的就是日志操作。不同的日志類庫,寫日志的機制不同,以Log4j 1.2.X版本為例,當日志隊列滿之后,有多種策略:同步等待,直到新的日志消息能夠入隊列,它會阻塞當前業(yè)務線程。

丟棄當前的日志消息,不會阻塞當前業(yè)務線程。

不入隊列,由當前調(diào)用寫日志的業(yè)務線程執(zhí)行日志I/O操作,如果此時磁盤I/O寫入速度慢,則會阻塞當前業(yè)務線程。

2-3 JDK1.7

在實際生產(chǎn)環(huán)境中,我們就遇到過類似問題,在某些時段,磁盤WIO達到10+持續(xù)幾秒鐘-10幾秒鐘,然后又恢復正常。WIO較高的時段,需要寫接口日志、話單等,由于系統(tǒng)默認采用的是同步等待策略,結果導致通信I/O線程、微服務調(diào)度線程等都被阻塞,最終鏈路因為心跳超時被強制關閉、微服務被大量阻塞在消息隊列中導致內(nèi)存居高不小、響應超時等。

由于偶現(xiàn)的WIO高導致同步寫日志被阻塞,繼而引起通信線程、微服務調(diào)用線程級聯(lián)故障,定位起來非常困難,平時Code Review也很難被注意到。所以,隱性的磁盤I/O操作,更需要格外關注。

要解決上面的問題,有三種策略:使用非阻塞I/O,對文件進行異步讀寫操作。

業(yè)務層面封裝一個異步的I/O操作,最簡單的策略就是由一個獨立的線程或者線程池來執(zhí)行磁盤I/O操作。

選擇支持非阻塞方式調(diào)用的I/O類庫,例如使用log4j的異步日志API。

以JDK1.7為例,它提供了異步的文件I/O操作類庫,基于該類庫,就不需要擔心磁盤I/O操作被阻塞:

微服務可靠性設計

異步非阻塞文件接口

自己在上層封裝異步I/O操作,也比較簡單,它的優(yōu)點是可以實現(xiàn)磁盤I/O操作與微服務之間的線程隔離,但是底層仍然使用的是同步阻塞I/O,如果此時磁盤的I/O比較高,依然會阻塞寫磁盤的I/O線程。它的原理如下所示:

微服務可靠性設計

2-4 應用層封裝的異步文件操作將文件I/O操作封裝成一個Task或者Event,投遞到文件I/O線程池的消息隊列中,根據(jù)投遞結果,構造I/O操作相關聯(lián)的Future對象給微服務調(diào)用線程。通過向Future對象注冊Listener并實現(xiàn)callback接口,可以實現(xiàn)異步回調(diào)通知,這樣微服務和文件I/O操作就實現(xiàn)了線程隔離。文件I/O操作耗時,并不會阻塞微服務調(diào)度線程。當使用第三方文件I/O操作類庫時,需要注意下相關API,盡量使用支持異步非阻塞接口的API,如果沒有,則需要考慮是否做上層的異步封裝。

2.3. 數(shù)據(jù)庫操作

部分數(shù)據(jù)庫訪問支持非阻塞方式,例如Oracle的OCI,它支持non-blocking模式和blocking模式:阻塞方式就是當調(diào)用 OCI操作時,必須等到此OCI操作完成后服務器才返回客戶端相應的信息,不管是成功還是失敗。非阻塞方式是當客戶端提交OCI操作給服務器后,服務器立即返回OCI_STILL_EXECUTING信息,而并不等待服務端的操作完成。對于non-blocking方式,應用程序若收到一個OCI函數(shù)的返回值為OCI_STILL_EXECUTING時必須再次對每一個OCI函數(shù)的返回值進行判斷,判斷其成功與否。 可通過設置服務器屬性為OCI_ATTR_NONBLOCKING_MODE來實現(xiàn)。

對于Java語言而言,由于JDK本身提供了數(shù)據(jù)庫連接驅(qū)動相關的接口定義,JDBC驅(qū)動本身就是同步API接口,因此,Java語言的開源ORM框架也都是同步阻塞的,例如MyBatis、Hibernate等。盡管大部分數(shù)據(jù)庫訪問接口是同步阻塞的,但是由于數(shù)據(jù)庫中間件的超時控制機制都比較成熟,因此通過合理設置超時時間,可以避免微服務的數(shù)據(jù)庫訪問被長時間掛住。

也可以在應用上層封裝異步數(shù)據(jù)庫操作層,實現(xiàn)微服務調(diào)度與數(shù)據(jù)庫操作的線程級隔離,原理2.2章節(jié)已經(jīng)介紹過,采用該方式同樣存在兩點不足:

排隊現(xiàn)象:如果某個數(shù)據(jù)庫操作非常耗時,超時時間配置的又比較大(例如30S),會導致后續(xù)的數(shù)據(jù)庫操作在隊列中排隊。

無法充分發(fā)揮數(shù)據(jù)庫效能:由于底層數(shù)據(jù)庫訪問采用同步阻塞的方式,所以不能高效發(fā)揮數(shù)據(jù)庫的效能。

3. 故障隔離由于大部分微服務采用同步接口調(diào)用,而且多個領域相關的微服務會部署在同一個進程中,很容易發(fā)生“雪崩效應”,即某個微服務提供者故障,導致調(diào)用該微服務的消費者、或者與故障微服務合設在同一個進程中的其它微服務發(fā)生級聯(lián)故障,最終導致系統(tǒng)崩潰。

為了避免“雪崩效應”的發(fā)生,需要支持多種維度的依賴和故障隔離,以實現(xiàn)微服務的HA。

3.1. 通信鏈路隔離由于網(wǎng)絡通信本身通常不是系統(tǒng)的瓶頸,因此大部分服務框架會采用多線程+單個通信鏈路的方式進行通信,原理如下所示:圖10

3-1 多線程-單鏈路P2P通信模式

正如前面章節(jié)所述,由于微服務使用異步非阻塞通信,單個I/O線程可以同時并發(fā)處理多個鏈路的消息,而且網(wǎng)絡讀寫都是非阻塞的,因此采用多線程+單鏈路的方式進行通信性能本身問題不大。但是從可靠性角度來看,只支持單鏈路本身又存在一些可靠性隱患,我們從下面的案例中看下問題所在。

某互聯(lián)網(wǎng)基地微服務架構上線之后,發(fā)現(xiàn)在一些時段,經(jīng)常有業(yè)務超時,超時的業(yè)務沒有固定規(guī)律。經(jīng)定位發(fā)現(xiàn)當有較多的批量內(nèi)容同步、語音和視頻類微服務調(diào)用時,系統(tǒng)的整體時延就增高了很多,而且存在較突出的時延毛刺。由于這些操作獲取的消息碼流往往達到數(shù)M到數(shù)十兆,微服務之間又采用單鏈路的方式進行P2P通信,導致大碼流的傳輸影響了其它消息的讀寫效率,增大了微服務的響應時延。

問題定位出來之后,對微服務之間的通信機制做了優(yōu)化,節(jié)點之間支持配置多鏈路,每個鏈路之間還可以實現(xiàn)不同策略的隔離,例如根據(jù)消息碼流大小、根據(jù)微服務的優(yōu)先級等策略,實現(xiàn)鏈路級的隔離,優(yōu)化之后的微服務通信機制:

微服務可靠性設計

圖3-2 支持多鏈路隔離

3.2. 調(diào)度資源隔離

3.2.1. 微服務之間隔離當多個微服務合設運行在同一個進程內(nèi)部時,可以利用線程實現(xiàn)不同微服務之間的隔離。對于核心微服務,發(fā)布的時候可以獨占一個線程/線程池,對于非核心微服務,則可以共享同一個大的線程池,在實現(xiàn)微服務隔離的同時,避免線程過于膨脹:

微服務可靠性設計

圖3-3 微服務之間故障隔離假如非核心服務3發(fā)生故障,長時間阻塞線程池1的工作線程,其它與其共用線程池消息隊列的非核心服務1和服務2只能在隊列中排隊等待,當服務3釋放線程之后,排隊的服務1和服務2可能已經(jīng)超時,只能被丟棄掉,導致業(yè)務處理失敗。采用線程池隔離的核心服務1和服務2,由于各自獨占線程池,擁有獨立的消息隊列,它的執(zhí)行不受發(fā)生故障的非核心服務1影響,因此可以繼續(xù)正常工作。通過獨立線程池部署核心服務,可以防止故障擴散,保障核心服務的正常運行。

3.2.2. 第三方依賴隔離

在微服務中通常會調(diào)用第三方中間件服務,例如分布式緩存服務、分布式消息隊列、NoSQL服務等。只要調(diào)用第三方服務,就會涉及跨網(wǎng)絡操作,由于客戶端SDK API的封裝,很多故障都是隱性的,因此,它的可靠性需要額外關注。

整體而言,第三方依賴隔離可以采用線程池 + 響應式編程(例如RxJava)的方式實現(xiàn),它的原理如下所示:

1) 對第三方依賴進行分類,每種依賴對應一個獨立的線程/線程池。

2) 微服務不直接調(diào)用第三方依賴的API,而是使用異步封裝之后的API接口。

3) 異步調(diào)用第三方依賴API之后,獲取Future對象。利用響應式編程框架,可以訂閱后續(xù)的事件,接收響應,針對響應進行編程。利用Netflix開源的hystrix + RxJava,可以快速實現(xiàn)第三方依賴的隔離,后續(xù)章節(jié)我們會詳細介紹下如何使用。

3.3. 進程級隔離

對于核心的微服務,例如商品購買、用戶注冊、計費等,可以采用獨立部署的方式,實現(xiàn)高可用性。

3.3.1. 容器隔離微服務鼓勵軟件開發(fā)者將整個軟件解耦為功能單一的服務,并且這些服務能夠獨立部署、升級和擴容。如果微服務抽象的足夠好,那么微服務的這一優(yōu)點將能夠提升應用的敏捷性和自治理能力。利用Docker容器部署微服務,可以帶來如下幾個優(yōu)點:

高效:Docker容器的啟動和停止不需要幾分鐘,只要幾百毫秒就足夠了。使用Docker部署微服務,微服務的啟動和銷毀速度非???,在高壓力時,可以實現(xiàn)秒級彈性伸縮。

高性能:Docker容器的性能接近裸的物理機,比VM平均高20%+。

隔離性:利用Docker,可以實現(xiàn)0.1 core的隔離?;诩毩6鹊馁Y源隔離機制,可以實現(xiàn)高密度的部署微服務,同時實現(xiàn)它們之間的資源層隔離,保障微服務的可靠性。

可移植性:在基于虛擬機的解決方案中,應用的可移植性通常來說會受到云提供商所提供的虛擬機格式限制。如果應用程序需要部署到不同類型的虛擬機中,需要針對特定的虛擬機格式做鏡像文件,新增很多額外的開發(fā)和測試工作量。Docker容器的設計理念是“一次編寫,到處運行”,這可以使開發(fā)者避免上面這種限制。

基于Docker容器部署微服務,實現(xiàn)物理資源層隔離示意圖如下所示:圖13

圖3-4 基于Docker容器的微服務隔離3.3.2. VM隔離除了Docker容器隔離,也可以使用VM對微服務進行故障隔離,相比于Docker容器,使用VM進行微服務隔離存在如下優(yōu)勢:微服務的資源隔離性更好,CPU、內(nèi)存、網(wǎng)絡等可以實現(xiàn)完全的資源隔離。

對于已經(jīng)完成硬件虛擬化的遺留系統(tǒng),可以直接使用已有的VM,而不需要在VM中重新部署Docker容器。

4. 集群容錯當微服務不可用時,需要根據(jù)預置的策略做容錯處理,大部分的容錯能力和策略是公共的,因此可以下沉到服務框架中實現(xiàn)。4.1. 路由容錯當集群環(huán)境中微服務調(diào)用失敗之后,利用路由容錯機制,可以在底層實現(xiàn)微服務的自動容錯處理,提升系統(tǒng)的可靠性。常用的容錯策略包括:失敗自動切換機制:微服務調(diào)用失敗自動切換策略指的是當發(fā)生服務調(diào)用異常時,重新選路,查找下一個可用的微服務提供者。微服務發(fā)布的時候,可以指定服務的集群容錯策略。消費者可以覆蓋服務提供者的通用配置,實現(xiàn)個性化的容錯策略。

失敗回調(diào)機制:微服務調(diào)用失敗之后,提供異?;卣{(diào)接口,執(zhí)行微服務消費者自定義的失敗處理邏輯。

快速失敗機制:在業(yè)務高峰期,對于一些非核心的服務,希望只調(diào)用一次,失敗也不再重試,為重要的核心服務節(jié)約寶貴的運行資源。此時,快速失敗是個不錯的選擇。快速失敗策略的設計比較簡單,獲取到服務調(diào)用異常之后,直接忽略異常,記錄異常日志。

4.2. 服務降級

大促或者業(yè)務高峰時,為了保證核心服務的SLA,往往需要停掉一些不太重要的業(yè)務,例如商品評論、論壇或者粉絲積分等。另外一種場景就是某些服務因為某種原因不可用,但是流程不能直接失敗,需要本地Mock服務端實現(xiàn),做流程放通。以圖書閱讀為例,如果用戶登錄余額鑒權服務不能正常工作,需要做業(yè)務放通,記錄消費話單,允許用戶繼續(xù)閱讀,而不是返回失敗。通過服務治理的服務降級功能,即可以滿足上述兩種場景的需求。

4.2.1. 強制降級

當外界的觸發(fā)條件達到某個臨界值時,由運維人員/開發(fā)人員決策,對某類或者某個服務進行強制降級。強制降級的常用策略:不發(fā)起遠程服務調(diào)用,直接返回空。例如mock = force: return null。

不發(fā)起遠程服務調(diào)用,直接拋出指定異常。例如mock = force: throw Exception。

不發(fā)起遠程服務調(diào)用,直接執(zhí)行本地模擬接口實現(xiàn)類。mock = force: execute Bean: 《Spring beanName》。

4.2.2. 容錯降級

當非核心服務不可用時,可以對故障服務做業(yè)務邏輯放通,以保障核心服務的運行。容錯降級與屏蔽降級的主要差異是:觸發(fā)條件不同:容錯講解是根據(jù)服務調(diào)用結果,自動匹配觸發(fā)的;而屏蔽降級往往是通過人工根據(jù)系統(tǒng)運行情況手工操作觸發(fā)的。

作用不同:容錯降級是當服務提供者不可用時,讓消費者執(zhí)行業(yè)務放通;屏蔽降級的主要目的是將原屬于降級業(yè)務的資源調(diào)配出來供核心業(yè)務使用。

調(diào)用機制不同:一個發(fā)起遠程服務調(diào)用,一個只做本地調(diào)用。

容錯降級的常用策略如下:異常轉(zhuǎn)義:mock = fail: throw Exception。

自定義降級邏輯:mock = fail: execute Bean: 《beanName》。將異常屏蔽掉,直接執(zhí)行本地模擬接口實現(xiàn)類,返回Mock接口的執(zhí)行結果。

4.2.3. 服務降級Portal

利用服務治理Portal,可以在線的動態(tài)修改微服務的降級策略,實時生效,它的界面如下所示:

微服務可靠性設計

圖4-1 服務降級配置界面

4.3. 熔斷機制熔斷機制(Circuit Breaker),也叫自動停盤機制,是指當股指波幅達到規(guī)定的熔斷點時,交易所為控制風險采取的暫停交易措施。在微服務領域,熔斷機制是從消費端保護微服務提供者的措施,當微服務的運行質(zhì)量低于某個臨界值時,啟動熔斷機制,暫停微服務調(diào)用一段時間,以保障后端的微服務不會因為持續(xù)過負荷而宕機。

4.3.1. 工作原理

微服務的熔斷機制原理如下所示:

微服務調(diào)用時,對熔斷開關狀態(tài)進行判斷,當熔斷器開關關閉時, 請求被允許通過熔斷器。如果當前微服務健康度高于指定閾值, 開關繼續(xù)保持關閉。否則開關切換為打開狀態(tài)。

當熔斷器開關打開時,微服務調(diào)用請求被禁止通過。調(diào)用失敗,執(zhí)行本地降級邏輯,如果沒有實現(xiàn)降級邏輯,默認返回異常。

當熔斷器開關處于打開狀態(tài)時, 經(jīng)過指定周期T, 熔斷器會自動進入半開狀態(tài), 這時熔斷器會允許請求通過,當請求調(diào)用成功時, 熔斷器恢復到關閉狀態(tài)。若失敗, 則繼續(xù)保持打開狀態(tài)。

它的工作原理示意如下:

微服務可靠性設計

圖4-2 微服務熔斷器工作原理

熔斷器機制能保證微服務消費者在微服務運行狀態(tài)不佳時,快速返回結果,避免大量的同步等待。并且能在指定周期T后繼續(xù)偵測微服務是否可用, 以實現(xiàn)故障恢復之后的自動感知。

4.3.2. 微服務健康度

熔斷器開關的狀態(tài)取決于微服務的運行質(zhì)量,微服務的運行質(zhì)量通常由多種因素決定,具有多個衡量因子。通過對微服務健康度建模,可以實現(xiàn)對微服務運行質(zhì)量的360°實時評估。微服務健康度模型如下所示:

微服務可靠性設計

圖4-3 微服務健康度模型微服務運維體系通過分布式日志采集系統(tǒng)、告警系統(tǒng)、性能KPI數(shù)據(jù)采集等,利用在線大數(shù)據(jù)實時分析技術,通過健康度模型,對微服務的健康度按照周期進行實時打分,同時將微服務的得分通過消息隊列訂閱發(fā)布出去,各個節(jié)點訂閱微服務的健康度得分,與熔斷器閾值進行比較,修改熔斷器開關的狀態(tài)。5. 流量控制

當資源成為瓶頸時,服務框架需要對消費者做限流,啟動流控保護機制。流量控制有多種策略,比較常用的有:針對訪問速率的靜態(tài)流控、針對資源占用的動態(tài)流控等。

在實踐中,各種流量控制策略需要綜合使用才能起到較好的效果。

5.1. 動態(tài)流控

動態(tài)流控的最終目標是為了保命,并不是對流量或者訪問速度做精確控制。當系統(tǒng)負載壓力非常大時,系統(tǒng)進入過負載狀態(tài),可能是CPU、內(nèi)存資源已經(jīng)過載,也可能是應用進程內(nèi)部的資源幾乎耗盡,如果繼續(xù)全量處理業(yè)務,可能會導致消息嚴重積壓或者應用進程宕機。

動態(tài)流控檢測的資源包括:

CPU使用率。

內(nèi)存使用率(對于Java,主要是JVM內(nèi)存使用率)。

隊列積壓率。

主機CPU、內(nèi)存使用率采集算法非常多,例如使用java.lang.Process執(zhí)行top、sar等外部命令獲取系統(tǒng)資源使用情況,然后解析后計算獲得資源使用率。也可以直接讀取操作系統(tǒng)的系統(tǒng)文件獲取相關數(shù)據(jù),需要注意的是,無論是執(zhí)行操作系統(tǒng)的本地命令,還是直接讀取操作系統(tǒng)的資源使用率文件,都是操作系統(tǒng)本地相關的,不同的操作系統(tǒng)和服務器,命令和輸出格式可能存在很大差異。在計算時需要首先判斷操作系統(tǒng)類型,然后調(diào)用相關操作系統(tǒng)的資源采集接口實現(xiàn)類,通過這種方式就可以支持跨平臺。

動態(tài)流控是分級別的,不同級別拒掉的消息比例不同,這取決于資源的負載使用情況。例如當發(fā)生一級流控時,拒絕掉1/4的消息;發(fā)生二級流控時,拒絕掉1/2消息;發(fā)生三級流控時,所有的消息都被流控掉。

不同的級別有不同的流控閾值,系統(tǒng)上線后會提供默認的;流控閾值,不同流控因子的流控閾值不同,業(yè)務上線之后通常會根據(jù)現(xiàn)場的實際情況做閾值調(diào)優(yōu),因此流控閾值需要支持在線修改和動態(tài)生效。需要指出的是為了防止系統(tǒng)波動導致的偶發(fā)性流控,無論是進入流控狀態(tài)還是從流控狀態(tài)恢復,都需要連續(xù)采集N次并計算平均值,如果連續(xù)N次平均值大于流控閾值,則進入流控狀態(tài);同理,只有連續(xù)N次資源使用率平均值低于流控閾值,才能脫離流控恢復正常。

5.2. 靜態(tài)流控

靜態(tài)流控主要針對客戶端訪問速率進行控制,它通常根據(jù)服務質(zhì)量等級協(xié)定(SLA)中約定的QPS做全局流量控制,例如計費服務的靜態(tài)流控閾值為200 QPS,則無論集群有多少個計費服務實例,它們總的處理速率之和不能超過200 QPS。由于微服務具備彈性伸縮、動態(tài)上線和下線等特性,因此集群中某個微服務實例的節(jié)點個數(shù)是動態(tài)變化的,采用傳統(tǒng)的平均分配制無法做到精準的控制。在實踐中,比較成熟的集群靜態(tài)流控策略是動態(tài)配額申請制,它的工作原理如下:系統(tǒng)部署的時候,根據(jù)微服務節(jié)點數(shù)和靜態(tài)流控QPS閾值,拿出一定比例的配額做初始分配,剩余的配額放在配額資源池中。

哪個微服務節(jié)點使用完了配額,就主動向服務注冊中心申請配額。配額的申請策略:如果流控周期為T,則將周期T分成更小的周期T/N(N為經(jīng)驗值,默認值為10),當前的服務節(jié)點數(shù)為M個,則申請的配額為 (總QPS配額 - 已經(jīng)分配的QPS配額)/M * T/N。

總的配額如果被申請完,則返回0配額給各個申請配額的服務節(jié)點,服務節(jié)點對新接入的請求消息進行流控。

5.3. 用戶自定義流控機制

不同的業(yè)務,存在不同的流控策略,例如基于微服務優(yōu)先級的流控、基于節(jié)假日的流控、基于業(yè)務字段的流控等。底層的服務框架無法實現(xiàn)所有業(yè)務級的定制流控策略,因此,過于業(yè)務化的流控往往由業(yè)務通過自定義流控機制定制實現(xiàn)。

服務框架提供服務調(diào)用入口的攔截點和切面接口,由業(yè)務實現(xiàn)自定義流控。也可以提供基礎的流控框架,供業(yè)務實現(xiàn)流控條件判斷、流控執(zhí)行策略等,簡化業(yè)務的定制工作量。

6. 使用Hystrix提升微服務可靠性

6.1. Hystrix簡介

Hystrix是Netflix開源的一個可靠性組件,主要用于分布式環(huán)境中的依賴解耦,Hystrix library通過添加延遲容忍和容錯邏輯來控制分布式服務之間的相互影響,通過服務之間訪問的隔離點阻止連鎖故障,并提供了失敗回調(diào)機制,來改進系統(tǒng)的可靠性。

Hystrix提供如下機制來提升分布式系統(tǒng)的可靠性:

保護通過第三方客戶端API依賴訪問,控制其延遲和故障

阻止級聯(lián)故障和“雪崩效應”

提供熔斷機制,快速失敗和恢復

失敗回調(diào)和優(yōu)雅降級機制

近實時檢測、報警和KPI指標展示

6.2. Hystrix的核心功能

Hystrix提供了一些非常有價值、與具體微服務框架實現(xiàn)無關的特性,方便不同的分布式系統(tǒng)集成使用。

6.2.1. 依賴隔離

Hystrix使用命令模式HystrixCommand(Command)包裝依賴調(diào)用邏輯,每個命令在單獨線程/信號授權下執(zhí)行。依賴調(diào)用的超時時間可配置,如果超時,則則返回失敗或者執(zhí)行fallback邏輯。原理如下所示:

微服務可靠性設計

圖6-1 基于線程/信號的依賴隔離

6.2.2. 熔斷器

Hystrix會先經(jīng)過熔斷器,此時如果熔斷器的狀態(tài)是打開,則說明已經(jīng)熔斷,這時將直接進行降級處理,不會繼續(xù)將請求發(fā)到線程池。

熔斷器的開關狀態(tài)由熔斷算法決定,它的原理如下:

判斷是否熔斷:根據(jù)bucket中記錄的次數(shù),計算錯誤率。如果錯誤率達到熔斷預置的閾值,則開啟熔斷開關。

熔斷恢復:對于被熔斷的請求,暫停處理一段時間之后(HystrixCommandProperties.circuitBreakerSleepWindowInMilliseconds()),允許單個請求通過,若請求成功,則取消熔斷,否則,繼續(xù)熔斷。

Hystrix熔斷器的工作原理如下所示:

微服務可靠性設計

圖6-2 Hystrix熔斷機制

6.2.3. 優(yōu)雅降級

當微服務調(diào)用異常、超時,或者熔斷時,可以通過回調(diào)Fallback()的方式實現(xiàn)業(yè)務的優(yōu)雅降級,它的原理如下所示:

微服務可靠性設計

圖6-3 Hystrix優(yōu)雅降級機制

6.2.4. Reactive編程Hystrix支持響應式編程,并提供了相關接口給用戶,如下所示:

微服務可靠性設計

利用響應式編程,可以更加優(yōu)雅和靈活的實現(xiàn)異步回調(diào)邏輯的處理。

6.2.5. 信號量隔離

為了降低線程資源的開銷,Hystrix提供了信號量Semaphores,用于實現(xiàn)輕量級的依賴隔離。開發(fā)者可以限制系統(tǒng)對某一個依賴的最高并發(fā)數(shù),這個基本上等同于并發(fā)流控策略。每次微服務調(diào)用依賴時都會檢查一下是否到達信號量的限制值,如達到則拒絕。該隔離策略的優(yōu)點是不新起線程,減少上下文切換和線程數(shù),缺點是無法配置斷路,每次都一定會去嘗試獲取信號量。

6.3. 集成Hystrix

由于Hystrix與特定的分布式系統(tǒng)、微服務框架無關,是個通用的分布式系統(tǒng)可靠性組件,可以通過類庫集成的方式方便的集成到已有的微服務架構體系中。

6.3.1. 集成架構

在已有微服務體系中集成Hystrix的策略如下:微服務框架中,對于通用的微服務調(diào)用、磁盤I/O操作、數(shù)據(jù)庫操作和網(wǎng)絡I/O操作等使用HystrixCommand做一層異步包裝,實現(xiàn)業(yè)務的微服務調(diào)用線程和第三方依賴的線程隔離。

對于非通用的第三方依賴,或者業(yè)務微服務自身引入的第三方依賴,直接基于HystrixCommand做異步隔離。

對第三方依賴進行分類、分組管理,根據(jù)依賴的特點設置熔斷策略、優(yōu)雅降級策略、超時策略等,以實現(xiàn)差異化的處理。

集成架構示例如下:

微服務可靠性設計

圖6-4 集成Hystrix的微服務架構

6.3.2. 集成Hystrix帶來的優(yōu)點

第三方依賴隔離具備一定的通用性,例如數(shù)據(jù)庫隔離、磁盤I/O隔離、第三方服務調(diào)用隔離等,如果各自構建一套隔離機制,除了增加工作量之外,后續(xù)維護起來也比較麻煩。另外,業(yè)務微服務自身也會引入第三方依賴,如果沒有通用的隔離機制,則業(yè)務需要自己構建業(yè)務級的隔離體系,相應的開發(fā)難度和工作量都較大,架構上也很難統(tǒng)一。

集成Hystrix,可以快速的構建微服務的隔離、熔斷、優(yōu)雅降級和響應式編程體系,提升系統(tǒng)的可靠性。

另外,Hystrix非常成熟,在Netflix已經(jīng)經(jīng)歷過苛刻的生產(chǎn)環(huán)境考驗,它的可靠性和成熟度完全能夠滿足大部分業(yè)務場景的需要。

聲明:本文內(nèi)容及配圖由入駐作者撰寫或者入駐合作網(wǎng)站授權轉(zhuǎn)載。文章觀點僅代表作者本人,不代表電子發(fā)燒友網(wǎng)立場。文章及其配圖僅供工程師學習之用,如有內(nèi)容侵權或者其他違規(guī)問題,請聯(lián)系本站處理。 舉報投訴
  • 微服務
    +關注

    關注

    0

    文章

    137

    瀏覽量

    7351
收藏 人收藏

    評論

    相關推薦

    寶藏級微服務架構工具合集

    大量數(shù)據(jù)流。這些工具各有特色,可根據(jù)具體需求和場景選擇合適的來構建和管理微服務架構。以下是UU云小編整理的幾個熱門的微服務架構工具及其概括介紹:
    的頭像 發(fā)表于 12-21 16:33 ?140次閱讀

    半導體封裝的可靠性測試及標準

    產(chǎn)品可靠性是指產(chǎn)品在規(guī)定的使用條件下和一定時間內(nèi),能夠正常運行而不發(fā)生故障的能力。它是衡量產(chǎn)品質(zhì)量的重要指標,對提高客戶滿意度和復購率具有重要影響。金鑒實驗室作為一家提供檢測、鑒定、認證和研發(fā)服務
    的頭像 發(fā)表于 11-21 14:36 ?199次閱讀
    半導體封裝的<b class='flag-5'>可靠性</b>測試及標準

    微服務架構與容器云的關系與區(qū)別

    微服務架構與容器云密切相關又有所區(qū)別。微服務將大型應用拆分為小型、獨立的服務,而容器云基于容器技術,為微服務提供構建、發(fā)布和運行的平臺。區(qū)別在于,
    的頭像 發(fā)表于 10-21 17:28 ?226次閱讀

    無鉛焊接的可靠性

    電子發(fā)燒友網(wǎng)站提供《無鉛焊接的可靠性.pdf》資料免費下載
    發(fā)表于 10-16 10:50 ?5次下載

    PCB高可靠性化要求與發(fā)展——PCB高可靠性的影響因素(上)

    在電子工業(yè)的快速發(fā)展中,印刷電路板(PCB)的可靠性始終是設計和制造的核心考量。隨著集成電路(IC)的集成度不斷提升,PCB不僅需要實現(xiàn)更高的組裝密度,還要應對高頻信號傳輸?shù)奶魬?zhàn)。這些趨勢對PCB
    的頭像 發(fā)表于 10-11 11:20 ?336次閱讀
    PCB高<b class='flag-5'>可靠性</b>化要求與發(fā)展——PCB高<b class='flag-5'>可靠性</b>的影響因素(上)

    入門級攻略:如何容器化部署微服務?

    第一步理解容器化基礎,第二步創(chuàng)建Dockerfile,第三步構建推送鏡像,第四步部署微服務,第五步管理微服務、第六步優(yōu)化更新。容器化部署微服務是現(xiàn)代軟件開發(fā)中的一種高效方法,可提供良好的可移植
    的頭像 發(fā)表于 10-09 10:08 ?156次閱讀

    基于可靠性設計感知的EDA解決方案

    產(chǎn)品可靠性,包括制造和運營方面,正在成為芯片-封裝-系統(tǒng)迭代設計周期中設計的關鍵方面,尤其是那些有望承受更長使用壽命和可能的惡劣操作環(huán)境的產(chǎn)品,例如汽車電子系統(tǒng)、高性能計算 (HPC)、電信
    的頭像 發(fā)表于 07-15 09:56 ?424次閱讀
    基于<b class='flag-5'>可靠性</b>設計感知的EDA解決方案

    汽車功能安全與可靠性的關系

    當前,隨著汽車領域的飛速發(fā)展,汽車也被重新定義。在汽車電子電氣系統(tǒng)設計時,離不開對功能安全和可靠性設計的考慮。正確理解兩者之間的關系,有助于更好地分析問題和解決問題。什么是汽車可靠性汽車可靠性是指
    的頭像 發(fā)表于 07-13 08:28 ?3223次閱讀
    汽車功能安全與<b class='flag-5'>可靠性</b>的關系

    請問FATFS文件系統(tǒng)可靠性如何?

    ST官方固件庫中使用了FATFS文件系統(tǒng),想問下,這個文件系統(tǒng)可靠么? 我想了解一下,有哪位朋友真正產(chǎn)品上使用FATFS文件系統(tǒng),可靠性有什么問題沒有。
    發(fā)表于 05-16 06:35

    半導體可靠性手冊

    電子發(fā)燒友網(wǎng)站提供《半導體可靠性手冊.pdf》資料免費下載
    發(fā)表于 03-04 09:35 ?23次下載

    基于結構相似可靠性監(jiān)測結果

    電子發(fā)燒友網(wǎng)站提供《基于結構相似可靠性監(jiān)測結果.pdf》資料免費下載
    發(fā)表于 02-05 09:10 ?0次下載
    基于結構相似<b class='flag-5'>性</b><b class='flag-5'>可靠性</b>監(jiān)測結果

    美國站群服務器優(yōu)化:提升性能與可靠性的關鍵功能

    隨著互聯(lián)網(wǎng)的迅猛發(fā)展,網(wǎng)站的性能和可靠性成為了企業(yè)成功的關鍵因素之一。美國作為全球互聯(lián)網(wǎng)的中心,其站群服務器在全球范圍內(nèi)都有著廣泛的應用。本文將探討美國站群服務器優(yōu)化的關鍵功能,以提升其性能和
    的頭像 發(fā)表于 01-25 11:56 ?343次閱讀

    如何確保IGBT的產(chǎn)品可靠性

    在當今的半導體市場,公司成功的兩個重要因素是產(chǎn)品質(zhì)量和可靠性。而這兩者是相互關聯(lián)的,可靠性體現(xiàn)為在產(chǎn)品預期壽命內(nèi)的長期質(zhì)量表現(xiàn)。任何制造商要想維續(xù)經(jīng)營,必須確保產(chǎn)品達到或超過基本的質(zhì)量標準和可靠性
    的頭像 發(fā)表于 01-25 10:21 ?1642次閱讀
    如何確保IGBT的產(chǎn)品<b class='flag-5'>可靠性</b>

    IGBT的可靠性測試方案

    在當今的半導體市場,公司成功的兩個重要因素是產(chǎn)品質(zhì)量和可靠性。而這兩者是相互關聯(lián)的,可靠性體現(xiàn)為在產(chǎn)品預期壽命內(nèi)的長期質(zhì)量表現(xiàn)。任何制造商要想維續(xù)經(jīng)營,必須確保產(chǎn)品達到或超過基本的質(zhì)量標準和可靠性
    的頭像 發(fā)表于 01-17 09:56 ?1459次閱讀
    IGBT的<b class='flag-5'>可靠性</b>測試方案

    游戲公司不使用微服務架構的原因

    微服務基本只有 request/response 的模式。做不了 streaming?微服務通常要求應用是無狀態(tài)的才能做到水平擴展。streaming 本身就是加入了狀態(tài)
    的頭像 發(fā)表于 12-29 11:18 ?443次閱讀