負載均衡是指,將請求/數據分攤到多個操做單元上執行,關鍵在於均衡。程序員
然而,後端的服務器有可能硬件條件不一樣:後端
可否根據異構服務器的處理能力來動態、自適應進行負載均衡,以及過載保護呢?服務器
service層的負載均衡,通常是經過service鏈接池來實現的,調用方鏈接池會創建與下游服務多個鏈接,每次請求「隨機」獲取鏈接,來保證訪問的均衡性。架構
負載均衡、故障轉移、超時處理等細節也都是經過調用方鏈接池來實現的。負載均衡
最容易想到的方法,能夠爲每一個下游service設置一個「權重」,表明service的處理能力,來調整訪問到每一個service的機率,如上圖所示:ide
(1) 假設ip1,ip2,ip3的處理能力相同,能夠設置weight1=1,weight2=1,weight3=1,這樣三個service鏈接被獲取到的機率分別就是1/3,1/3,1/3,可以保證均衡訪問;優化
(2) 假設ip1的處理能力是ip2,ip3的處理能力的2倍,能夠設置weight1=2,weight2=1,weight3=1,這樣三個service鏈接被獲取到的機率分別就是2/4,1/4,1/4,可以保證處理能力強的service分到等比的流量,不至於資源浪費;設計
Nginx就具有相似的能力。blog
方案優勢:簡單粗暴,可以快速的實現異構服務器的負載均衡。ip
方案缺點:權重是固定的,沒法自適應動態調整,而不少時候,服務器的處理能力是很難用一個固定的數值量化。
如何來標識一個service的處理能力呢?
服務能不能處理得過來,該由調用方說了算:
如何來設計動態權重?
能夠這麼玩:
(1) 用一個動態權重,來標識每一個service的處理能力,默認初始處理能力相同,即分配給每一個service的機率相等;
(2) 每當service成功處理一個請求,認爲service處理能力足夠,權重動態+1;
(3) 每當service超時處理一個請求,認爲service處理能力可能要跟不上了,權重動態-10;
畫外音:
權重降低,會比權重上升更快。
爲了方便權重的處理,能夠把權重的範圍限定爲[0, 100],把權重的初始值設爲60分。
舉例說明:
假設service-ip1,service-ip2,service-ip3的動態權重初始值:
隨着時間的推移:
隨着動態權重的增減,權重會發生變化:
如上圖所示,若是沒有過載保護:
過載保護,是指當外部負載超過系統處理能力時,系統會進行自我保護,依然能對外提供有損的穩定服務。
如上圖所示,若是進行了過載保護:
這是最簡易的方式,服務端設定一個負載閾值,超過這個閾值的請求壓過來,所有拋棄。
畫外音:這個方式不是特別優雅。
如同異構服務器負載均衡,仍然經過:
當一個服務端多次處理超時,權重不斷下降時,鏈接池只要實施一些策略,就可以對「疑似過載」的服務器進行降壓,而不用服務器「拋棄請求」這麼粗暴的實施過載保護。
能夠這麼玩:
(1) 若是某一個服務器,連續3個請求都超時,即連續-10分三次,就能夠認爲,服務器處理不過來了,得給這個服務器喘一小口氣,因而設定策略:接下來的若干時間內,例如1秒,負載再也不分配給這個服務器;
畫外音:休息1秒後,再分給它。
(2) 若是某一個service的動態權重,降爲了0(休息了3次還超時),就能夠認爲,服務器徹底處理不過來了,得給這個服務器喘一大口氣,因而設定策略:接下來的若干時間內,例如1分鐘,請求再也不分配給這個服務器;
畫外音:根據經驗,此時服務器通常在fullGC,差很少1分鐘能回過神來。
這樣的話,不但能借助「動態權重」來實施動態自適應的異構服務器負載均衡,還能在客戶端層面更優雅的實施過載保護,在某個下游服務器快要響應不過來的時候,給其喘息的機會。
要防止過載保護引發服務器的雪崩,若是「總體負載」已經超過了「服務器集羣」的處理能力,怎麼轉移請求也是處理不過來的。這時,仍是得經過拋棄請求來實施自我保護。
架構師之路-分享可落地的技術文章
相關推薦:
《GFS架構啓示》
《Google MapReduce解決什麼問題?》
《Google MapReduce巧妙優化思路?》
《程序員養女兒的四大要點!》
聽說,配圖值得轉。