技術風口上的限流


PART. 1

站在風口上


站在風口上的技術“服務網格”是什麼?可以將它比作是應用程序或者說微服務間的 TCP/IP,負責服務之間的網絡調用、限流、熔斷和監控。


對於編寫應用程序來說一般無須關心 TCP/IP 這一層(比如通過 HTTP 協議的 RESTful 應用),同樣使用 Service Mesh 也就無須關心服務之間的那些原本通過服務框架實現的事情,只要交給 Service Mesh 就可以了。


Service Mesh 作爲 sidecar 運行,對應用程序來說是透明,所有應用程序間的流量都會通過它,所以對應用程序流量的控制都可以在 Serivce Mesh 中實現,這對於限流熔斷而言就是一個天然的流量劫持點。


如今螞蟻 80% 以上的應用都已經完成了 Mesh 化,Mesh 統一限流熔斷的建設自然是水到渠成了。


服務網格(Service Mesh)是處理服務間通信的基礎設施層。它負責構成現代雲原生應用程序的複雜服務拓撲來可靠地交付請求。


在實踐中,Service Mesh 通常以輕量級網絡代理陣列的形式實現,這些代理與應用程序代碼部署在一起,對應用程序來說無需感知代理的存在。



相較於傳統的限流組件,Mesh 限流具備很多優勢,在研發效能和研發成本上都取得了明顯的收益


MOSN 架構天然的流量劫持讓應用無需逐個接入 SDK


也無需爲特定語言開發不同版本的限流組件


- 限流能力的升級也無需業務同步升級



「背景業務」



在 Mesh 統一限流實現前,螞蟻集團內部存在多個不同的限流產品,分別提供不同的流量控制策略:


不同類型的流量(SOFARPC、無線網關 RPC、HTTP、消息等)限流配置分散在不同的平臺,由不同的團隊維護,產品質量和文檔質量參差不齊,學習成本高、使用體驗差。


不同的限流策略需要接入不同的 SDK,引入很多間接依賴,安全漏洞引起的升級頻繁,維護成本高。


不僅在開發建設上存在不必要的人力投入,也給業務方使用造成了困擾和不便。


另一方面,我們的業務規模越來越大,但大量服務仍在使用最簡單的單機限流策略。沒有通用的自適應限流、熱點限流、精細化限流、集羣限流等能力。


因爲限流能力缺失、限流漏配、錯誤的限流配置等問題引起的故障頻發。


Mesh 架構下,sidecar 對流量管理具備天然的優勢,業務無需在應用中接入或升級限流組件,中間件也無需針對不同的技術棧開發或維護多個版本的限流組件。


在目前 Service Mesh 螞蟻內部大規模接入完成的背景下,將多種不同的限流能力統一收口至 MOSN,將所有限流規則配置統一收口至“統一限流中心”,可以進一步提高 MOSN 的流量管理能力,同時大幅降低業務限流接入及配置成本。


基於這樣的背景下,我們在 MOSN 中進行了統一限流能力建設。



PART. 2

站在巨人肩膀上


在建設統一限流能力的過程中,我們調研了許多成熟的產品,既包括我們自己的 Guardian、Shiva、都江堰等,也包括開源社區的 concurrency-limits 、Hystrix、Sentinel 等產品。


我們發現阿里巴巴集團開源的 Sentinel 是其中的集大成者。


之前我們在打造 Shiva 的過程中也與集團 Sentinel 的同學進行過交流學習,他們也正在積極建設 Golang 版本的 sentinel-golang。


MOSN 作爲一款螞蟻自研的基於 Golang 技術建設的 Mesh 開源框架,如果搭配上 Sentinel 的強大的流控能力和較爲出色的社區影響力,簡直是強強聯合、如虎添翼、珠聯璧合、相得益彰...啊。


不過 Sentinel 對於我們而言也並不是開箱即用的,我們並不是完全沒有歷史包袱的全新業務,必須要考慮到螞蟻的基礎設施和歷史限流產品的兼容,經過我們調研發現主要存在幾個需要投入建設的點:


1.  控制面規則下發需要走螞蟻的基礎設施

2. Sentinel-golang 的單機限流、熔斷等邏輯,和我們之前的產品有較大差異

3. 集羣限流也要用螞蟻的基礎設施實現

4. Sentinel 自適應限流粒度太粗,螞蟻有更加精細化的需求

5. 日誌採集方案需要調整


綜合考慮後,我們決定基於 Sentinel 做擴展,站在巨人的肩膀上打造螞蟻自己的 Mesh 限流能力。


基於 Sentinel 良好的擴展能力,我們對單機限流、服務熔斷、集羣限流、自適應限流等都做了螞蟻自己的實現,也將部分通用的改動反哺到了開源社區,同時配套建設了統一的日誌監控報警、統一限流中心。



最終我們在 MOSN 裏將各種能力都完成了建設,下表展示了 MOSN 限流和其他限流組件的能力對比:




PART. 3

