微服务实践分享(8) 控制调用中心
1.熔斷
在微服務領域,熔斷機制是從消費端保護微服務提供者的措施,當微服務的運行質量低于某個臨界值時,啟動熔斷機制,暫停微服務調用一段時間,以保障后端的微服務不會因為持續過負荷而宕機。
?
2.降級
服務降級主要包括容錯降級和屏蔽降級
屏蔽降級:1)throw null 不發起遠程調用,直接返回空
? ? ? ? ?2)throw exception 不發起遠程調用,直接拋出指定異常
? ? ? ? ?3)execute bean 不發起遠程調用,直接執行本地模擬接口實現?
服務降級是可逆操作,當系統壓力恢復到一定值不需要降級服務時,要重新發起遠程調用,服務狀態改為正常
?
容錯降級:非核心服務不可調用時,可以對故障服務做業務放通,保證主流程不受影響
1)RPC異常:通常指超時、消息解碼異常、流控異常、系統擁塞保護異常等
2)Service異常 eg登錄校驗異常、數據庫操作失敗異常等
?
容錯降級和屏蔽降級的區別在于:
1)觸發條件不同:屏蔽降級往往是人工根據系統的運行,手動設置
? ? ? ? ? ? ? ? 容錯降級是根據服務調用返回的結果,結合當前的服務級別,自動匹配觸發
2)作用不同:容錯降級是服務不可用時,讓消費者執行業務放通
? ? ? ? ? ? 屏蔽降級主要目的是將原屬于降級業務的資源調配出來供核心業務使用
3)調用機制不同,一個發起遠程服務調用,一個只做本地調用
?
3.流量控制
當資源成為瓶頸時,服務框架需要對消費者做限流,啟動流控保護機制。流量控制有多種策略,比較常用的有:針對訪問速率的靜態流控、針對資源占用的動態流控等。
在實踐中,各種流量控制策略需要綜合使用才能起到較好的效果。
動態流控
動態流控的最終目標是為了保命,并不是對流量或者訪問速度做精確控制。當系統負載壓力非常大時,系統進入過負載狀態,可能是CPU、內存資源已經過載,也可能是應用進程內部的資源幾乎耗盡,如果繼續全量處理業務,可能會導致消息嚴重積壓或者應用進程宕機。
動態流控檢測的資源包括:
- CPU使用率。
- 內存使用率(對于Java,主要是JVM內存使用率)。
- 隊列積壓率。
靜態流控
靜態流控主要針對客戶端訪問速率進行控制,它通常根據服務質量等級協定(SLA)中約定的QPS做全局流量控制,例如計費服務的靜態流控閾值為200 QPS,則無論集群有多少個計費服務實例,它們總的處理速率之和不能超過200 QPS。
由于微服務具備彈性伸縮、動態上線和下線等特性,因此集群中某個微服務實例的節點個數是動態變化的,采用傳統的平均分配制無法做到精準的控制。
在實踐中,比較成熟的集群靜態流控策略是動態配額申請制,它的工作原理如下:
用戶自定義流控機制
不同的業務,存在不同的流控策略,例如基于微服務優先級的流控、基于節假日的流控、基于業務字段的流控等。底層的服務框架無法實現所有業務級的定制流控策略,因此,過于業務化的流控往往由業務通過自定義流控機制定制實現。
服務框架提供服務調用入口的攔截點和切面接口,由業務實現自定義流控。也可以提供基礎的流控框架,供業務實現流控條件判斷、流控執行策略等,簡化業務的定制工作量。
?
4.隔離
?
由于大部分微服務采用同步接口調用,而且多個領域相關的微服務會部署在同一個進程中,很容易發生“雪崩效應”,即某個微服務提供者故障,導致調用該微服務的消費者、或者與故障微服務合設在同一個進程中的其它微服務發生級聯故障,最終導致系統崩潰。
為了避免“雪崩效應”的發生,需要支持多種維度的依賴和故障隔離,以實現微服務的HA。
通信鏈路隔離
由于網絡通信本身通常不是系統的瓶頸,因此大部分服務框架會采用多線程+單個通信鏈路的方式進行通信,原理如下所示:
多線程-單鏈路P2P通信模式
正如前面章節所述,由于微服務使用異步非阻塞通信,單個I/O線程可以同時并發處理多個鏈路的消息,而且網絡讀寫都是非阻塞的,因此采用多線程+單鏈路的方式進行通信性能本身問題不大。但是從可靠性角度來看,只支持單鏈路本身又存在一些可靠性隱患,我們從下面的案例中看下問題所在。
某互聯網基地微服務架構上線之后,發現在一些時段,經常有業務超時,超時的業務沒有固定規律。經定位發現當有較多的批量內容同步、語音和視頻類微服務調用時,系統的整體時延就增高了很多,而且存在較突出的時延毛刺。由于這些操作獲取的消息碼流往往達到數M到數十兆,微服務之間又采用單鏈路的方式進行P2P通信,導致大碼流的傳輸影響了其它消息的讀寫效率,增大了微服務的響應時延。
問題定位出來之后,對微服務之間的通信機制做了優化,節點之間支持配置多鏈路,每個鏈路之間還可以實現不同策略的隔離,例如根據消息碼流大小、根據微服務的優先級等策略,實現鏈路級的隔離,優化之后的微服務通信機制:
支持多鏈路隔離
?調度資源隔離
? ? 微服務之間隔離
當多個微服務合設運行在同一個進程內部時,可以利用線程實現不同微服務之間的隔離。
對于核心微服務,發布的時候可以獨占一個線程/線程池,對于非核心微服務,則可以共享同一個大的線程池,在實現微服務隔離的同時,避免線程過于膨脹:
圖3-3 微服務之間故障隔離
假如非核心服務3發生故障,長時間阻塞線程池1的工作線程,其它與其共用線程池消息隊列的非核心服務1和服務2只能在隊列中排隊等待,當服務3釋放線程之后,排隊的服務1和服務2可能已經超時,只能被丟棄掉,導致業務處理失敗。
采用線程池隔離的核心服務1和服務2,由于各自獨占線程池,擁有獨立的消息隊列,它的執行不受發生故障的非核心服務1影響,因此可以繼續正常工作。通過獨立線程池部署核心服務,可以防止故障擴散,保障核心服務的正常運行。
?第三方依賴隔離
在微服務中通常會調用第三方中間件服務,例如分布式緩存服務、分布式消息隊列、NoSQL服務等。只要調用第三方服務,就會涉及跨網絡操作,由于客戶端SDK API的封裝,很多故障都是隱性的,因此,它的可靠性需要額外關注。
整體而言,第三方依賴隔離可以采用線程池 + 響應式編程(例如RxJava)的方式實現,它的原理如下所示:
1) 對第三方依賴進行分類,每種依賴對應一個獨立的線程/線程池。
2) 微服務不直接調用第三方依賴的API,而是使用異步封裝之后的API接口。
3) 異步調用第三方依賴API之后,獲取Future對象。利用響應式編程框架,可以訂閱后續的事件,接收響應,針對響應進行編程。
利用Netflix開源的hystrix + RxJava,可以快速實現第三方依賴的隔離,后續章節我們會詳細介紹下如何使用。
進程級隔離
對于核心的微服務,例如商品購買、用戶注冊、計費等,可以采用獨立部署的方式,實現高可用性。
? 容器隔離
微服務鼓勵軟件開發者將整個軟件解耦為功能單一的服務,并且這些服務能夠獨立部署、升級和擴容。如果微服務抽象的足夠好,那么微服務的這一優點將能夠提升應用的敏捷性和自治理能力。
利用Docker容器部署微服務,可以帶來如下幾個優點:
- 高效:Docker容器的啟動和停止不需要幾分鐘,只要幾百毫秒就足夠了。使用Docker部署微服務,微服務的啟動和銷毀速度非常快,在高壓力時,可以實現秒級彈性伸縮。
- 高性能:Docker容器的性能接近裸的物理機,比VM平均高20%+。
- 隔離性:利用Docker,可以實現0.1 core的隔離。基于細粒度的資源隔離機制,可以實現高密度的部署微服務,同時實現它們之間的資源層隔離,保障微服務的可靠性。
- 可移植性:在基于虛擬機的解決方案中,應用的可移植性通常來說會受到云提供商所提供的虛擬機格式限制。如果應用程序需要部署到不同類型的虛擬機中,需要針對特定的虛擬機格式做鏡像文件,新增很多額外的開發和測試工作量。Docker容器的設計理念是“一次編寫,到處運行”,這可以使開發者避免上面這種限制。
基于Docker容器部署微服務,實現物理資源層隔離示意圖如下所示:
圖3-4? 基于Docker容器的微服務隔離
VM隔離
除了Docker容器隔離,也可以使用VM對微服務進行故障隔離,相比于Docker容器,使用VM進行微服務隔離存在如下優勢:
開源:
1.Hystrix - Latency and fault tolerance library designed to isolate points of access to remote systems, services and 3rd party libraries, stop cascading failure and enable resilience in complex distributed systems where failure is inevitable.
2. Resilient HTTP - A smart HTTP client with super powers like fault tolerance, dynamic server discovery, auto balancing and reactive recovery, designed for distributed systems.
?
參考文獻:
【1】http://www.infoq.com/cn/articles/micro-service-reliability-design
?
轉載于:https://www.cnblogs.com/davidwang456/p/9264919.html
總結
以上是生活随笔為你收集整理的微服务实践分享(8) 控制调用中心的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 微服务的容错模式
- 下一篇: 微服务实践分享(9)文档中心