集群與負載均衡的演算法與實現

2022-09-18 05:51:22 字數 3182 閱讀 5199

什麼是負載均衡呢?使用者輸入的流量通過負載均衡器按照某種負載均衡演算法把流量均勻的分散到後端的多個伺服器上,接收到請求的伺服器可以獨立的響應請求,達到負載分擔的目的。從應用場景上來說,常見的負載均衡模型有全域性負載均衡和集群內負載均衡,從產品形態角度來說,又可以分為硬體負載均衡和軟體負載均衡。全域性負載均衡一般通過dns實現,通過將乙個網域名稱解析到不同vip,來實現不同的region排程能力;硬體負載均衡器常見的有f5、a10、array,它們的優缺點都比較明顯,優點是功能強大,有專門的售後服務團隊,效能比較好,缺點是缺少定製的靈活性,維護成本較高;現在的網際網路更多的思路是通過軟體負載均衡來實現,這樣可以滿足各種定製化需求,常見的軟體負載均衡有 lvs、nginx、haproxy。

阿里雲高效能負載均衡使用 lvs 和 tengine,我們在乙個 region 區分不同的機房,每個機房都有 lvs 集群和 tengine 集群,對於使用者配置的四層監聽,lvs 後面會直接掛載使用者 ecs,七層使用者監聽 ecs 則掛載在 tengine 上,四層監聽的流量直接由 lvs **到 ecs,而 7 層監聽的流量會經過 lvs 到 tenigine 再到使用者 ecs。每乙個 region 裡都會有多個可用區,達到主備容災目的,每乙個集群裡都有多台裝置,第一是為了提公升效能,第二也是基於容災考慮。

圖為高效能負載均衡控制管理概要圖,slb 產品也有 sdn 概念,**和控制是分離的,使用者所有配置通過控制台先到控制器,通過集中控制器轉換將使用者配置推送到不同裝置上,每台裝置上都有 agent 接收控制器下發的需求,通過本地轉換成 lvs 和 tengine 能夠識別的配置,這個過程支援熱配置,不影響使用者**,不需要 reload 才能使新配置生效。

早期 lvs 支援三種模式,dr 模式、tun 模式和 nat 模式。

dr 模式

dr 模式經過 lvs 之後,lvs 會將 mac 位址更改、封裝 mac 頭,內層 ip 報文不動,報文經過 lvs 負載均衡查詢到 rs 之後,將源 mac 頭改成自己的,目的 mac 改成 rs 位址,mac 定址是在二層網路裡,對網路部署有一定的限定,在大規模分布式集群部署裡,這種模式的靈活性沒有辦法滿足需求;

tun 模式

tun 模式走在 lvs 之後,lvs 會在原有報文基礎上封裝 ip 頭,到了後端 rs 之後,rs 需要解開 ip 報文封裝,才能拿到原始報文,不管是 dr 模式還是 tun 模式,後端 rs 都可以看到真實客戶源 ip,目的 ip 是自己的 vip,vip 在 rs 裝置上需要配置,這樣可以直接繞過 lvs 返回給使用者,tun 模式問題在於需要在後端 ecs 上配置解封裝模組,在 linux 上已經支援這種模組,但是 windows 上還沒有提供支援,所以會對使用者系統映象選擇有限定。

nat 模式

nat 模式使用者訪問的是 vip,lvs 查詢完後會將目的 ip 做 dnat 轉換,選擇出 rs 位址,因為客戶端的 ip 沒變,在回包的時候直接向公網真實客戶端 ip 去路由,nat 的約束是因為 lvs 做了 dnat 轉換,所以回包需要走 lvs,把報文頭轉換回去,由於 ecs 看到的是客戶端真實的源位址,我們需要在使用者 ecs 上配置路由,將到 ecs 的預設路由指向 lvs 上,這對使用者場景也做了限制。

netfilter 是 linux 提供的網路開放平台,基於平台可以開發自己的業務功能模組,早期好多安全廠商都是基於 netfilter 做一些業務模型實現,這種模型比較靈活,但通用模型裡更多的是相容性考慮,路徑會非常長;而且通用模型中沒辦法發揮多核特性,目前 cpu 的發展更多是向橫向擴充套件,我們經常見到多路伺服器,每路上有多少核,早期通用模型對多核支援並不是特別友善,在多核設計上有些欠缺,導致我們在通用模型上做一些應用開發時的擴充套件性是有限的,隨著核的數量越來越多,效能不增反降。