奧卡姆剃刀


Pluralitas non est ponenda sine necessitate.

如無必要,勿增實體 



一個限流策略就配套一個 SDK 和一個管理後臺七零八落,交互體驗參差不齊,文檔和操作手冊質量也良莠不齊,交由不同的團隊維護和答疑,如果你全都體驗過一遍一定會深惡痛絕。


而 Mesh 統一限流的核心目的之一就是砍掉這些東西,化繁爲簡,降低業務同學的學習成本和使用成本,降低我們自己的維護成本。


- 流量控制的能力全部集成到 MOSN 裏,取衆家之長,去其糟粕


- 流量控制的管控臺全部收口到統一限流中心


這應該是我們造的最後一個限流輪子了吧




PART. 4

青出於藍而勝於藍


上文提到了我們是站在 Sentinel 的肩膀上實現的 Mesh 統一限流,那我們又做了什麼  Sentinel 所不具備的能力呢?


實際上我們對幾乎所有的 Sentinel 提供的限流能力都做了一套自己的實現,其中也有不少的亮點和增強。


下面分享幾個我們的技術亮點。


 自適應限流 


- 對於業務同學而言逐個接口做容量評估和壓測迴歸費時費心,有限的精力只能投入到重點的接口保障上,難免會漏配一些小流量接口的限流。


- 而負責質量和穩定性保障的同學經常在故障覆盤時看到各種漏配限流、錯配限流、壓測故障、線程阻塞等造成的各種故障。


我們希望即使在系統漏配錯配限流的情況下,在系統資源嚴重不足時 MOSN 能夠精準的找到導致系統資源不足的罪魁禍首,並實時根據系統水位自動調節異常流量。


在此需求背景下我們實現了一套符合成熟雲原生定義的自檢測、自調節的限流策略。



自適應限流的實現原理並不複雜,樸素的解釋就是,觸發限流後實時檢測系統整體水位,同時秒級按比例調節流量


核心邏輯如下:


- 系統資源檢測:秒級檢測系統資源佔用情況,如果連續超過閾值 N 秒(默認 5 秒)則觸發基線計算,同時將壓測流量阻斷騰挪出資源給線上業務使用;


- 基線計算:將當前所有的接口統計數據遍歷一遍,通過一系列算法找出資源消耗大戶,再把這些大戶裏明顯上漲的異常流量找出來,把他們當前的資源佔用做個快照存入基線數據中;


- 基線調節器:將上一步驟存入的基線數據根據實際情況進行調整,根據系統資源檢測的結果秒級的調整基線值,仍然超過系統閾值則按比例下調基線值,否則按比例恢復基線值,如此反覆;


- 限流決策

系統流量不斷經過自適應限流模塊,會嘗試獲取該接口的基線數據,如果沒有說明該接口未被限流直接放過;

如果有基線數據則對比當前併發是否超過基線數據,根據實際情況決策是否允許該請求通過。



這套自主實現的自適應限流有如下幾點優勢:


- 省心配置無代碼入侵,極簡配置;


- 秒級調控:單機自檢測自調節,無外部依賴,秒級調整水位;


- 智能識別:壓測資源騰挪、異常流量識別等特性;


- 精準識別:相較於其他的自適應限流技術,例如 Netflix 的 concurrency-limits,Sentinel 基於 BBR 思想的系統維度自適應限流等,精準識別能做到接口維度,甚至參數或者應用來源維度的自適應限流。


 集羣限流 


在介紹集羣限流之前,我們先簡單思考一下單機限流在什麼場景下會存在不足。


單機限流的計數器是在單機內存中獨立計數的,獨立的機器之間的數據彼此不關心,並且每臺機器通常情況下采用了相同的限流配置。


考慮一下以下場景:


-假設業務希望配置的總限流閾值小於機器總量,例如業務有 1000 臺機器,但希望限制 QPS 總量爲 500,均攤到每臺機器 QPS<1,單機限流的值該怎麼配置呢?


- 假設業務希望限制 QPS 總量爲 1000,一共有 10 臺機器,但分佈到每臺機器上的業務流量不是絕對均勻的,單機限流的值又該怎麼配置呢?


計算機科學領域的任何問題都可以通過增加一個間接的中間層來解決,我們很容易想到通過一個統一的外部的計數器來存儲限流統計數據,這就是集羣限流的基本思想。



不過每個請求都去同步請求緩存存在一些問題:


-如果請求量很大,緩存的壓力會很大,需要申請足夠多的資源;


-同步請求緩存,尤其是在跨城訪問緩存的情況下,耗時會明顯增加,最壞情況下 30ms+ 的跨城調用耗時可不是每個業務都能接受的。


-我們在集羣限流中提供了同步限流和異步限流兩種模式。針對流量很大或耗時敏感的情況我們設計了一個二級緩存方案,不再每次都請求緩存,而是在本地做一個累加,達到一定的份額後或者達到一定時間間隔後再諮詢緩存,如果遠端份額已扣減完,則將阻止流量再進入,直到下一個時間窗口後恢復。異步限流模式在大流量場景下對集羣限流的性能和精度實現了儘可能的平衡。




