TSF微服務治理實戰系列(三)——服務限流

語言: CN / TW / HK

導語

大家應該都有去遊樂園遊玩的經歷,其實服務限流與遊樂園人流管理很相似。比如每一個遊樂園所能承載的標準遊客總數是大概確定的,當遊樂園承載的遊客數量超出了標準數量,遊客在遊玩的時候就會出現遊玩路線人潮擁擠(請求擁堵處理慢)、熱點遊樂設施排隊久(熱點API過載)、餐品飲料供應缺貨(資料庫連線池不足)等情況,更有在重大節日時由於人數太多導致的踩踏事故(服務宕機導致的雪崩)。

服務限流其實就是一種應對超額流量的保護機制,當業務流量超出系統能夠承載的上限時,快速處理超額的請求(如快速失敗),防止超額的請求繼續爭搶/佔用系統資源。本節將簡單介紹服務限流針對的問題域、設計原則及TSF在服務限流方面的能力和使用場景。

作者簡介

崔凱                                                                        

騰訊雲 CSIG 微服務產品中心產品架構師

多年分散式、高併發電子商務系統的研發、系統架構設計經驗,擅長主流微服務架構技術平臺的落地和實施,目前專注於微服務架構相關中介軟體的研究推廣和最佳實踐的沉澱,致力於幫助企業完成數字化轉。

限流概述

社會的優勢資源總是稀缺的,稀缺的資源又總是讓人蜂擁而至。比如在12306搶春節回家的票,就是一場全國返鄉人民都會參與的秒殺活動,如此大規模的流量讓春節回家難這件事年年上熱搜,那麼具體是什麼技術原因導致的呢?

  • 由於回家心切而過於激動的去重複重新整理搶票頁面(海量併發讀);

  • 票放出的時間和庫存都是固定的,所有人會在同一時間點選購買按鈕(海量併發寫);

  • 很多人就想搶到好時間段的票,就去買了搶票機器人(流量放大);

  • 系統沒有做多級快取、資料精簡、訊息佇列解耦等(自身架構問題)。

上述原因只是一部分主要影響因素,在遭遇大流量時,如果沒有適當的防禦機制,輕則系統響應緩慢、頻繁報錯,重則系統癱瘓。其實每年的車票就那麼多,與其讓所有人都花費額外的資源去爭搶,不如早早讓使用者知道賣光了,快速失敗。

服務限流就是為了保護後端服務和資料不被大流量擊垮而設計,當發生流量浪湧時,讓例項能在最大有效負荷執行,而不會超過負載導致崩潰。

能力模型

產品的能力再炫酷,也需要落地在問題場景中才能產生價值。那麼針對上述問題場景,服務限流可以使用哪些能力模型來解決問題呢?小編認為至少需要具備如下幾種主要的能力:全侷限流從整體限定服務容量(包括閘道器和業務服務),標籤限流進行精準的細粒度控制,動態調節讓服務可以根據自身狀態自適應調整流量。

  • 全侷限流

從每個服務的視角整體把控服務容量,並且不區分呼叫請求的來源。所有流經被呼叫服務的請求都將被統計計數,一旦統計數字超過了全侷限流配置的閾值,整個服務會拒絕超過配額的請求。

  • 標籤限流

通過標籤化能力,將上游請求進行分類,針對不同種類的請求配置不同的限流規則,同時限流規則甚至可以精確控制到每個請求上。最終通過多個限流規則的組合,實現針對服務中不同API、不同流量來源的組合型防護。

  • 動態調節

每個單個例項基於自身情況,通過演算法動態調整流經服務的請求數量,保證在不超過每個例項最大吞吐量的情況下,使得資源被有效的充分利用。

限流演算法

限流常見的演算法包括固定視窗演算法、滑動視窗演算法、漏斗演算法、令牌桶演算法等,演算法的內容在網際網路已有諸多描述,小編不再贅述,只簡要對比各演算法優劣點。

演算法名稱

優點

缺點

固定視窗演算法

程式碼邏輯簡單易實現

視窗臨界點流量翻倍問題

滑動視窗演算法

避免了臨界點翻倍問題

超過臨界值後沒有緩衝機制

漏斗演算法

固定速率保證穩定性,有一定緩衝

瞬時流量不能在短時間內立即被處理

令牌桶演算法

兼顧緩衝機制和瞬時流量處理

