前言
這篇文章主要是介紹mosn在v1.5.0中新引入的基於延遲的負載均衡算法。
- 對分佈式系統中延遲出現的原因進行剖析
- 介紹mosn都通過哪些方法來降低延遲
- 構建來與生產環境性能分佈相近的測試用例來對算法進行驗證
地址:
https://github.com/mosn/mosn/pull/2253
在開始聊基於延遲的負載均衡算法之前,先介紹下什麼是負載均衡——
什麼是負載均衡
Wikipedia中**Load Balancing (Computing)**詞條是這樣介紹負載均衡的:
負載均衡是將一組任務分配到一組資源(計算單元)上的過程,目的是使它們的整體處理更有效率。負載均衡可以優化響應時間,避免負載不均勻導致一些計算節點過載而其他計算節點處於空閒狀態
負載均衡在大型分佈式系統中是關鍵的組成部分。負載均衡解決了分佈式系統中最重要的兩個問題:可伸縮性(scalability)和韌性(resilience)。
- 可伸縮性:應用程序部署在多個相同的副本中。當計算資源不足時可以通過部署額外的副本來增加計算資源,而當計算資源大量冗餘時可以通過減少副本來節省成本。通過負載均衡可以將請求負載分佈到不同的副本中。
- 韌性:分佈式系統的故障是部分的。應用程序通過冗餘副本的方式,保證在部分組件故障時仍能正常地提供服務。負載均衡通過感知節點的故障,調整流量的分配,將流量更多的分配到那些能夠正常提供服務的節點上。
走得更快
負載均衡使得現代軟件系統具備了可擴展性和韌性。但在分佈式系統中還存在不容忽視的問題:延遲。
延遲來自哪裏
現代軟件系統通常是多層級結構大型分佈式系統,即使是隻服務單個終端用戶的請求,它背後也有可能經過了上百次的數據訪問,這種情況在微服務架構中更是尤爲普遍。
微服務架構(引用自Microservices Pattern)
單臺性能穩定的服務器中延遲通常由以下幾個方面造成:
- 計算任務本身的複雜度
- 內容的傳輸過程中的延遲
- 請求排隊等待的延遲
- 後臺任務活動所導的資源競爭
這些服務器之間的延遲將會疊加,任何顯著的延遲增加都會影響終端用戶的體驗。此外,任何來自單個節點的延遲峯值也會直接影響到終端用戶體驗。最後,越來越多地使用公有云部署應用程序,進一步加劇了響應時間的不可預測性,因爲在這些環境中存在共享資源(CPU、內存和IO)的爭用,應用程序機幾乎不可避免地遇到性能影響,並且這種影響是隨時發生的。
如何減少延遲
有研究表明,在大型互聯網應用中,延遲往往具有長尾特點,P999比中位數高出幾個數量級。如果在應用架構的每層都能夠減少這些尾部延遲,那麼對終端用戶整體的尾部延遲將會顯著降低。
在服務網格中,所有接收和發送的流量都會經過邊車代理,通過邊車代理可以輕鬆地控制網格的流量,而無需對服務進行任何修改。如果邊車代理在對應用層流量進行轉發時,總是通過負載均衡時選擇響應時間較短的服務器,那麼將會顯著降低對終端用戶的尾部延遲。
基於此,我們準備開始爲mosn引入基於延遲的負載均衡算法,並進行適當調整來保證能夠在大多數使用場景下顯著減少延遲。
性能問題是局部的
前面提到了,每個節點的性能受到多種因素的影響,這些影響因素是動態的,難以準確預測每個節點的性能,因此我們無法精確地選擇最好的節點,但是可以避免較差的節點。
在雲環境中,服務器的性能常常是難以預測的,但是我們可以通過對大量的數據進行分析,發現服務器性能的分佈大多數情況下是符合正態分佈的。因此,儘管有一部分的服務器在性能方面表現比較差,它們的數量通常都是少數的(3sigma),而絕大部分服務器節點的表現是正常的。
除了服務器之間的差異,還存在由基礎設施導致的動態延遲,這種延遲可能是由於網絡擁塞、故障或不斷增長的流量所導致。這種延遲通常具有持續性和局部性。持續性則表示延遲會長時間存在,不會在短時間內消失;而局部性指的是延遲往往只出現在某些特定服務器上,而不會在全局發生。
PeakEWMA
面對這些問題,我們使用PeakEWMA(Peak Exponentially Weighted Moving Average)計算響應時間指標,並根據這個指標來對節點進行負載均衡。
EWMA是一種動態權重調整算法,各數值的加權影響力隨時間而指數式衰退,越近期的數據加權影響力越重,但較舊的數據也給予一定的加權值。
它以相對較高的權重考慮了最近響應時間的影響,因此更具有針對性和時效性。加權的程度以常數 決定, 數值介於 0 至 1,它用來控制數據加權影響力衰退的速率。
作爲一種統計學指標,EWMA的計算過程不需要大量的採樣點以及時間窗口的設定,有效地避免了計算資源的浪費,更適合在mosn這樣的邊車代理中使用。
由於響應時間是歷史指標,當服務器出現性能問題導致長時間未返回時,負載均衡算法會錯誤地認爲這臺服務器仍是最優的,而不斷地向其發送請求而導致長尾延遲增高。我們使用活躍連接數作爲實時變化的指標對響應時間進行加權,表示等待所有活躍的連接都返回所需要的最大時間。
P2C(Power of Two Choice)
在大規模集羣中,如果使用遍歷所有服務器選擇最好的服務器的方法,雖然可以找到最輕負載的服務器來處理請求,但這種方法通常需要大量的計算資源和時間,因此無法處理大規模的請求。因此,我們使用P2C(Power of Two Choice)來選擇最優節點。相比之下,P2C算法可以在常數時間內選擇兩個服務器進行比較,並選擇其中負載更輕的服務器來處理請求。P2C基於概率分配,即不直接基於權重分配,而是根據每個服務器優於其他服務器的概率值來決定請求的分配。
此外,在多個負載均衡器的情況下,不同負載均衡器可能會有不同的節點視圖,這可能導致某些負載均衡器選擇的最優節點總是最差的節點。這是因爲負載均衡器選擇最優節點時基於自己的視圖信息,而節點視圖隨着時間的變化可能會發生變化,因此不同的負載均衡器選擇的最優節點也可能不同。P2C算法通過對隨機選擇的兩個節點進行比較,可以使節點間的負載均衡更加均勻,即使節點視圖發生變化,也能提供穩定的負載均衡效果。
在mosn的v1.5.0版本中,只有節點權重相同時會使用P2C,當權重不同時會使用EDF進行加權選擇。後續會提供可配置的選項。
模擬流量驗證
我們構建了與生產環境性能分佈相近的測試用例來對算法進行驗證。
首先我們使用正態分佈生成了10臺服務器的基準性能,其中數學期望爲50ms,標準差爲10ms。接下來,我們將這些基準性能作爲數學期望,並以標準差爲5ms的正態分佈隨機生成了請求延遲,以模擬真實世界的情況。此外,我們還在其中一臺服務器注入了概率爲0.1的故障,故障發生時會產生1000ms的延遲,以測試系統的容錯性。
爲了模擬請求傾斜時請求排隊等待的延遲,我們限制了每臺服務器的最大併發數爲8,當同時處理的最大請求數超過了最大併發數時,將會排隊等待。這樣能夠更加真實地模擬出系統的運行情況。
最後,我們使用了Round Robin、Least Request和PeakEWMA三種算法,分別以16併發同時發送請求,得到的P99如下
Round Robin算法雖然平衡,但是始終會選擇到注入了故障的服務器,導致P99始終在1000ms上下波動;Least Request算法雖然避開了故障服務器,但是其P99值依然表現出較大的波動。
與此相比,PeakEWMA算法在保持穩定的同時,P99值始終低於Round Robin和Least Request算法。這恰當地體現了mosn在性能優化方面的成功,mosn確實做到了走得更快。
期待走得更穩
雖然服務網格解決了讓應用跑得更快的問題,但是分佈式系統中的故障卻時刻存在。我們期望通過mosn的負載均衡算法,可以讓我們的服務走得更穩。
快速失敗的挑戰
根據經驗,故障時的響應時間往往遠遠小於正常值,比如網絡分區導致的連接超時,而沒有實際處理請求。我們稱這種錯誤時響應時間遠遠小於正常值的情況爲快速失敗。
在服務器出現快速失敗時,從負載均衡的角度看,就會錯誤地認爲該服務器是最優的選擇。儘管可以通過斷路器來避免向該服務器持續發送請求,但是斷路器的閾值設置也存在挑戰。此外,斷路器需要足夠的錯誤樣本才能觸發,而我們期望儘可能避免錯誤的發生。
因此,我們在後續版本中將會對負載均衡算法進行調整,讓負載均衡算法能夠感知錯誤的發生,並在觸發斷路器前就避免將請求轉發到故障的服務器中。
作者:京東物流 紀卓志
內容來源:京東雲開發者社區