1. 程式人生 > >Google Maglev 牛逼的網絡負載均衡器(轉)

Google Maglev 牛逼的網絡負載均衡器(轉)

均衡 下載 發送 span 路由器 體系 最重要的 選擇 tcp

https://segmentfault.com/a/1190000009565788

Maglev 是什麽

Maglev 是谷歌搞的一個工作在三層(IP層)的網絡負載均衡器, 它是一個運行在普通的 Linux 系統上的巨大的分布式系統, 並且可以簡單平滑的伸縮後端服務器數量, 谷歌在自己的數據中心便使用該方案做負載均衡, 後面又以論文的形式將 Maglev 的負載均衡方案分享了出來.

剛說 Maglev 是一個三層的負載均衡, 那麽什麽是三層的負載均衡呢?

就是當你訪問一個負載均衡的 IP 的時候, 這個 IP 的後面是一個服務器組, 而不是單個服務器, 而這個服務器組中的任意一個服務器上面都可以監聽該 IP 來提供對外服務, 這樣達到的一個效果是不存在 IP 單點故障的問題, 並且該 IP 的服務能力可以通過增加機器來進行擴展.

它達到的效果如圖所示:

技術分享圖片

Maglev 是如何工作的

首先, 我們來看一下 maglev 的數據包的流向圖:

技術分享圖片

如圖, 當一個用戶訪問一個帶有 Maglev 負載均衡的服務的 VIP 的時候, 用戶的請求首先通過 Internet 到達真實的服務節點所在的物理機房的核心交換機上, 也就是上圖的 Router, 這個時候核心交換機通過 ECMP 的功能將請求該 VIP 的數據包均衡的發送給後面的 N 個 Maglev 節點(藍色線1).

請求該 VIP 的數據包到達 Maglev 節點之後, Maglev 會知道該 VIP 對應哪些 Service Endpoint, 然後通過一種牛逼的一致性哈希算法選擇一個 Service Endpoint 將數據包發過去(紫色線2), 而要返回給用戶的數據包會由 Service Endpoint 直接返回到核心交換機上, 然後通過 Internet 返回給用戶(紅色線3).

以上簡要的概括了數據包的是如何傳輸的, 看起來很簡單, 那麽整套體系要如何實現呢? 下面挑最重要的幾個技術細節來詳細講解一下.

首先是 ECMP 等價路由功能, 它可以讓交換機或者路由器使用多條不同鏈路而達到相同的目的地址, 一般的物理交換機都是支持該協議的, 只要打開該選項即可.

在物理交換機打開了 ECMP 的情況下, 對於同一個 VIP 地址, 只要有多個不同鏈路的路由信息, 交換機便可以工作, 那麽這個路由信息是從哪裏來的呢?

這個時候就輪到 Maglev 上場了, 首先每一個 Maglev 節點都會和核心交換機建立 BGP 連接, BGP 連接建立之後, Maglev 會通過該連接告訴交換機某某某 IP 我是可達的, 如果多個 Maglev 都告訴交換機說某某某 IP 我是可達的, 交換機上面便會記錄多條類似於下面的路由條目:

<vip> via <Maglev1_IP> dev eth0
<vip> via <Maglev2_IP> dev eth0
<vip> via <Maglev3_IP> dev eth0
....

這個時候交換機在啟用 ECMP 路由功能的情況下, 會根據上述的路由信息將數據包均衡的發送給多個 Maglev 節點, 好了, 這個時候數據包到了 Maglev 節點, 那麽 Maglev 節點本身是如何處理這些數據包的呢? 如下圖是數據包在 Maglev 節點上面的處理過程:

技術分享圖片

上面簡要的說過, Maglev 要挑選一個 Service Endpoint 然後將數據包發給選中的 Service Endpoint, 那麽兩個問題, 如何挑? 如何發?

先說 Maglev 是如何挑選 Service Endpoint 的, 首先交換機會通過簡單的一致性哈希算法將擁有相同5元組的 packet 發送給同一臺 Maglev 節點, 然後 Maglev 通過 packet 目標 IP, 也就是 VIP 來選擇對應的後端節點, 同樣的在選擇後端的時候 Maglev 也使用了一種一致性哈希算法, 這樣便可以保證同一 TCP 連接上的所有的 packet 會打到相同的 Service Endpoint 上. 選擇好後端之後, Maglev 會將該5元組對應的後端記錄在自己的 connection tracking 表中, 等到下個數據包來的時候, 只要根據包的5元組直接查詢這個 connection tracking 表即可. 那為什麽有了一致性哈希選擇後端, 還要有 connection tracking 呢? 這是因為當一個 VIP 對應的 Service Endpoint 擴容或者縮容的時候, 一致性哈希選擇的結果會發生變化, 這樣會導致同一連接上的包選擇的後端不一致, 造成網絡錯誤.

然後在說說 Maglev 是如何將數據包發送給挑好的 Service Endpoint 的, 從原理上來說, Maglev 會將收到的數據包封一層 GRE/IP 頭然後發給 Service Endpoint, 相應的 Service Endpoint 端需要對收到的 packet 進行解包, 還有一種比較簡單的修改方式, 如果 Maglev 節點和 Service Endpoint 是在一個二層網絡裏的話, 那麽只要修改數據包的目標 mac 地址為選中的 Service Endpoint 的 mac 地址便可以將數據包發送過去, 後端也不需要進行解包. 修改好數據包之後, Maglev 只要把修改好的包從相應的網卡上發出去即可. 這裏涉及到了讀包寫包的問題, 如果直接使用 Linux Kernel 提供的方法來直接讀寫 packet, 會發現性能不能滿足需求, 在這裏可以使用一些 Kernel Bypass 的技術來做, 比如 dpdk 或者其他 Kernel Bypass 的技術.

至此, Maglev 最重要的原理已經講清楚了, 當然還有更細節的, 比如 Maglev 的一致性哈希算法是如何實現的等等, 這裏不再贅述, 如果你想更加深入的了解可以看看 Maglev 的論文. 本文也是對 Maglev 論文的一個簡單總結, 其中如果有理解錯誤或者不準確的地方也歡迎指正.

Maglev 論文下載

Maglev: A Fast and Reliable Software Network Load Balancer

最後, 你也可以到我自己搭建的博客上查看這篇文章:

http://codekiller.cn/2017/05/...

Google Maglev 牛逼的網絡負載均衡器(轉)