初次啟動時令牌數量需優化

其實每種演算法都有使用的場景,比如滑動視窗演算法,實現起來簡單易懂,比較適合簡單的限流場景;漏斗演算法由於其流出速率恆定的特點,更偏重於保護下游服務,減少大流量對下游服務或三方平臺的衝擊;令牌桶演算法更注重保護應用自身,同時滿足了對請求進行緩衝和瞬時大流量問題的平衡。

另外在微服務體系中,限流更多的落地方式是大量微服務共用一套分散式限流框架,方便統一配置、統一運維、統一管理。TSF服務限流通過令牌桶演算法,實現了一整套分散式服務限流的管控機制,使得應用在引用TSF-SDK後,開箱即用的獲得分散式限流的能力。

上圖為TSF服務限流架構示意圖,首先支撐端限流中心基於使用者的限流配置,計算得出服務中每個例項單位時間(1S)內應經過的最大的請求數配額(單位時間內最大流經請求數),並將該配額下發到每一個對應的服務例項中(各例項配額並不相同)。其次TSF-SDK會將單位時間內的統計資料上傳到限流中心,供限流中心計算下一個單位時間應當下發的配額。最後,在當前單位時間內,當超過配額的請求到達例項後,就會被攔截並返回HTTP 429(Too Many Requests)錯誤。

簡單總結下,TSF服務限流通過SDK實時上報的例項統計資料,使得限流中心元件可以動態的調整每個例項當前的配額數值。例如一個服務有4個例項,全侷限流配置為100QPS,則每個例項初始時各得25的配額。但當某一個例項發生阻塞,該阻塞例項會通過上報資料被限流中心感知,之後分配給阻塞例項的配額會適當減少(如5),並適當增加其它例項的壓力。阻塞例項在低流量壓力情況下逐漸恢復後,限流中心可以捕獲到例項的壓力已經減小,又會重新調整每個例項的配額到基本均分狀態。

限流原則

以下圖為例是一個通用的WEB系統架構,流量通過APP、PC、第三方平臺等不同的入口經過閘道器的安全鑑權和攻擊防護,通過CLB負載到每一個微服務閘道器暴露的對外API上,再由微服務閘道器將請求分發到不同的後端服務中。

從設計服務限流的視角,我們不應僅僅將限流的動作侷限在某一些服務上,需儘量從整個架構的視角來分析,核心思想是 “分層分級”

分層是指請求從閘道器進入到返回使用者,經過了閘道器、LB、微服務閘道器、後端服務等多層環節,我們其實可以在請求流經的每一層進行快取,提前減少不安全的(如惡意攻擊)、非必要的(如靜態資源)的請求直接透傳到後端服務和DB,避免寶貴資源被浪費。

分級是指使用者請求會不同程度的分散到閘道器、前臺服務、中臺服務中的各個API中,那麼根據服務是否核心、API是否熱點等不同的特徵,可以對各微服務進行分級。例如對於入口型的微服務閘道器或者BFF聚合服務,更適合配置針對閘道器/服務的全侷限流;核心服務的核心API更適合配置針對API的標籤限流;針對單個服務中API數量較多的情況,單獨配置API可能不切實際,更適合通過全侷限流配置一個該服務QPS合計的預估峰值。

另外,在配置限流之前,對微服務的歷史資料(QPS均值和峰值、PV/UV等)、可蒐集到的已有業務資料(使用者數、庫存、商家、預估流量等)、資源消耗情況(伺服器配置和數量、CPU記憶體與流量的對應關係等)提前參照,也是重要的準確評估流量的手段。

壓測方法

在進行服務限流配置之前,首先要了解服務所處的層級、服務的預估容量等情況,這就需要一套完整的壓測方法來支撐。以下為一些專案中壓測的落地經驗,供各位讀者參考。

首先,在準備壓測前先了解一些壓測的“潛規則”:

  • 儘量保證壓測環境與生產環境的伺服器配置、數量、型號保持一致;

  • 影響壓測的因素包括不限於:例項數量、伺服器配置、應用配置、網路環境等;

  • 通過改變上述某一個影響壓測的因素,觀察壓測資料的變化趨勢,而不要同時改變多個;

  • 當服務中待壓測介面較多時,優先壓測核心介面,因為時間總是有限;

  • 常見可能的拐點為,在併發壓力增大時QPS持平或不升反降、應用報錯率飆高、響應耗時飆高等;

  • 長鏈路壓測過程中儘量保證被壓服務的下游依賴服務資源相對空閒,如consumer->provider且consumer為被壓服務時,需保證provider並無明顯壓力;

  • 可先通過mock的方式壓測自身的服務容量,再進行全鏈路壓測。

