摘要:二現有方案分析目前全局流控方案主要需要解決兩個實現問題全局計數器使用何種存儲全局計數器存儲可以使用,也可以使用。優勢方案減少的訪問量,同時保證流控的準確性。
作者:莫家文,騰訊事務型開發工程師
商業轉載請聯系騰訊WeTest獲得授權,非商業轉載請注明出處。
原文鏈接:http://wetest.qq.com/lab/view/320.html
全新的全局流控實現方案,既解決了目前流控的實現難點,同時保證運行穩定且流控準確的前提下,實現更簡單,部署成本更低,容災能力更強。 該方案組件化之后,可以推廣到別的有需要的部門使用,只需簡單的接入和部署即可獲得全局流控的能力。
一、背景流控作為容災體系中必不可少的一環,在請求量超過系統容量的時候,通過拒絕超量請求的方式,防止服務接口的雪崩和系統掛掉。
目前部門只具備單機流控的能力,隨著業務的增長和系統復雜度的增加,單機流控越來越不能滿足需要,升級流控能力日趨重要。
(一)流控分類升級流控之前,先簡單了解不同流控方式的優缺點:
對比可知,全局流控能能彌補單機流控的缺點,而動態流控又是在全局流控的基礎上做更精細化的流控。
(二)現有方案分析目前全局流控方案主要需要解決兩個實現問題:
1、全局計數器使用何種存儲
全局計數器存儲可以使用redis,也可以使用ckv。
分布式流控很關鍵一點是將流控服務做成原子化。而做流控需要記錄兩個信息,計數和計時。比如全局流控閾值設置了5w/s的值,計數器記錄了當前的請求數(計數),在達到1s時計數器需失效或清零(計時)。
計數和計時要保證原子操作,目前已知的方式有:
1)使用加鎖的方式,比如ckv的cas計數,或者redis+lua技術,但在并發量大的時候,加鎖的性能比較無法保證;
2)使用incr的方式,由于目前redis和ckv的incr都沒過期時間設置,要滿足要求(計數和計時同時原子操作),需改造redis或ckv,使得incr支持過期時間設置,目前已知有改造redis支持過期時間的案例。
2、 如何上報請求
一般統計的方式分兩種:
1) 請求全量上報,這樣要求存儲的訪問能力足夠強大,優點是流控實時性得到保證;
2) 請求定時批量上報,這樣存儲的訪問壓力較小,資源消耗也更少,缺點是流控可能不實時;
一般還需要每臺機器部署agent來完成上報和流控判斷,業務模塊與agent之間要實現通訊。
大體的邏輯結構如下:
注:圖片來自文章《MSDK全局流控介紹》
實現難點:
1)將流控服務做成原子化,目前無論使用redis還是ckv,加鎖方式并發下無法保證性能,原生的incr方式要解決過期時間的問題,需要的技術門檻和開發成本都比較高;
2)從上報統計方式看,全量上報對請求量巨大的業務部門來說不大可行,定時批量上報又無法保證實時流控;
3)接入全局流控每臺機器都需要部署agent,agent能否正常工作影響全局流控的使用,同時部署及運維的成本不低;
二、方案設計面對目前困難,我們提出這樣的疑問:
有沒有一套簡單可行的方案,能解決上述問題的同時,保證開發成本較低,部署簡單,運行穩定,而且流控準確的呢?
方案要點:
1、計數器的key能“計時“
首先選擇使用ckv作為計數器存儲,相比redis開發會更熟悉,同時維護也更容易,當然該方案也可以選擇redis作為計數器存儲。
既然使用ckv的cas用作計數在高并發下有性能瓶頸,那么只能使用incr的方式,同時要解決計時的問題。
方案沒有對incr增加過期時間的方式,而是將時間信息寫入key,把一天按時間劃分(比如1s劃分一個key)為若干個key作為計數器。這樣每個key既能使用incr方式計數,同時也有”計時“的能力,當超過劃分時間(比如1s后),就順移到下一個key上做計數。
優勢:方案用簡單的方式將全局流控服務做成原子化(計數和計時原子化),開發門檻低。
2、請求統計用拉取的方式替換上報
對于請求的統計方式,一般全量上報不可行,所有業務的請求量至少1:1上報到ckv,ckv的容量和是個問題,單key也容易成為熱點。定時或者定量批量上報,都無法保證實時流控,特別是請求量大的時候,流控延遲的問題會被放大。
方案拋開原有的上報思維定式,引入配額拉取的概念,替換一般統計上報的方式,取而代之的是每個key初始化時寫入流控閾值,每個業務機器并非上報請求量,而是訪問ckv拉取配額到本地保存,本地配額消耗完畢再次拉取,類似余庫存扣減。
優勢:方案減少ckv的訪問量,同時保證流控的準確性。
3、部署不需要agent
已有的流控方案都需要每臺業務機器部署agent,完成上報請求和流控判斷的功能。這樣做機器都要部署agent,同時agent的正常使用也要納入維護。
為了做更輕量的方案,我們考慮agent的必要性,分析發現,agent要完成的功能比較簡單,主要功能托管到業務流控api。
這樣的做法會讓業務在調用流控校驗時有額外的開銷,開銷主要是拉取配額訪問ckv的時間消耗,正常是<1ms,只要每次拉取配額的值設置合理,分攤到每個請求的耗時就少的可以忽略。
比如拉取配額設置10,即正常10個請求要拉取一次配額,這時流控api會請求一次ckv拉取配額,這個業務請求耗時增加約1ms。
優勢:方案不采用agent的方式,部署維護更簡單。
4、全局及單機流控同時啟用
考慮全局流控不可用的情況,比如ckv掛掉,能否保證業務不受影響且流控可用?
方案對容災做了充分的考慮,主要解決方式是全局及單機流控同時啟用,即基于ckv的全局流控和基于單機共享內存的單機流控都同時工作。
全局流控失效(ckv掛掉或連續超時導致拉取配額失敗),流控api判斷出這種情況后,暫時停止使用全局流控,而單機流控依然可以正常工作,流控api定期去探查(比如30s)全局流控是否恢復可用,再啟動全局流控。
優勢:方案有很好的容災能力,容災方式簡單有效。
5、解決ckv性能瓶頸,流控性能達百萬/s
由于使用ckv的incr以及配額拉取的實現方式,全局流控接入服務請求的能力得到成本增長。
目前方案多帶帶申請了一塊ckv,容量為6G,使用incr的方式,壓測性能達到9w+/s。
對業務空接口(Appplatform框架)做流控壓測,使用30臺v6虛擬機,單機50進程,壓測性能達到50w+/s。
單接口50w/s的請求的服務接入,同樣也能滿足多接口總體服務請求量50w+/s的全局流控需求。
上述的壓測瓶頸主要是Appplatform框架的性能原因,由于拉取配額值是根據流控閾值設定(一般>10),50w+的請求量只有不到5w的ckv訪問量,ckv沒到瓶頸。
優勢:方案使用同等的資源(多帶帶一塊6G的ckv),能滿足業務的請求量更高,性能達百萬/s。
6、支持擴容和動態流控升級
支持平行擴展流控能力,一套全局流控部署能滿足流控的服務請求量是達百萬/s,更大的服務請求量需要部署多套全局流控。
支持升級到動態流控能力,ckv寫入的流控閾值是通過定時管理器完成,目前業務已經做了健康度上報,定時管理器只需要對接健康度數據,分析接口當前請求情況,動態調整流控閾值即可達到動態流控能力。
優勢:方案整體簡單輕量,擴容和升級都很容易。
接下來詳細介紹一下具體方案的實現。
(二)流控邏輯架構方案涉及幾個功能簡單、清晰的角色:
1、管理定時器:
根據配置,將頻率限制任務的配額值,寫入多個帶時間信息的key。比如頻率限制任務1配了閾值為5000/s的全局流控,那么就以每一秒生成一個kv為例:
key為task1_20170617000000、task1_20170617000001、task1_20170617000002等
value為5000
2、共享內存:
保存每一個任務流控相關的本機信息,包括流控狀態、本地配額、配額鎖等。
3、流控API:
業務通過流控api,請求先扣減本地配額(原子操作),如果配額<=0,就從ckv拉取配額到共享內存中,如果沒配額拉取,就做說明流控生效。
(三)流控狀態機全局流控過程可以抽象出三個主要狀態:
1、全局非流控狀態指的是全局流控可用的情況下,但還沒觸發限流,業務請求可以正常通過;
2、全局流控狀態指的是業務請求觸發限流,請求不能通過;
3、全局失效狀態指的是全局流控由于異常不可用,比如ckv訪問超時或掛掉,業務請求可以正常通過;
圍繞三個流控狀態的跳轉,抽象出整個全局流控的核心關鍵流程:
1、當狀態為全局非流控,首先會先扣減本地配額,本地配額<=0時,就走拉取配額流程;
2、當狀態為全局流控,本地配額<=0時,先判斷key是否發生變化,作用是同一個時間間隔內配額已經消耗完,減少無效的拉取;
3、當狀態為全局失效,會判斷時間是否已經超過一個設定值,在失效時間內不會嘗試拉取配額,作用是減少無效的拉取;
4、 拉取配額先獲取原子鎖,作用是當業務進程并發拉取時,只有獲取鎖成功的進程,才能拉取賠額額;
整個流程考慮了所有會發生的情況,圍繞三個狀態的跳轉,正常及異常流程處理都很好的統一到一個流程里。
比如發送ckv不可用的故障,通過拉取配額失敗的動作,很好的從正常的全局非流控狀態切換到全局失效狀態,又通過定時拉配額,去探查故障是否消除,如果消除就回復到全局非流控的正常狀態。
三、方案關鍵問題 (一)機器時間不一致由于以時間間隔做key,劃分不同的時間片并寫入流控配額,當機器拉取配額面臨個機器時間是否一致的問題。
據了解,時間同步是通過ntp服務來完成,精度在1~50ms之間,一般情況是<10ms。
目前的時間間隔都是1s以上,ntp服務的精度已經滿足。
換句話說只要保證ntp服務正常運行,全局流控的單個時間片的計數是準確的。
如果ntp服務沒正運行,導致機器時間不一致,會導致同一時刻應該訪問同一key的機器,訪問了多個key,則會造成計數不準確。
由于ntp服務目前處理方式是通過監控流控任務一段時間內的key的變化情況,及時發現機器時間不一致的情況。具體做法是如果發現某一時刻超過兩個kv的配額值發生變化,可以確認機器同一時刻訪問key的分布超過合理的范圍,有時間有不一致的情況。
(二)計數原子化為了保證并發情況下配計數的準確性,會使用原子操作的方式處理計數,無需加鎖。
1、全局配額是用ckv的incr方式,保證配額拉取扣減的準確;
2、本地配額累加或扣減,對共享內存使用gcc提供的__sync_add_and_fetch的原子操作方式;
(三)配額鎖發生死鎖拉取配額使用了加鎖,鎖的方式是對對共享內存使用gcc提供__sync_bool_compare_and_swap的原子操作方式。
極端情況下,獲取鎖的進程core掉,就會導致鎖無法釋放,其他進程需要拉取配額時也獲取不了鎖。死鎖不會影響業務請求正常通過,但由于無法拉取配額,會導致全局流控無法使用。
處理這種情況目前的方式是,判斷加鎖的時長是否超過合理值 ,具體做法是加鎖記錄當前時間,正常釋放清空這個時間值,獲取不了鎖的進程判斷加鎖的時長,大于設定值(1min),說明有死鎖情況,主動釋放鎖。
(四)配額拉取值設定配額拉取的值的設置起到一個很關鍵的一步,影響流控的準確性,拉取的效率以及ckv訪問壓力。
拉取配額值合理,既減少ckv訪問壓力,減輕業務Api額外的拉取耗時(一般<1ms),同時也能保證流控準確。
拉取配額值不合理,設置過大會造成機器剩余的配額浪費,需要配額的機器可能沒配額,導致產生錯誤流控。設置過小會導致本地配額消耗完(本地配額值<0),配額拉取滯后,造成流控生效延后,拉取次數過多,ckv訪問壓力大,業務api拉取效率低。
配額值的設置是:單機閾值與拉取值的比值為50。比如全局流控閾值 10000/s,機器數20,平均單機流控閾500/s,配額值設定為10。
目前是通過壓測觀察的經驗值得來,拉取值設置是否合理,還有待后續觀察和分析。
四、方案運維 (一)部署及擴展部署:
1、管理定時器的部署,只需多帶帶部署到腳本機上;
2、業務模塊添加流控api,已經接入原來單機流控的業務,無需改動業務邏輯代碼,只需要替換舊的靜態庫和依賴的的頭文件即可(待給出詳細接入);
擴展:
方案支持平行擴展,一套全局流控部署能滿足流控的服務請求量是50w+/s,更大的服務請求量需要部署多套全局流控。平行擴展一套主要的變更包括:申請新的ckv,使用新的一塊共享內存以及新的流控任務配置。
(二)監控報警1、對流控任務做了可視化監控
主要監控及跟蹤各流控任務的基本使用能夠信息,以及當前和歷史流量情況
2、機器時間不一致的監控及上報
主要監控流控任務一段時間內的key的變化情況,及時發現機器是否時間不一致
(三) 容災/故障處理1、管理定時器接入zk主從切換組件,在單點掛掉的情況下可以切到另外一臺機器上,保證timer的可用性。
2、當ckv連接超時或無法訪問時,對應的流控狀態會變成全局失效,過一段時間會自動重新拉起。所以出現ckv不可用的情況,只需要恢復ckv,接入全局流控的服務會自動恢復可用狀態。
五、方案升級 (一)完善監控和告警目前流控監控只是對流控任務使用情況做了簡單的展示,流控的歷史情況等其他必要的信息還沒能查詢及展示。
還有待補充的監控有機器時間不一致監控,監控發現的問題需要告警,以便于人工及時介入。
有待規劃的監控和告警后續再補充。
(二)流控方案升級流控升級下一步是從全局流控升級到動態流控,所需健康度數據已經上報,而接入的方式目前可以直接在管理定時器上面增加配額調整的能力,這個擴展很方便。重點應該是怎么去根據上報的健康數據分析并實現動調整當前配額值。
配額調整大致的思路如下:
注:圖片來自于理財通的《接入層限流介紹》
WeTest壓測大師運用了沉淀十多年的內部實踐經驗總結,通過基于真實業務場景和用戶行為進行壓力測試,幫助游戲開發者發現服務器端的性能瓶頸,進行針對性的性能調優,降低服務器采購和維護成本,提高用戶留存和轉化率。
功能目前免費對外開放中,點擊鏈接:http://wetest.qq.com/gaps 即可體驗!
如果對使用當中有任何疑問,歡迎聯系騰訊WeTest企業qq:800024531
文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。
轉載請注明本文地址:http://specialneedsforspecialkids.com/yun/35836.html
摘要:二現有方案分析目前全局流控方案主要需要解決兩個實現問題全局計數器使用何種存儲全局計數器存儲可以使用,也可以使用。優勢方案減少的訪問量,同時保證流控的準確性。 作者:莫家文,騰訊事務型開發工程師 商業轉載請聯系騰訊WeTest獲得授權,非商業轉載請注明出處。 原文鏈接:http://wetest.qq.com/lab/view/320.html WeTest 導讀 全新的全局流控實現方...
閱讀 1442·2023-04-25 17:18
閱讀 1882·2021-10-27 14:18
閱讀 2123·2021-09-09 09:33
閱讀 1839·2019-08-30 15:55
閱讀 2016·2019-08-30 15:53
閱讀 3439·2019-08-29 16:17
閱讀 3429·2019-08-26 13:57
閱讀 1730·2019-08-26 13:46