微服務治理實踐:如何對單點異常進行自動摘除

直播回顧:點擊這裏前端

微服務架構下,穩定性和高可用性一個永恆的話題,在實際的治理過程當中,咱們有可能會遇到如下場景:git

  • 某個應用灰度發佈,先上了幾臺機器,因爲代碼邏輯寫的有問題,形成線程池滿,出現運行異常。
  • 服務端集羣中,某幾臺機器因爲磁盤滿,或者是宿主機資源爭搶致使 load 太高,客戶端出現調用超時。
  • 服務端集羣中,某幾臺機器因爲線程池滿,形成 Full Garbage Collection。

在以上 3 種場景中,因爲客戶端並不法感知已經出現問題的那些服務端,依然會發送請求到這些機器上,形成業務調用報錯,上游的機子將會被下游的某臺機子的短暫故障拖垮,形成應用雪崩的風險。github

面對這種場景,若是僅僅爲此而進行服務降級,對應用的傷害未免過大,但若是咱們能夠檢測出服務集羣中某些故障機子,並對其進行短暫隔離,便可有效保障服務的高可用與系統的穩定性,同時給運維人員提供了寶貴的緩衝時間,用於問題定位,排除故障。web

本文將做爲《微服務治理實踐》系列篇的第一篇,爲你們介紹如何實現離羣實例摘除。該系列文章是基於阿里雲商業化產品 EDAS 的微服務實踐,若是您團隊具有較強的微服務治理能力,那麼但願咱們在微服務治理方面的實踐和背後的思考,能夠爲您提供一些參考。算法

Microservice Outlier Ejection (微服務離羣實例摘除)

  • 什麼是離羣實例摘除

當單點發生夯機異常時,consumer 能主動判斷,並將對應的 provider 實例短期剔除,再也不請求,在必定時間間隔後再繼續訪問。同時,具備全局異常判斷能力,當 provider 異常實例的數量過多時,而且超過必定的控制比例,說明此時 provide 總體服務質量低下,該機制僅保持摘除必定的比例。瀏覽器

  • 離羣實例摘除的功能

從服務層容錯能力上,對業務穩定性進行加強,有效解決單點故障的問題。網絡

  • 與熔斷的區別

熔斷是指當服務的輸入負載激增時, 避免服務被迅速壓垮致使雪崩效應,而對負載進行斷路的一種方式 。 熔斷通常由熔斷請求判斷算法,熔斷恢復機制,熔斷報警等模塊組成。隔離是指,爲了不在依賴的服務故障時候形成的故障擴散,而採起的將系統進行單元化設計的一種架構方法。架構

若僅僅因爲服務端集羣中單點異常問題,就採用熔斷降級方案,將會對應用的傷害過大,離羣實例摘除能夠有效地解決單點異常問題從而保證服務質量。若 provider 總體服務質量低下時,離羣摘除效果再也不明顯,此時能夠採用熔斷降級功能。框架

  • 離羣實例摘除支持的版本

只要您的應用版本在列表中,您無需改動一行代碼就可使用到離羣實例摘除功能。less

目前已經覆蓋了市面上大部分微服務場景,後續咱們將會持續支持開源最新的 Dubbo/Spring Cloud 版本。

咱們提供了 Dubbo 和 Spring Cloud 兩種場景的離羣摘除功能,本文將先介紹一下 Dubbo Microservice Outlier Ejection 的實踐與效果。

下面將經過在 EDAS 上經過演示 Dubbo 離羣摘除功能及效果。

企業級分佈式應用服務EDAS(Enterprise Distributed Application Service)是一個應用託管和微服務管理的 PaaS 平臺,提供應用開發、部署、監控、運維等全棧式解決方案,同時支持 Dubbo、Spring Cloud 等微服務運行環境。

https://www.aliyun.com/product/edas

準備

接下來以微服務Demo爲例子示範離羣摘除功能,讀者能夠從github中下載驗證