早期模式的各種限制制約了我們的發展,所以我們首先做了 fullnat,相比原來的 nat 方式,fullnat 多了 snat 屬性,將客戶端的原 ip 位址作了轉換;其次,我們在並行化上做了處理,充分利用多核實現效能線性提公升;然後是快速路徑,我們在做網路**模型時很容易想到設計快速路徑和慢速路徑,慢速路徑更多是解決首包如何通過裝置問題,可能需要查acl或路由,需要判斷許多和策略相關的東西,後面所有報文都可以通過快速路徑**出去;還有指令相關優化,利用因特爾特殊指令提公升效能;另外針對多核架構,numa 多節點記憶體訪問,通過訪問 local 節點記憶體可能獲得更好的延遲表現。

客戶端進來 ip 首先訪問 lvs 的 vip,原 ip 是客戶端的,目的 ip 是 lvs 的 vip,經過 fullnat 轉換後,原 ip 變成 lvs 的 local 位址,目的位址是 lvs 選擇出來的 rs 位址,這樣在 rs 回包時比較容易,只要路由可達,報文一定會交到 lvs 上,不需要在 rs 上做特殊的配置。右面就是 dnat + snat 轉換,報文就可以通過 lvs **回客戶端,這種方式主要帶來應用場景部署靈活性選擇。

通過並行化實現對 lvs 效能的改善,效能沒有辦法得到線性提公升更多的是因為每條路徑都需要訪問全域性資源,就會不可避免引入鎖的開箱,另外,同一條鏈結上的報文可能分散在不同的核上,大家去訪問全域性資源時也會導致 cache 的丟失。所以我們通過 rss 技術把同乙個五源組報文扔到同乙個 cpu 上處理,保證入方向的所有相同連線上的報文都能交給相同 cpu 處理,每個核在**出去時都用當前 cpu 上的 local 位址,通過設定一些 fdir 規則,報文回來時後端 rs 訪問的目的位址就是對應 cpu 上的 local 位址,可以交到指定的 cpu 上去處理,這樣一條連線上左右方向報文都可以交給同乙個 cpu 處理,將流在不同的 cpu 隔離開;另外,我們把所有配置資源包括動態快取資源在每個 cpu 上作了拷貝,將資源區域性化,這使整個流從進入 lvs 到**出去訪問的資源都是固定在乙個核上的本地資源,使效能達到最大化,實現線性提公升。

改進後的 lvs 表現如下:

tengine 在應用過程中也遇到了各種問題,最嚴重的就是效能問題,我們發現隨著 cpu 數量越來越多,qps 值並沒有線性提公升;nginx 本身是多 worker 模型,每個 worker 是單程序模式,多 worker 架構做 cpu 親和,內部基於事件驅動的模型,其本身已經提供了很高的效能,單核 nginx 可以跑到 1w5~2w qps。nginx 往下第一層是 socket api,socket 往下有一層 vfs,再往下是 tcp、ip,socket 層比較薄,經過量化的分析和評估,效能開銷最大的是 tcp 協議棧和 vfs 部分,因為同步開銷大,我們發現橫向擴充套件不行,對此,我們做了一些優化。

七層反向**的路徑更長,處理更複雜,所以它的效能比 lvs 低很多,我們比較關注單機和集群的效能,集群效能可以靠堆裝置去解決,單機如果不提公升,成本會一直增加,從效能角度來看,有以下的優化思路和方向:

**:有夢想的鹹魚

集群與負載均衡

集群是一組協同工作的服務實體。當客戶請求到來時,集群內部的負載均衡器會比較均衡的把很多客戶的請求分布到集群環境下的計算和網路資源,也就是說,負載均衡是集群的乙個重要特性。集群的另外乙個特性就是錯誤恢復的能力,當乙個實體中的資源不能工作,另乙個實體中的資源透明的繼續完成任務的過程叫做錯誤恢復。集群實體...

WEB集群與負載均衡

負載均衡的作用是在多個節點之間按照一定的策略 演算法 分發網路或計算處理負載。負載均衡可以採用軟體和硬體來實現。一般的框架結構可以參考下圖。後台的多個web節點上面有相同的web應用,使用者的訪問請求首先進入負載均衡分配節點 可能是軟體或者硬體 由它根據負載均衡策略 演算法 合理地分配給 某個web...

Linux Nginx的集群與負載均衡

nginx的集群與負載均衡 集群就是一群人幹同樣的活,負載均衡就是保證每個人都幹得差不多。或者大人幹得多一些,小孩幹得少一些。nginx實現負載均衡很方便。準備三颱伺服器,一台是用於訪問 66 另外是兩台用於提供服務的集群 61,62 先準備三個logo.png。66上如下 61上如下 62上如下 ...