其次,對於服務中單個API的壓測,目的在於確認每個API在不同場景下的QPS。對於全鏈路的壓測,是以模擬真實業務鏈路為前提,將服務中單個API進行串聯後,確認鏈路上所有相關API的QPS,兩種場景是從不同的視角出發的。全鏈路壓測的問題在於,當上遊服務的API成為瓶頸時,下游API的效能再好也無從發揮且不易覺察,而單個API的壓測恰好彌補了這一點。同時,基於對上下游API和整體鏈路的QPS分析比對,可以有效的減少鏈路中不必要的資源浪費。所以在壓測用例中可以嘗試如下用例組合:

  • 服務單例項:通過單例項壓測,瞭解每一個單獨的部署單元的介面/服務容量;

  • 服務多例項:單例項前增加一層客戶端負載均衡,與單例項的壓測資料對比,觀察對介面的影響;

  • 閘道器單例項:同服務單例項,瞭解閘道器單例項容量;

  • 閘道器多例項:同服務多例項,瞭解閘道器多例項容量;

  • 閘道器+服務:通過增加閘道器,觀察閘道器路由對介面的影響;

  • CLB+閘道器+服務:通過增加CLB,觀察CLB對介面的影響;

  • CLB+閘道器+服務A+服務B+服務C:通過全鏈路壓測,瞭解真實業務鏈路情況下服務執行的狀態。

增加例項並不會線性增加容量,當進行服務容量評估時,需要以實際壓測結果作為參考。另外,針對壓測數值要留有一定的安全空間作為緩衝,通常限流配置的閾值需根據例項平均CPU在70-80%左右時的QPS表現來確定。如閘道器壓測時QPS為10000時CPU跑滿且響應耗時開始顯著增加(效能拐點),同時在QPS為7500時,各例項CPU平均數值為70%,則配置限流閾值應為7500(服務API同理)。具體如下表所示:

應用型別

CPU100%壓測數值

實際配置數值

閘道器

10000

7500

服務

200

150

在壓測過程中mock介面可能需要模擬真實呼叫的隨機延時,可從業務分支拉出專門用於壓測的壓測分支,並對待壓測介面進行mock修改,mock程式碼內容可參考如下程式碼的思路編寫:

public String mockResponseTime() throws InterruptedException {
int responseTime = 0;
Random randomProportion = new Random();
Random randomOffset = new Random();
int proportion = randomProportion.nextInt(100);
int offset = randomOffset.nextInt(5);
if(proportion < 80){
responseTime = calcTime(50,offset);
} else if(proportion >=80 && proportion < 95){
responseTime = calcTime(200,offset);
}else {
responseTime = calcTime(400,offset);
}
Thread.sleep(responseTime);
return "OK";
}


private int calcTime(int milliSecond,int offset){
Random random = new Random();
if(random.nextInt(100) % 2 == 0){
return milliSecond + offset;
}
return milliSecond - offset;
}

TSF限流

配置方法

TSF的服務限流包括兩種配置方式:全侷限流、標籤限流。全侷限流針對整個微服務的所有請求,標籤限流可以根據上游流量攜帶的系統標籤或自定義標籤進行細粒度管控。限流的配置主要通過配置時間和請求數來控制。

一個服務可以有多個同時生效的限流規則,當一個請求被多個限流規則約束時,則僅當所有作用規則都判通過時才會放行。且請求通過後每個作用規則的 通行請求數+1 。若被一個規則攔截,則針對該規則的 限流請求數+1

此外,TSF彈性伸縮機制可以通過觀測QPS、響應時間、CPU使用率、記憶體使用率的監控資料,對服務例項數量進行動態水平擴縮,安全有效的減少運維成本。當瞬時大流量來臨時,啟用彈性伸縮組內的預留資源,儘可能承接使用者的業務請求。配合容器自身快速彈性伸縮的特性,可以實現服務的秒級擴縮容。

