同窗,要不要來挑戰雙11零點流量洪峯?

阿里妹導讀:雙十一的零點,整個電商系統的請求速率到達峯值。若是將這些請求流量只分配給少部分 server,這些機器接收到的請求速率會遠超過處理速率,新來的任務來不及處理,就會產生請求任務堆積。算法

今年的中間件性能挑戰賽就圍繞「挑戰雙11零點流量洪峯」展開。自2015年開始,中間件性能挑戰賽已經成功舉辦了四屆,被歷年大賽選手稱爲「中間件技術的風向標」。接下來,跟隨阿里巴巴中間件團隊的郭浩,一塊兒來圍觀賽題,解讀賽題。網絡

在現代分佈式應用中,服務請求是由物理機或虛擬機組成的 server 池進行處理的。 一般,server 池規模巨大且服務容量各不相同,受網絡、內存、CPU、下游服務等各類因素影響,一個 server 的服務容量始終處於動態變更和趨於穩定的狀態,如何設計和實現這種系統的負載均衡算法是一個極具挑戰的難題。數據結構

自適應負載均衡的需求背景

負載均衡有兩個主要目標:併發

  • 保持較短的請求響應時間和較小的請求阻塞機率;
  • 負載均衡算法的 overhead 在可控級別,不佔用過多的 CPU 、網絡等資源。

自適應負載均衡是指不管系統處於空閒、穩定仍是繁忙狀態,負載均衡算法都會自動評估系統的服務能力,進行合理的流量分配,使整個系統始終保持較好的性能,不產生飢餓或者過載、宕機。負載均衡

這種算法對於如今的電商系統、數據中心、雲計算等領域都頗有必要,使用自適應負載均衡可以更合理的利用資源,提升性能。框架

對用戶而言,一旦產生任務堆積,請求會變慢甚至超時,體驗嚴重降低,甚至致使服務不可用。而處理請求的機器也會因爲堆積的任務愈來愈多而發生嚴重過載,直到被打垮。剩餘的還沒有宕機的其它機器會逐漸重複這個過程,直至整個應用不可用,發生系統故障。dom

爲了不這種狀況發生,咱們可能會想到一種經常使用的辦法:在服務上線前提早進行壓測,使用壓測的容量做爲限流值,當線上服務的請求速率大於限流值的時候,服務拒絕新到的服務,從而保障服務始終可用。可是這種方式也存在問題:壓測時測試的容量進行限流一般會趨於保守,不能充分發揮異構系統的所有性能;也沒法智能地應對因爲網絡、下游服務變化而致使的容量降低等問題,系統仍然存在宕機風險。分佈式

所以,咱們須要具有自適應能力的負載均衡算法,來更好地進行流量分配調度以及穩定性保障,追求極致性能,挑戰大促等場景下的流量洪峯。ide

結合中間件性能挑戰賽的賽題

咱們結合「第五屆中間件性能挑戰賽」中的初賽場景,來一塊兒探討一下設計和實現一個自適應的負載均衡的基本思路。微服務

本次挑戰賽的場景由施壓程序(阿里雲性能測試PTS)、服務調用方(Consumer)和三個規格不一樣的服務提供方(Provider) 組成。在評測過程當中,每一個程序都部署在不一樣的物理機上,以免因 CPU、網絡資源的競爭,致使評測程序抖動,影響最終評測成績。

Becnhmarker 負責請求 Consumer, Consumer 收到請求後,從三臺物理規格不一樣、服務響應時間和最大併發都不一樣的 Provider 中選擇一個進行調用並返回結果。選擇哪個 Provider 進行調用的流程就是本次挑戰賽須要實現的負載均衡算法。

爲了簡化環境部署和提高性能,本次挑戰賽沒有使用服務註冊和發現機制。三個 Provider 對應的 URL 都已經被直接配置在了 Consumer 中,選手在開發和測試時可直接經過 Provider-small 等 hostname 訪問相應的 Provider。

賽題分析

題目描述很簡單,不考慮 Consumer 直接拒絕的狀況下,場景能夠簡化爲 3 選 1 的問題,但如何進行這個決策則是本次挑戰賽考察的難點和重點。

官方題目組提供了 Random 算法做爲默認實現:從 3 個 Provider 中隨機取任意一個。對於單 dispatcher (在本次賽題中是 Consumer) 同構系統的場景,Random能夠達到漸近負載均衡, 每一個 Provider 接收到的總請求數接近。可是對於多 dispatcher 或異構系統而言,Random 算法因爲缺乏全局狀態,沒法保證全局隨機,極端條件下,多個 dispatcher 可能將請求同時分配到一臺 Provider 上,致使系統存在服務過載和宕機的風險;異構系統中,不一樣 Provider 服務容量實際是不一樣的,即便每一個 Provider 請求速率相同也會產生空閒、穩定、過載等不一樣的服務狀態,沒法實現最優流量分配,更不能作到響應時間最小。顯而易見,Random 並非符合賽題要求的自適應算法。

