前言
這篇文章主要是介紹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的負載均衡演算法,可以讓我們的服務走得更穩。
快速失敗的挑戰
根據經驗,故障時的響應時間往往遠遠小於正常值,比如網路分割槽導致的連線超時,而沒有實際處理請求。我們稱這種錯誤時響應時間遠遠小於正常值的情況為快速失敗。
在伺服器出現快速失敗時,從負載均衡的角度看,就會錯誤地認為該伺服器是最優的選擇。儘管可以透過斷路器來避免向該伺服器持續傳送請求,但是斷路器的閾值設定也存在挑戰。此外,斷路器需要足夠的錯誤樣本才能觸發,而我們期望儘可能避免錯誤的發生。
因此,我們在後續版本中將會對負載均衡演算法進行調整,讓負載均衡演算法能夠感知錯誤的發生,並在觸發斷路器前就避免將請求轉發到故障的伺服器中。
作者:京東物流 紀卓志
內容來源:京東雲開發者社群