天天看點

穩定性實踐:限流降級

本周我們繼續來讨論穩定性實踐的内容。在現實情況下,當面對極端的業務場景時,瞬時的業務流量會帶來大大超出系統真實容量的壓力。

為了應對,前面我們介紹了容量規劃方面的實踐經驗。不過,我們不會無限度地通過擴容資源來提升容量,因為無論從技術角度,還是從成本投入角度,這樣做都是不劃算的,也是不現實的。

是以,我們通常采取的政策就是限流降級,以保障承諾容量下的系統穩定;同時還有業務層面的開關預案執行,峰值時刻隻保障核心業務功能,非核心業務功能就關閉。 今天我們就先來介紹一下限流降級的解決方案。

什麼是限流和降級

首先,我們先梳理清楚限流和降級的概念,明白它們會發揮怎樣的作用,這樣才便于我們了解後續的解決方案。

限流,它的作用是根據某個應用或基礎部件的某些核心名額,如QPS或并發線程數,來決定是否将後續的請求進行攔截。比如我們設定1秒QPS門檻值為200,如果某一秒 的QPS為210,那超出的10個請求就會被攔截掉,直接傳回約定的錯誤碼或提示頁面。

降級,它的作用是通過判斷某個應用或元件的服務狀态是否正常,來決定是否繼續提供服務。以RT舉例,我們根據經驗,一個應用的RT在50ms以内,可以正常提供服務,一旦超 過50ms,可能就會導緻周邊依賴的報錯或逾時。是以,這時我們就要設定一個政策,如果應用的RT在某段時間内超過50ms的調用次數多于N次,那該應用或該應用的某個執行個體 就必須降級,不再對外提供服務,可以在靜默一定時間後(比如5s或10s)重新開啟服務。

這裡再特别說一下降級,今天我們講的内容可以了解為服務降級,後面我會介紹業務開關,可以了解為業務降級。這裡隻是叫法不同,不同的人有不同的了解,是以我們在讨論概念時,還是盡量回到我們要解決的問題和場景上來,上下文保持一緻了,在觀點和思路上也更容易達成一緻。

講到這裡,再提個問題,我們講的降級,和熔斷這個概念是什麼關系?你不妨停下來,按照我們剛剛講過的思路思考一下。

常見的限流解決方案

我們先看幾種常見的限流類型。

第一類,接入層限流。

作為業務流量的入口,我們限流的第一道關卡往往會設定在這裡,而且接入層限流往往也是最有效的。這裡又有兩類解決方案,根據接入層所使用的技術方案而定。

1.Nginx限流

Nginx或其開源産品是最常用的Web伺服器,我們使用的是TEngine。對于一個Web類應用,如Web頁面或H5頁面,我們通常會将限流政策增加到這一層,會設定QPS、并發數以 及CPU的Idle作為限流名額。Nginx有對應的函數接口,可以擷取到以上名額資訊,然後通過Lua腳本實作限流的邏輯,并作為TEngine的插件安裝即可。

2.API路由網關模式

對于用戶端模式的接入,我們使用了API路由網關模式,一方面可以更方面地管理用戶端與服務端的連結,另一方面也可以通過配置的方式管理服務接口,這裡的服務管理會複用到 微服務架構的配置中心,并實作相應的路由政策。對于QPS和并發限流,直接在配置中心中進行配置即可。

第二類,應用限流。

這一類的限流政策跟上面API路由網關模式的限流相似,同樣是依賴配置中心管理,限流邏輯會配套服務化的架構完成。

第三類,基礎服務限流。

主要針對資料庫、緩存以及消息等基礎服務元件的限流而設定。同樣,限流邏輯會配套分布式資料庫中間件,緩存或消息的架構來實作。

講到這裡,我來解釋幾個關鍵的技術點。

資源和政策。資源是我們要進行限流的對象,可能是一個應用,或者一個方法,也可能是一個接口或者URL,展現了不同的限流粒度和類型。政策就是限流的規則,比如下面我們 要提到的QPS和并發數限流。

時間精度。主要指對于QPS、并發數或CPU的門檻值判斷。比如對于QPS,我們就會設定一個QPS時間精度(假設3s),如果低于門檻值則不啟用政策,如果超過門檻值就啟動限流策 略。