配置彈性伸縮規則時注意CPU利用率、記憶體利用率、請求QPS、響應時間的判斷取的都是關聯部署組內所有例項對應指標的 平均值 。冷卻時間是指在完成一次擴縮容之後,會間隔一段時間(即冷卻時間),期間並不會再次判斷和觸發彈性伸縮。

不過,注意彈性伸縮與服務限流組合使用的場景。第一,彈性伸縮與限流同時監控QPS時,彈性伸縮的規則生效時間需要持續至少1分鐘以上才會生效,而限流需要在1秒內完成限制,會導致QPS在超限後立刻被限流而達不到彈性擴容的條件或者已經超限至少1分鐘後才開始限流;第二,彈性伸縮的目的在於動態改變例項的數量,而限流規則是根據固定的例項數量而配置的,當發生彈性擴縮容後,也就意味著原有配置的限流規則失效並需要更新。

電商大促

每年的雙11大促是商家和使用者們的狂歡,但細心的讀者朋友可能會發現,其實不止11月,每個月電商平臺都會招攬商家們搞促銷。即使是為了應對3.15這種每年都會查處商家的晚會,各大平臺仍會樂此不疲。所以,對於有一定規模的電商平臺而言,系統為了應對每月促銷所帶來的巨大流量,限流幾乎是研發團隊的一項日常操作。

針對電商大促的場景,TSF可以通過全侷限流+標籤限流的組合來管理流量。首先,假設目前僅完成了核心服務consumer-demo的服務部署,未進行任何的限流配置。

在日常流量大幅波動時,核心服務沒有自保機制,這是業務不能接受的,所以需要對核心服務新增限流規則。在經過壓測及歷史資料分析後,預估當前資源配置可支撐的容量為1500QPS,即全侷限流配置每1秒1500個請求作為上限,如下圖所示:

其次,僅配置全侷限流不能針對性解決熱點API超載的問題,那麼可以配合標籤限流針對熱點API進行限制,如下圖所示將某一個熱點API限制在1000QPS以內。

額外補充一點,由於微服務閘道器/閘道器是南北流量的入口,一旦閘道器癱瘓或故障,影響的是所有的業務。如果不在閘道器處新增一定的限流規則,可能會發生請求還沒有流經後端服務,閘道器已經先搞掛了,這樣後端的限流策略根本無從起效。

結語

服務限流相比其他治理手段更容易在落地專案中看到,主要是由於其實現方式比較成熟,同時各行各業中有豐富的落地場景。TSF服務限流的主要價值在於,極少的程式碼改造成本和學習成本、可以統一管理不同語言及框架的限流策略、簡單的控制檯使用方法、免運維的支撐方式,讓使用者可以快速的獲得穩定的服務限流能力。

另外服務限流也需要在未來適應更多的場景,比如跟降級規則的聯動、如何做到更精準的流量預測和流量自適應、如何做到毫秒級限流等。隨著微服務治理實戰系列已經來到了第三章,也希望能更多的得到大家的反饋,一起探索更多的落地場景和方法。

引用

http://cloud.tencent.com/document/product/649/30719

http://cloud.tencent.com/document/product/649/19046

One more thing

近日,Spring Cloud Tencent 於6月14日正式對外開源,作為騰訊開源的一站式微服務框架,Spring Cloud Tencent 實現了 Spring Cloud 標準微服務 SPI ,開發者可以基於 Spring Cloud Tencent 快速開發 Spring Cloud 微服務架構應用。Spring Cloud Tencent 的核心依託騰訊開源的一站式服務發現與治理平臺  Polarismesh ,實現各種分散式微服務場景。

  • 如果你也是 Spring Cloud 的愛好者

  • 如果你的公司正在使用 Spring Cloud 並且有一些好的實踐

  • 如果你的公司正在做微服務技術選型

... ...

請加入我們,你的一個建議、Issue、Pull Request 甚至只是一個小小的 Star 都是對我們最大的支援,也是我們持續迭代的動力。

Github 地址(文末點選「閱讀原文」即可跳轉至該連結):

http://github.com/Tencent/spring-cloud-tencent

掃碼進Spring Cloud Tencent使用者交流群

往期

推薦

掃描下方二維碼關注本公眾號,

瞭解更多微服務、訊息佇列的相關資訊!

解鎖超多鵝廠周邊!

戳原文,檢視更多微服務平臺TSF的資訊!

點個 在看 你最好看