https://github.com/aliyun/alibabacloud-microservice-demo/tree/master/src

微服務Demo是一個簡單的電商項目,下圖爲項目結構,cartservice 爲 Dubbo 框架的購物車服務 provider,productservice 爲Spring Cloud提供的商品詳情服務 provider,frontend 爲web controller即前端展現頁面,能夠理解爲consumer。

咱們將以cartservice服務即Dubbo服務端爲例子,展現離羣實例摘除功能。

EDAS 上部署微服務 Demo

首先 cd cartservice切換到 cartservice 目錄下,再經過 mvn clean install 打包,經過 cd cartservice-provider/target 切換到target目錄下,咱們能夠看到新生成的 cartservice-provider-1.0.0-SNAPSHOT.jar 包,而後在 EDAS上 建立一個 cartservice 應用。

點擊下一步後,上傳剛纔打包的jar包,即 cartservice-provider/target/ cartservice-provider-1.0.0-SNAPSHOT.jar 而後下一步,記住登錄密碼,直到建立應用成功。

而後啓動應用,到目前爲止,咱們啓動了一個 cartservice-provider。點擊按此實例規格擴容,該服務咱們部署在兩個實例上。

咱們在這個 provider 的 com.alibabacloud.hipstershop.provider.CartServiceImpl 類中能夠看到,這個 provider 是提供了viewCart 和 addItemToCart 的兩個關於購物車的服務,咱們在 viewCart 中加入一些模擬運行時異常的邏輯。

其中 exceptionIp 爲 ACM 配置中心的exception.ip的配置項,若該項配置爲本機ip時,該服務throw RuntimeException,用於模擬業務異常的場景。

  • 爲何將 cartservice 擴容到兩個實例,想必你們也猜到了,運行時經過配置ACM配置中心指定其中一個實例的IP,模擬出一個實例異常的場景。

接下來,咱們須要部署 frontend / productservice 兩個服務,方式同樣,分別上傳 frontend/target/frontend-1.0.0-SNAPSHOT.jar 和 productservice/productservice-provider/target/productservice-provider-1.0.0-SNAPSHOT.jar

從下圖能夠看到,咱們的微服務Demo在EDAS部署上去了。

模擬業務異常

進入到 frontend 應用中,咱們看到其實例的公網 ip 爲 47.99.150.33。

進入瀏覽器訪問 http://47.99.150.33:8080/

點擊View Cart 訪問至 http://47.99.150.33:8080/cart

能夠看到,此時服務都是正常的。

咱們去 ACM 配置中心 配置 exception.ip 爲 172.16.205.180(即cartservice的其中某個實例的IP)。

而後繼續訪問 http://47.99.150.33:8080/cart ,發現 50 % 的機率錯誤頁面

此時,咱們寫一個腳本,定時大量訪問 http://47.99.150.33:8080/cart 模擬請求。

而後 sh curlservice.sh http://47.99.150.33:8080/cart

咱們看到不斷重複的每秒鐘 10 次的 50% 的調用成功率。

其實也能夠理解到,下游的服務質量隨着上游的某臺機子的異常而急劇降低,甚至可能致使下游服務被上游某些機子的(系統、業務)異常給拖垮。

開啓離羣摘除策略

下面我將演示離羣摘除的策略的開啓及其效果的展現。

建立

咱們進入到 EDAS 左側列表的 [微服務管理] 下的 [離羣實例摘除] 界面中,並選擇建立離羣實例摘除策略。

而後按照提示一步步建立離羣摘除的策略。

基本信息

image

如上圖能夠選擇命名空間、填寫策略名稱、選擇該策略支持的框架類型(Dubbo/Spring Cloud)。

選擇生效應用

按照目前的調用方式,咱們只須要配置 frontend 應用,保護下游應用 consumer。

配置策略