名額計數。對于并發限制請求,會統計目前的并發數,1次請求進入到限流子產品加1,等請求結束退出時減1,目前正在處理的請求數就是并發數。對于QPS限流,統計QPS不能按 照秒統計,因為第1s,系統可能就被打挂了,是以QPS得按照毫秒級别去統計,統計的級别越小,性能損耗越大。是以定在10ms~100ms的級别去統計會更平滑一些,比如 将1s切成10份,每一份100ms,一個請求進來肯定會落在某一份上,這一份的計數值加1。計算目前的QPS,隻需要将目前時間所在份的計數和前面9份的計數相加,記憶體裡面需 要維護目前秒和前面2秒的資料。

限流方式。對于Nginx就針對總的請求進行限流即可,但是粒度會比較粗。對于應用層,因為配置中心的靈活性,其限流就可以做得更細化。比如可以針對不同來源限流,也可以 針對去向限流,粒度上可以針對類級别限流,也可以針對不同的方法限流,同時還可以針對總的請求情況限流,這些靈活政策都可以在微服務的配置中心實作。

穩定性實踐:限流降級

Spring AOP。對于Java應用,絕大多數公司都會用到Spring架構,包括我們上面講到的分布式資料庫等元件,也一樣會依賴Spring架構,比如我們用到的MyBatis開源元件。 而Spirng架構中的關鍵技術點,就是IoC和AOP,我們在限流方案的實作上,也會利用到相關技術。簡單來說就是,我們通過配置需要限流的方法作為AOP的切入點,設 定Advice攔截器,在請求調用某個方法,或請求結束退出某個方法時,進行上述的各種計數處理,同時決定是否要進行限流,如果限流就傳回約定好的傳回碼,如果不限流就正常 執行業務邏輯。基于AOP這樣一個統一的技術原理,我們就可以開發出與業務邏輯無關的限流元件,通常會在對外的服務調用、資料庫調用、緩存調用、消息調用這些接口方法上 設定預設的切面,并在業務代碼運作時注入,這樣就可以做到對業務透明,無侵入性。

Web類型的限流。對于Web類型URL接口限流,我們就利用Servlet的Filter機制進行控制即可。

控制台。上面我們講了各種配置和政策,如果都是通過人工來操作是不現實的,這時就需要開發對應的限流降級的控制台,将上述的各種配置和政策通過界面的方式進行管理,同 時在配置完成之後,能夠同步到對應的服務執行個體上。比如對于Nginx,當一個政策配置完成後,就要同步到指定的伺服器上生成新的配置檔案并Reload。對于配置中心模式的策 略,也就是Spring AOP模式的限流,在控制台上配置完成後,就要将配置值同步更新到配置中心裡,同時再通過運作時的依賴注入,線上上運作的業務代碼中生效。

整體簡化的示意圖如下:

穩定性實踐:限流降級

限流降級的難點

上面整體介紹了限流降級的解決方案,我們可以看到涉及到很多新概念,各種不同的限流類型,同時還有比較複雜的技術細節,是以要清晰地了解這些概念。

對于降級,主要是針對RT來進行判斷,它的整個技術方案沒有限流這麼複雜,且思路上跟限流是相似的,是以我們就不再單獨介紹降級的技術方案了。

從整個建設過程來看,我的體會是,限流降級的難點和關鍵還是在于整體技術棧的統一,以及後期對每個應用限流降級資源政策的準确把握和配置。

我們先來看整體技術棧的統一,這其實也就是我們在專欄最開始就講到的标準化建設。這裡我們會基于一個統一的技術棧進行限流降級方案的設計,要求有統一的Web伺服器類型。對服 務化架構、各類分布式架構以及代碼開發架構(如Spring),這些都要有很明确的要求。如果這裡面有某些應用使用的架構不同,那麼這套統一的方案就無法推廣落地。

我們在實際推廣過程中就遇到很多類似的問題,導緻大量的時間耗費在技術棧統一上,甚至會要求業務代碼做出改變和調整,代碼上線運作後再進行統一,這個代價是非常大的。

這也是為什麼我們在一開始就非常強調标準化的重要性。這裡我們再強調一下标準化,再來複習一下以應用為核心的運維體系的思維導圖。

穩定性實踐:限流降級

再來看對應用的限流降級資源政策的把握,這個就需要對應用和業務有深入的了解。比如開發人員要非常清楚哪些接口是核心接口,它的來源和去向有哪些;哪些來源是核心的,哪些是 非核心的;如果要限流,需要對哪些接口限流,同時要重點保障哪些接口等等。