Google-谷歌- 是如何做負載均衡的?Nginx|HAProxy|Maglev
在程序員的心目中,Google 出品的技術自帶光環,尤其是基礎設施領域,每一次技術揭祕都像是揭開了某種 “神祕面紗”。而今天我們要聊的主角 —— Maglev,正是 Google 在負載均衡領域的終極武器。
一、傳統負載均衡的性能瓶頸
談到負載均衡,我們最熟悉的莫過於用戶態的老牌工具:Nginx 和 HAProxy。它們靈活、配置簡單,是無數網站架構的第一選擇。
但它們有一個天然的性能瓶頸:數據包必須從網卡進入內核,再穿過一層層協議棧處理,最後到達用戶態應用再做轉發。這中間的 “堆棧” 非常深,帶來了大量不必要的系統開銷。
爲了解決這個問題,Linux 世界的 “華人之光”——LVS(Linux Virtual Server)登場了。LVS 直接工作在內核層,繞開了用戶態,大幅提高了性能。但它的配置相對複雜,對網絡環境也有更高的要求。
那麼,Google 是怎麼做的?
二、Google 負載均衡架構
對普通網站而言,一臺負載均衡器足矣。但對於 Google 這樣流量驚人的全球級巨頭,負載均衡器本身也必須能夠橫向擴展並實現高可用。於是,Google 自研了一套極致性能的解決方案:Maglev。
先來看看我們平常訪問 http://www.google.com 時,請求是如何一步步被處理的
- 第一步:DNS 層負載均衡
DNS 服務器會根據用戶的地理位置,返回一個距離最近的數據中心地址(VIP)。這是第一層橫向擴展。
- 第二步:路由器層 ECMP 分發
用戶請求到達 VIP 所對應的數據中心路由器後,ECMP 協議會將請求均勻地分發到多個 Maglev 節點上。這是第二層負載均衡。
- 第三步:DR 模式轉發減壓
Maglev 節點將請求包轉發給後端服務器,並僞造源地址爲用戶真實 IP。響應時服務器直接將數據包發回路由器,而不是再回到負載均衡器,從而大幅降低負載均衡器的處理壓力。
四、Maglev 的 “魔法”:直接把程序寫在網卡上!
Maglev 是直接和網卡共享內存的,這樣就不需要將數據包再從網卡進行一次複製到負載均衡器中,也不需要把數據包再從負載均衡器複製到網卡,網卡入口隊列,負載均衡器,網卡出口隊列共享一個數據池空間,三個指針不斷的移動處理數據包,可謂是在內存這裏做到了極致
雖然這個流程乍看之下與 LVS 的 DR 模式相似,但 Google 徹底改變了玩法:
Maglev 不是運行在內核中,而是直接繞過內核,貼着網卡運行!
在 Google 看來,即使 LVS 已經進入內核,完整的 TCP/IP 協議棧依然是性能的瓶頸。Maglev 的做法是:把程序寫在網卡上,通過讀取網卡輸入隊列的前幾個字節(即五元組:源地址、源端口、目標地址、目標端口、協議號)即可完成轉發決策,根本不需要解析 payload、序列號等冗餘信息。
這樣做有幾個驚人的優化:
-
繞過內核,減少上下文切換
-
不依賴 TCP/IP 協議棧
-
不做數據包複製,網卡入口、負載均衡器、網卡出口共享同一個數據池
這不僅極大節省了內存和 CPU 的使用,還使處理路徑異常短,性能被榨到了極致。
上圖中展示了數據包在系統中從接收、處理、發送到回收的完整流程:
-
Steering(引導)階段:系統接收數據包後,首先將其標記爲 Reserved(保留),隨後接收(Received)並處理(Processed)。此階段主要完成解析與預處理工作。
-
Packet Pool(包池)階段:處理後的數據包進入共享內存池,不同狀態(Used、Available、Unused)用於區分資源佔用情況,以實現高效複用。
-
Muxing(複用)階段:數據包準備好後進入發送隊列,發送後被回收,重新標記爲可用狀態,迴流至內存池中,進入下一個調度週期。
這種機制通過狀態標記加內存池複用,極大地減少了內存分配和回收的系統開銷,爲高併發環境下的數據轉發提供了保障。
五、真正的黑魔法:350ns 的平均處理時延
Maglev 的優化遠不止如此:。
-
每個 CPU 核心綁定獨立線程,避免 cache miss
-
避免 memory contention
-
批量處理數據包 + 定時中斷優化
最終的結果是:處理一個數據包僅需 350 納秒(ns)!在網絡設備級別,這個數據可以說是恐怖如斯。
而性能波動的來源竟然不是 Maglev,而是網卡發送數據的刷新時間和中斷等待(50 微秒)。換句話說,瓶頸不在 Maglev,而在網卡。
六、Maglev 是一個 “有狀態” 的“無狀態”集羣
傳統負載均衡器都是一個單點,而 Maglev 是一個集羣,集羣就會碰到很多的問題。嚴格來說負載均衡器不能算是一個無狀態的服務,因爲 TCP 連接本身是有狀態的,一組會話內的請求包必須轉發到相同的後端服務器,不然服務器端的 TCP 會話就亂套了。
對於單點的負載均衡器來說很好解決,記錄個轉發表裏面有每個數據包的五元組和它第一轉發到哪臺機器,來一個新的數據包查這個表就知道給誰了。而像 Maglev 這樣的集羣數據包是通過路由器 ECMP 隨機分發的,第一個數據包是這個 Maglev node 處理,下一個就不知道去哪個 Maglev node 了。而且集羣就會涉及滾動式的更新和隨機的故障, 這樣本機的轉發表也就很可能會丟失。
那怎麼保證會話一致性?
這就是 Maglev 的又一關鍵創新點:
Google 自研的 Maglev Hashing:結合一致性哈希,實現有狀態服務的無狀態化!
直接通過五元組散列到後端的同一臺固定服務器,這樣硬生生的把有狀態服務做成了無狀態。Maglev Hashing 不僅保證散列均衡,還能在節點上下線時最小化連接擾動。
這樣,Maglev 就實現了:
-
多節點轉發表一致性
-
集羣內無需同步狀態
-
實現在線升級和高可用容錯
-
節點故障不影響整體服務
相比之下,美團採用 DPDK 編寫的負載均衡器也使用了共享內存、CPU 綁定等優化思路,但還需節點間同步狀態。而 Maglev 做到了真正的分佈式無狀態轉發系統。
七、總結:Maglev,現代工程的極致典範
Maglev 是 Google 打造的一款工程極致的負載均衡器:
-
繞過內核,貼近網卡運行
-
使用共享內存池減少數據複製
-
精準控制線程與 CPU 綁定
-
實現五元組直接轉發,精簡邏輯
-
自研一致性哈希解決狀態同步難題
這不僅讓 Maglev 成爲全世界最強的負載均衡系統之一,也爲整個基礎設施架構設計提供了極具啓發性的範式。
Maglev,不只是負載均衡器,它是一場工程極致主義的實踐。
本文由 Readfog 進行 AMP 轉碼,版權歸原作者所有。
來源:https://mp.weixin.qq.com/s/uKn85SpovdT-0vxwfUbvhQ