這些參數都提供了默認值,須要根據本身應用的具體狀況調整最合適的值,因爲須要保護的 RuntimeException 屬於業務異常因而選上 網絡異常+業務異常。(須要注意的是即便摘除實例比例上限配得特別低,向下取整數小於1,當集羣中實例數目大於1,且某一實例異常,咱們也會摘除一實例)。

建立完成

能夠看到策略的信息,建立完成。

策略

看到了咱們建立的離羣摘除策略,且是針對Dubbo框架,而且針對的是 網絡異常+業務異常 的異常類型。

驗證離羣摘除效果

這時,咱們看到,再感知到異常後,離羣摘除功能生效,請求調用一陣子後,均返回正確結果。

不斷刷新瀏覽器訪問 http://47.99.150.33:8080/cart 也均正常

客戶端感知到某臺服務端機子異常後,主動摘除。僅僅調用業務正常的 Provider 實例,同時咱們也能夠通 ARMS(EDAS監控系統) 監控看到服務質量的上升,以及流量從異常 Provider 中摘除。

Dubbo框架能夠從 /home/admin/.opt/ArmsAgent/logs 目錄下的日誌中,搜索日誌中的 「OutlierRouter」 關鍵字能夠看到一系列離羣實例摘除的事件日誌。

修改/關閉離羣摘除策略

對於EDAS的應用咱們支持經過控制檯動態修改和刪除離羣摘除策略。

  • 對應策略規則的修改

點擊 修改生效應用 或者 編輯策略。

而後增長刪除應用或者調整參數,肯定後均當即生效

  • 刪除對應策略

控制檯的操做,對應用中的配置都是實時生效的,若刪除策略後,默認關閉相關策略。

若咱們打開ARMS監控觀察具體的調用狀況。

ARMS監控

若咱們開啓監控,將會直觀看到流量與請求錯誤等信息。

開啓離羣摘除前

以下圖方式開啓,而後跳轉至ARMS(EDAS監控系統)應用監控頁面,咱們須要把三個應用都開啓高級監控。

咱們能夠從下圖即ARMS(EDAS監控系統)應用監控頁面直觀地看到結果。

從如下拓撲圖中咱們看到,流量不斷地訪問到cartservice服務上。

開啓離羣摘除後

離羣摘除效果經過簡單的例子就看到了,固然能夠經過 ARMS (EDAS監控系統)的監控能夠明顯觀察到服務質量的提高。

能夠看到,在開啓了離羣摘除的那個點只後,錯誤率從50%明顯降低。

其中兩個小的起伏毛刺是由於,離羣摘除一段時間後會從新嘗試訪問被摘除的 endPoint ,若依舊錯誤率高於閾值,繼續隔離,且間隔時間更長。

離羣實例摘除具體控制邏輯

前面咱們看到了,離羣實力摘除對應用穩定性提升帶來的幫助,下面咱們將具體分析離羣實例摘除的控制邏輯,有助於您更好地理解其各類參數的意義,以及能夠根據本身的應用狀況,經過調整參數,配置出最合適本身的離羣摘除策略。

對於 Dubbo/SpringCloud 框架:

  • 默認QPS下限爲1

只有當前某實例的調用QPS大於1纔會開始離羣實例摘除保護。

  • 默認錯誤率下限 50%

只有當前某實例的調用錯誤率高於 50% ,則系統會認爲該服務端集羣的當前某實例處於異常狀態。

  • 默認摘除實例比例上限 20%

若當前服務集羣中,有大於20%的實例節點處於異常狀態,則系統只會摘除異常狀態的實例數佔集羣總數的50%。

  • 異常類型

若異常類型爲 網絡異常 ,則系統僅僅把網絡異常的錯誤算進錯誤率統計中,忽略掉業務異常;反之,若選擇了 網絡異常 + 業務異常 則系統會將全部異常當成錯誤算進錯誤率統計中。

  • 關於恢復檢測單位時間(默認30000ms即30s)與未恢復累計次數上限(默認40)的解釋

