設(shè)計(jì)穩(wěn)定的微服務(wù)系統(tǒng)時(shí)不得不考慮的場景
我們的生產(chǎn)環(huán)境經(jīng)常會(huì)出現(xiàn)一些不穩(wěn)定的情況,如:
- 大促時(shí)瞬間洪峰流量導(dǎo)致系統(tǒng)超出最大負(fù)載,load 飆高,系統(tǒng)崩潰導(dǎo)致用戶無法下單
- “黑馬”熱點(diǎn)商品擊穿緩存,DB 被打垮,擠占正常流量
- 調(diào)用端被不穩(wěn)定服務(wù)拖垮,線程池被占滿,導(dǎo)致整個(gè)調(diào)用鏈路卡死
這些不穩(wěn)定的場景可能會(huì)導(dǎo)致嚴(yán)重后果。大家可能想問:如何做到均勻平滑的用戶訪問?如何預(yù)防流量過大或服務(wù)不穩(wěn)定帶來的影響?
介紹
下面兩種方式是在面對(duì)流量不穩(wěn)定因素時(shí)常見的兩種方案,也是我們?cè)谠O(shè)計(jì)高可用的系統(tǒng)前不得不考慮的兩種能力,是服務(wù)流量治理中非常關(guān)鍵的一環(huán)。
流量控制
流量是非常隨機(jī)性的、不可預(yù)測的。前一秒可能還風(fēng)平浪靜,后一秒可能就出現(xiàn)流量洪峰了(例如雙十一零點(diǎn)的場景)。每個(gè)系統(tǒng)、服務(wù)都有其能承載的容量上限,如果突然而來的流量超過了系統(tǒng)的承受能力,就可能會(huì)導(dǎo)致請(qǐng)求處理不過來,堆積的請(qǐng)求處理緩慢,CPU/Load 飆高,最后導(dǎo)致系統(tǒng)崩潰。因此,我們需要針對(duì)這種突發(fā)的流量來進(jìn)行限制,在盡可能處理請(qǐng)求的同時(shí)來保障服務(wù)不被打垮,這就是流量控制。
熔斷降級(jí)
一個(gè)服務(wù)常常會(huì)調(diào)用別的模塊,可能是另外的一個(gè)遠(yuǎn)程服務(wù)、數(shù)據(jù)庫,或者第三方 API 等。例如,支付的時(shí)候,可能需要遠(yuǎn)程調(diào)用銀聯(lián)提供的 API;查詢某個(gè)商品的價(jià)格,可能需要進(jìn)行數(shù)據(jù)庫查詢。然而,這個(gè)被依賴服務(wù)的穩(wěn)定性是不能保證的。如果依賴的服務(wù)出現(xiàn)了不穩(wěn)定的情況,請(qǐng)求的響應(yīng)時(shí)間變長,那么調(diào)用服務(wù)的方法的響應(yīng)時(shí)間也會(huì)變長,線程會(huì)產(chǎn)生堆積,最終可能耗盡業(yè)務(wù)自身的線程池,服務(wù)本身也變得不可用。
現(xiàn)代微服務(wù)架構(gòu)都是分布式的,由非常多的服務(wù)組成。不同服務(wù)之間相互調(diào)用,組成復(fù)雜的調(diào)用鏈路。以上的問題在鏈路調(diào)用中會(huì)產(chǎn)生放大的效果。復(fù)雜鏈路上的某一環(huán)不穩(wěn)定,就可能會(huì)層層級(jí)聯(lián),最終導(dǎo)致整個(gè)鏈路都不可用。因此我們需要對(duì)不穩(wěn)定的弱依賴服務(wù)進(jìn)行熔斷降級(jí),暫時(shí)切斷不穩(wěn)定調(diào)用,避免局部不穩(wěn)定因素導(dǎo)致整體的雪崩。
Q:不少同學(xué)在問了,那么是不是服務(wù)的量級(jí)很小就不用進(jìn)行流量控制限流防護(hù)了呢?是不是微服務(wù)的架構(gòu)比較簡單就不用引入熔斷保護(hù)機(jī)制了呢?
A:其實(shí),這與請(qǐng)求的量級(jí)、架構(gòu)的復(fù)雜程度無關(guān)。很多時(shí)候,可能正是一個(gè)非常邊緣的服務(wù)出現(xiàn)故障而導(dǎo)致整體業(yè)務(wù)受影響,造成巨大損失。我們需要具有面向失敗設(shè)計(jì)的意識(shí),在平時(shí)就做好容量規(guī)劃和強(qiáng)弱依賴的梳理,合理地配置流控降級(jí)規(guī)則,做好事前防護(hù),而不是在線上出現(xiàn)問題以后再進(jìn)行補(bǔ)救。
在流量控制、降級(jí)與容錯(cuò)場景下,我們有多種方式來描述我們的治理方案,下面我將介紹一套開放、通用的、面向分布式服務(wù)架構(gòu)、覆蓋全鏈路異構(gòu)化生態(tài)的服務(wù)治理標(biāo)準(zhǔn) OpenSergo,我們看看 OpenSergo 是如何定義流控降級(jí)與容錯(cuò)的標(biāo)準(zhǔn),以及支撐這些標(biāo)準(zhǔn)的實(shí)現(xiàn)有哪些,能幫助我們解決哪些問題?
OpenSergo 流控降級(jí)與容錯(cuò) v1alpha1 標(biāo)準(zhǔn)
在 OpenSergo 中,我們結(jié)合 Sentinel 等框架的場景實(shí)踐對(duì)流控降級(jí)與容錯(cuò)場景的實(shí)現(xiàn)抽象出標(biāo)準(zhǔn)的 CRD。我們可以認(rèn)為一個(gè)容錯(cuò)治理規(guī)則 (FaultToleranceRule) 由以下三部分組成:
- Target: 針對(duì)什么樣的請(qǐng)求
- Strategy: 容錯(cuò)或控制策略,如流控、熔斷、并發(fā)控制、自適應(yīng)過載保護(hù)、離群實(shí)例摘除等
- FallbackAction: 觸發(fā)后的 fallback 行為,如返回某個(gè)錯(cuò)誤或狀態(tài)碼
那我們看看針對(duì)常用的流控降級(jí)場景,OpenSergo 具體的標(biāo)準(zhǔn)定義是什么樣的,他是如何解決我們的問題的?
首先提到的,只要微服務(wù)框架適配了 OpenSergo,即可通過統(tǒng)一 CRD 的方式來進(jìn)行流控降級(jí)等治理。無論是 Java 還是 Go 還是 Mesh 服務(wù),無論是 HTTP 請(qǐng)求還是 RPC 調(diào)用,還是數(shù)據(jù)庫 SQL 訪問,我們都可以用這統(tǒng)一的容錯(cuò)治理規(guī)則 CRD 來給微服務(wù)架構(gòu)中的每一環(huán)配置容錯(cuò)治理,來保障我們服務(wù)鏈路的穩(wěn)定性。讓我們來詳細(xì)看看OpenSergo在各個(gè)具體場景下的一個(gè)配置。
流量控制
以下示例定義了一個(gè)集群流控的策略,集群總體維度每秒不超過 180 個(gè)請(qǐng)求。示例 CR YAML:
這樣一個(gè)簡單的 CR 就能給我們的系統(tǒng)配置上一個(gè)流量控制的能力,流控能力相當(dāng)于應(yīng)用的一個(gè)安全氣囊,超出系統(tǒng)服務(wù)能力以外的請(qǐng)求將被拒絕,具體邏輯可由我們自定義(如返回指定內(nèi)容或跳轉(zhuǎn)頁面)。
熔斷保護(hù)
以下示例定義了一個(gè)慢調(diào)用比例熔斷策略,示例 CR YAML:
這個(gè) CR 的語意就是:在 30s 內(nèi)請(qǐng)求超過 500ms 的比例達(dá)到 60% 時(shí),且請(qǐng)求數(shù)達(dá)到 5 個(gè),則會(huì)自動(dòng)觸發(fā)熔斷,熔斷恢復(fù)時(shí)長為 5s。
想象一下,在業(yè)務(wù)高峰期。當(dāng)某些下游的服務(wù)提供者遇到性能瓶頸,甚至影響業(yè)務(wù)。我們對(duì)部分非關(guān)鍵服務(wù)消費(fèi)者配置一個(gè)這樣的規(guī)則,當(dāng)一段時(shí)間內(nèi)的慢調(diào)用比例或錯(cuò)誤比例達(dá)到一定條件時(shí)自動(dòng)觸發(fā)熔斷,后續(xù)一段時(shí)間服務(wù)調(diào)用直接返回 Mock 的結(jié)果,這樣既可以保障調(diào)用端不被不穩(wěn)定服務(wù)拖垮,又可以給不穩(wěn)定下游服務(wù)一些“喘息”的時(shí)間,同時(shí)可以保障整個(gè)業(yè)務(wù)鏈路的正常運(yùn)轉(zhuǎn)。
流控降級(jí)與容錯(cuò)標(biāo)準(zhǔn)的實(shí)現(xiàn)
Sentinel 介紹
下面介紹一款支持 OpenSergo 流控降級(jí)與容錯(cuò)標(biāo)準(zhǔn)的項(xiàng)目 Sentinel 。
Sentinel 是阿里巴巴開源的,面向分布式服務(wù)架構(gòu)的流量控制組件,主要以流量為切入點(diǎn),從流量控制、流量整形、熔斷降級(jí)、系統(tǒng)自適應(yīng)保護(hù)等多個(gè)維度來幫助開發(fā)者保障微服務(wù)的穩(wěn)定性。
Sentinel 的技術(shù)亮點(diǎn):
- 高度可擴(kuò)展能力:基礎(chǔ)核心 + SPI 接口擴(kuò)展能力,用戶可以方便地?cái)U(kuò)展流控、通信、監(jiān)控等功能
- 多樣化的流量控制策略(資源粒度、調(diào)用關(guān)系、流控指標(biāo)、流控效果等多個(gè)維度),提供分布式集群流控的能力
- 熱點(diǎn)流量探測和防護(hù)
- 對(duì)不穩(wěn)定服務(wù)進(jìn)行熔斷降級(jí)和隔離
- 全局維度的系統(tǒng)負(fù)載自適應(yīng)保護(hù),根據(jù)系統(tǒng)水位實(shí)時(shí)調(diào)節(jié)流量
- 覆蓋 API Gateway 場景,為 Spring Cloud Gateway、Zuul 提供網(wǎng)關(guān)流量控制的能力
- 云原生場景提供 Envoy 服務(wù)網(wǎng)格集群流量控制的能力
- 實(shí)時(shí)監(jiān)控和規(guī)則動(dòng)態(tài)配置管理能力
一些普遍的使用場景:
- 在服務(wù)提供方(Service Provider)的場景下,我們需要保護(hù)服務(wù)提供方自身不被流量洪峰打垮。這時(shí)候通常根據(jù)服務(wù)提供方的服務(wù)能力進(jìn)行流量控制,或針對(duì)特定的服務(wù)調(diào)用方進(jìn)行限制。我們可以結(jié)合前期壓測評(píng)估核心接口的承受能力,配置 QPS 模式的限流,當(dāng)每秒的請(qǐng)求量超過設(shè)定的閾值時(shí),會(huì)自動(dòng)拒絕多余的請(qǐng)求。
- 為了避免調(diào)用其他服務(wù)時(shí)被不穩(wěn)定的服務(wù)拖垮自身,我們需要在服務(wù)調(diào)用端(Service Consumer)對(duì)不穩(wěn)定服務(wù)依賴進(jìn)行隔離和熔斷。手段包括信號(hào)量隔離、異常比例降級(jí)、RT 降級(jí)等多種手段。
- 當(dāng)系統(tǒng)長期處于低水位的情況下,流量突然增加時(shí),直接把系統(tǒng)拉升到高水位可能瞬間把系統(tǒng)壓垮。這時(shí)候我們可以借助 Sentinel 的 WarmUp 流控模式控制通過的流量緩慢增加,在一定時(shí)間內(nèi)逐漸增加到閾值上限,而不是在一瞬間全部放行。這樣可以給冷系統(tǒng)一個(gè)預(yù)熱的時(shí)間,避免冷系統(tǒng)被壓垮。
- 利用 Sentinel 的勻速排隊(duì)模式進(jìn)行“削峰填谷”,把請(qǐng)求突刺均攤到一段時(shí)間內(nèi),讓系統(tǒng)負(fù)載保持在請(qǐng)求處理水位之內(nèi),同時(shí)盡可能地處理更多請(qǐng)求。
- 利用 Sentinel 的網(wǎng)關(guān)流控特性,在網(wǎng)關(guān)入口處進(jìn)行流量防護(hù),或限制 API 的調(diào)用頻率。
阿里云微服務(wù)解決方案
在阿里云上提供了一款完全遵循 OpenSergo 微服務(wù)標(biāo)準(zhǔn)的企業(yè)級(jí)產(chǎn)品 MSE,MSE 服務(wù)治理的企業(yè)版中的流量治理能力我們可以理解為是一個(gè)商業(yè)化版本的 Sentinel ,我們也簡單總結(jié)了一下 MSE 流量治理與社區(qū)方案在流控降級(jí)與容錯(cuò)場景下的一個(gè)能力對(duì)比。
下面我將基于 MSE 來演示一下,如何通過流量控制與熔斷降級(jí)來保護(hù)我們的系統(tǒng),可以從容地面對(duì)不確定性的流量以及一系列不穩(wěn)定的場景。
- 配置流控規(guī)則
我們可以在監(jiān)控詳情頁面查看每個(gè)接口實(shí)時(shí)的監(jiān)控情況。
我們可以點(diǎn)擊接口概覽右上角的“新增防護(hù)規(guī)則”按鈕,添加一條流控規(guī)則:
我們可以配置最簡單的 QPS 模式的流控規(guī)則,比如上面的例子即限制該接口每秒單機(jī)調(diào)用量不超過 80 次。
- 監(jiān)控查看流控效果
配置規(guī)則后,稍等片刻即可在監(jiān)控頁面看到限流效果:
被拒絕的流量也會(huì)返回錯(cuò)誤信息。MSE 自帶的框架埋點(diǎn)都有默認(rèn)的流控處理邏輯,如 Web 接口被限流后返回 429 Too Many Requests,DAO 層被限流后拋出異常等。若用戶希望更靈活地定制各層的流控處理邏輯,可以通過 SDK 方式接入并配置自定義的流控處理邏輯。
總結(jié)
流控降級(jí)與容錯(cuò)是我們?cè)O(shè)計(jì)穩(wěn)定的微服務(wù)系統(tǒng)時(shí)不得不考慮的場景,如果我們?cè)O(shè)計(jì)每一套系統(tǒng)都要花許多心思來設(shè)計(jì)系統(tǒng)的流控降級(jí)與容錯(cuò)能力,這將會(huì)成為讓我們每一個(gè)開發(fā)者都頭疼的問題。那么我們接觸與設(shè)計(jì)了那么多系統(tǒng)的流控降級(jí),有沒什么通用的場景、最佳實(shí)踐、設(shè)計(jì)標(biāo)準(zhǔn)與規(guī)范乃至參考實(shí)現(xiàn)可以沉淀的?
本文從場景出發(fā)簡單介紹了 OpenSergo 的流量控制與熔斷保護(hù)標(biāo)準(zhǔn),同時(shí)也介紹了 Sentinel 流量防護(hù)的背景和手段,最后通過示例來介紹如何利用 MSE 服務(wù)治理的流量防護(hù)能力來為 您的應(yīng)用保駕護(hù)航。