PART. 5

精細化限流


傳統的接口粒度的限流可能無法滿足某些複雜的業務限流需求,例如同一個接口業務希望根據不同的調用來源進行區別對待,或者根據某個業務參數的值(例如商戶 ID、活動 ID 等)配置獨立的限流配置。


精細化限流就是爲了解決這樣的複雜限流配置而設計的。



我們先梳理一下業務同學可能希望支持的條件有哪些,基本上概括起來有幾類:


1. 按業務來源

例如 A 應用對外提供的服務被B、C、D 三個系統調用,希望只對來自 B 的流量做限制,C、D 不限制。


2. 按業務參數值

例如按 UID、活動 ID、商戶 ID、支付場景 ID 等。


3. 按全鏈路業務標¹

例如“花唄代扣”、“餘額寶申購支付”等。


[注1]:全鏈路業務標是根據業務配置的規則生成的標識,該標識會在 RPC 協議中透傳,達到跨服務識別業務來源的目的。


更復雜的場景下,可能上述條件還有一些邏輯運算關係,例如業務來源是 A 並且活動 ID 是 xxx 的流量,業務標是 A 或者 B 並且參數值是 xxx 等。


上面這些條件,有的是可以直接從請求的 header 中獲取到的,例如業務來源應用、來源 IP 等可以直接獲取到,我們稱之爲基本信息,而業務參數和全鏈路標識則不是每個應用都有,我們稱之爲業務信息。


流量條件規則就是讓基本信息、業務信息等支持基本的邏輯運算,根據運算結果生成獨立的子資源點。



根據業務配置的條件規則將流量拆分成若干個子資源點,再針對“子資源點”配置獨立的限流規則,從而實現了精細化限流的需求。


 Do More 

實現了限流熔斷的能力大一統之後,我們還可以做什麼?下面跟大家聊一下我們的一些思考。


 限流 X 自愈 

在實現了自適應限流後,我們很快在集團內進行了大規模的推廣覆蓋,幾乎每天都有自適應限流觸發的 case,但我們發現很多時候自適應限流觸發都是單機故障引起的。數十萬容器在線上運行,難免偶爾會出現單機抖動。


限流解決的是總體的容量問題,對於強依賴的服務限流後業務仍然表現爲失敗,更好的辦法是將流量快速轉移到其他健康機器。



傳統的自愈平臺都是通過監控發現機器故障,繼而執行後續的自愈動作,監控通常會有 2~3 分鐘的數據延遲,如果在自適應限流觸發後立即上報數據給自愈平臺,自愈平臺再進行判斷確認是否是單機問題,隨後執行自愈處理,則可以提高自愈的實效性,進一步提高業務可以率。


同樣的思路,在自愈平臺收到自適應限流觸發的消息後如果發現不是單機問題而是整體容量問題,則可以進行快速擴容實現容量問題自愈。


 限流 X 降級中臺 

當業務強依賴的服務發生故障時,限流保障的是服務不會因爲容量問題導致服務雪崩,並不能提高業務可用率。單機故障可以做流量轉移,但整體的故障發生時該怎麼辦呢?


更好的辦法是將請求轉發到提前準備好的降級服務中



基於 Serverless 平臺實現的降級中臺,可以將降級的一些通用邏輯下沉到基座中(例如:緩存記賬、異步恢復等),業務可以根據實際需求實現自己的 Serverless 業務降級模塊,這樣即使在服務完全不可用的狀態下,MOSN 仍然可以將請求轉發到降級服務中,從而實現更高的業務可用率。



「總 結」


隨着 MOSN 限流能力的逐步豐富與完善以及未來更多 Mesh 高可用能力建設,MOSN 逐漸成爲了技術風險和高可用能力基礎設施中重要的一環。


以上就是我們 Mesh 限流實踐與落地的一些經驗分享,希望大家能通過這些分享對 Service Mesh 能有更深入的認識和了解,也期待大家更多的關注 MOSN ,讓我們能得到更多社區的反饋,幫助我們做得更好。


希望大家一起努力, 共同進步。





開源項目 MOSN 核心成員「張稀虹」在 8 月 11 日 SOFAMeetup 「成都站」進行了《技術風口上的限流》分享帶領大家瞭解 Mesh 限流熔斷未來的探索方向。


一起期待下次 Meetup 嘉賓們精彩的分享吧~



   本週推薦閱讀  


螞蟻智能監控


深度 | 字節跳動微服務架構體系演進


2021 年雲原生技術發展現狀及未來趨勢


螞蟻集團 SOFATracer 原理與實踐



本文分享自微信公衆號 - 金融級分佈式架構(Antfin_SOFA)。
如有侵權,請聯繫 [email protected] 刪除。
本文參與“OSC源創計劃”,歡迎正在閱讀的你也加入,一起分享。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章