其中第一次摘除時長爲 0.5 分鐘,時間到了以後 consumer 會繼續訪問該 provider ,若該 provider 服務質量依舊低下,則會繼續摘除,摘除時長隨着連續被摘除次數的增長線性遞增每次增長 0.5 分鐘,每次最多摘除 20 分鐘。固然,若繼續調用以後,服務質量恢復了,則會當成健康服務,下一次又出現異常致使服務質量低下問題時,會從新隔離 0.5 分鐘,並繼續上述規則。

  • 兜底

可是當客戶端調用的服務僅有1個實例提供服務提供則不會隔離這個實例。

若當前客戶端調用的服務實例大於1個,且當前離羣摘除隔離比例計算出的實例數小於1,若服務端集羣出現單點故障,則會摘除1個實例。

上面全部的實例能夠理解爲endpoint(ip+port爲緯度)

  • 通用最佳實踐

能夠配置相對的錯誤率閾值(50%)與太低的摘除實例比例上限(10%),全鏈路開啓。

離羣實例摘除技術細節

無侵入技術

無侵入方案即經過agent技術來實現,一句話來講就是經過字節碼加強技術,運行時插入咱們的代碼,改變應用的原有邏輯,能夠理解爲運行時AOP,經過在Dubbo的鏈路中插入Filter/Router,在Spring Cloud中加強LoadBalance邏輯,來實現咱們指望的路由控制邏輯。同時由於是agent加強的,再加上 Dubbo 各個版本的鏈路總體基本沒大的變化,Spring Cloud 模型的統一性,所以咱們能夠花少的代價將能力基本覆蓋到全部版本。

Dubbo Agent 方案技術架構

對於用戶來講,無需改動一行代碼,一行配置,便可享受到穩定性加強的能力。

離羣實例摘除技術

Outlier Detection 離羣檢測

均是基於時間窗口的數據統計。

兩種實現
一、Dubbo 2.7 版本經過向鏈路中嵌入一個MetricsFilter,對於鏈路的每一個request/response作打點處理,統計rt、調用成功與否、異常類型,而且已endpoint(ip+port)爲key存儲

二、在 Agent 底座中統計通過的http請求,經過url、rt、狀態碼、異常類型等數據結果,統計最近時間窗口的數據(目前寫死 10 秒,暫時不透出)

實時統計前N秒的調用信息,做爲離羣實例摘除動做的依據。

Outlier Ejection 離羣摘除

Dubbo 基於 Dubbo Router 實現,對於調用的上游服務對應的全部 invokers 中,拉黑掉「不健康」的節點,同時記錄拉黑的信息。

Dubbo-Router控制邏輯

每次請求過來僅僅check一下並標記狀態,後臺有專門兩個線程將標記的流量進行判斷是否進入隔離列表或從中剔除,修改拉黑信息等耗時操做,最大程度上保證請求的實時性。

Spring Cloud 基於 擴展 LoadBalace 實現,原理類似。

微服務商業化團隊招人了~

Dubbo / Spring Cloud 商業化,咱們除了 EDAS,咱們還有 ARMS(應用實時監控服務)、MSE(微服務引擎)、ACM(應用配置管理)、SAE(Serverless 應用引擎)等獨立產品。咱們在忙什麼?用心打磨這些產品,就是咱們的工做。

團隊的目標是將阿里巴巴在服務治理上的最佳實踐經過產品化的形式輸出給阿里雲上的企業客戶,幫助客戶實現業務永遠在線。

招聘郵箱: shengwei.psw@alibaba-inc.com

做者信息:泮聖偉,花名十眠,中間件技術-微服務產品團隊研發工程師,負責 Dubbo / Spring Cloud 商業化產品開發相關工做,目前主要關注雲原生、微服務等技術方向。


本文做者:泮聖偉

原文連接

本文爲阿里雲內容,未經容許不得轉載。

相關文章
相關標籤/搜索