那麼,如何實現自適應負載均衡呢?接下來咱們將利用題目給出的條件由淺入深的描述這個算法的設計過程。

自適應算法首先要解決如何對服務進行容量評估的問題。

本次比賽按照硬件規格不一樣,Provider 被分爲 small、medium、和 large 三種,CPU 和內存對應的比例爲 1:2:3 。在評測過程當中,每一個 Provider 的處理能力都會動態變化,主要體如今單次響應時間的變化和容許的最大的併發數上。來自 Consumer 的請求速率過快時, Provider 端新到的請求會排隊等待處理,當排隊線程數和工做線程數量之和達到最大線程數時,Provider 返回線程池用盡異常。在算法的實現和調優過程當中,應該儘可能避免產生線程池異常,減小排隊。如何結合好程序和硬件的限制,區分出不一樣階段的瓶頸,作出符合實際的容量評估是賽題的第一個難點。對於本次題目所採用的參數和變化過程,僅憑現有的理論和實踐很難達到最優,因此須要選手充分理解題意和各參數配置,設計出更適合實際場景的算法。

第二個須要考慮的問題是如何應用容量評估結果,即如何維護表明 Provider 服務能力的狀態,又如何在選擇 Provider 階段根據這些狀態進行決策?

傳統的單 Dispatcher 負載均衡模型由一個 Dispatcher 維護全部 Provider 的狀態,在同構系統中,這種方式可以達到漸進最優負載均衡。可是它存在的問題也很明顯:單 Dispatcher 性能存在自然瓶頸,可擴容性較差,當 Provider 數量成倍上升時,Dispatcher 須要維護的狀態也在成倍上升,通訊成本也在上升。本次挑戰賽中爲了下降難度,沒有基於多 Dispatcher 模型構建題目,但多 Dispatcher 、多 Provider 纔是 Dubbo 等微服務框架在實際生產環境中最多見的狀況。所以,若能實現高性能且可擴展性良好的均衡算法,會是一個不錯的加分項。

第三點是輔助接口的使用。爲了避免限制算法設計思路,賽題提供了多個可能用到的輔助接口,包括雙向通訊、Provider 限流等支持。可是這些接口都是非必選項,是否使用這些接口取決於算法實現的須要。

在評測環境中,任意一個 Provider 服務處理速率都小於評測程序的請求速率。三個 Provider 總的處理速率會在請求速率上下浮動。最終成績由請求成功數和最大 TPS 組成,失敗的請求不計入成績。對於這個限制,能夠有兩種解讀方式,一是爲了保證服務不嚴重過載,能夠適當拒絕請求。第二點是須要充分利用每一個 Provider 的服務容量,保證性能最優的 Provider 請求數合理,適當的過載也是容許的。

以上僅做爲一個主要的算法設計思路,優秀的負載均衡算法在工程上的實現也是很關鍵的一點,須要選取合適的數據結構,充分利用好內存和 CPU,壓榨出比賽環境的每一點性能。固然,評測成績並不表明一切,良好的代碼結構、編碼風格以及通用性,也在最終初賽成績中佔據很大比例。

關注「阿里技術」官方公衆號,並在對話框內回覆「中間件」,便可得到初賽賽題。

賽題評測

評測環境由 1 臺 4 核 8G 的施壓機,1 臺 4 核 8G 的網關機和 3 臺 4 核 8G 的 Provider組成。Consumer 和 Provider 程序都會限制 CPU 和內存使用,每一個評測任務都會獨佔五臺機器。

  • 準備跑分環境,建立並鎖定工做區;
  • 根據提交的 Git 地址,從代碼倉庫中拉取代碼;
  • 構建代碼,生成最終執行的 fat JAR;
  • 啓動三個 Provider ,並驗證服務可用性;
  • 啓動 Consumer ,並驗證服務可用性;
  • 對系統進行預熱,持續 30 秒;
  • 正式評測 1 分鐘;
  • 取正式評測的總成功請求數和最大 TPS 做爲最終成績,上報天池系統;
  • 按順序依次中止 Consumer、三個 Provider;
  • 清理 Docker 實例及鏡像;
  • 收集日誌並上傳到 OSS;
  • 解鎖工做區,清理環境。

總結

本文結合第五屆中間件性能挑戰賽的賽題背景、題目場景、題目分析和評測環境與過程的角度,介紹了自適應負載均衡算法的基本設計思路,但願對即將參加比賽的同窗們能有所幫助,也歡迎更多的技術同窗報名參加咱們的挑戰賽,分享你在算法方面的思考和實踐。


原文連接 本文爲雲棲社區原創內容,未經容許不得轉載。

相關文章
相關標籤/搜索