萬字雄文講透現代網絡負載均衡和代理技術,終於弄懂負載均衡那點事

作者:Matt Klein

譯者:崔秀龍

原題:Introduction to modern network load balancing and proxying


最近我注意到,針對負載均衡和代理這兩項現代網絡技術,有教育意義的介紹性材料相當稀缺。這引起我的思考:爲什麼會這樣?在可靠的分佈系統的架構中,負載均衡是核心概念之一,這一地位要求有對應的高質量信息。


然而經過搜索之後,發現這方面的內容的確匱乏。Wikipedia 上的 負載均衡 和 代理服務器 頁面只包含了一些相關主題的概念,這些概念的闡述,尤其是微服務架構相關的部分顯得相當概括和晦澀。Google 搜索 Load Balancing,則會出現一些供應商頁面,充斥了各種時髦用詞,卻罕有細節。


本文裏我會嘗試對現代網絡負載均衡和代理技術進行一些講解,來彌補上述的材料缺失。平心而論,相關內容中的大量主題足以支撐起一本專著。爲了符合我對博客長度的控制習慣,我會將其中一些複雜主題進行概括和提煉,用簡單的概要方式進行陳述;根據讀者的興趣和反饋,我可能會在後續文章中對某些話題的細節進行更多的闡述。

上面的內容就是我開始寫作本文的動機,下面開始正式內容。

1


網絡負載均衡和代理是什麼?

Wikipedia 對負載均衡的定義 是:

In computing, load balancing improves the distribution of workloads across multiple computing resources, such as computers, a computer cluster, network links, central processing units, or disk drives. Load balancing aims to optimize resource use, maximize throughput, minimize response time, and avoid overload of any single resource. Using multiple components with load balancing instead of a single component may increase reliability and availability through redundancy. Load balancing usually involves dedicated software or hardware, such as a multilayer switch or a Domain Name System server process.

中文版:

負載平衡(Load balancing)是一種計算機網絡技術,用來在多個計算機(計算機集羣)、網絡連接、CPU、磁盤驅動器或其他資源中分配負載,以達到最優化資源使用、最大化吞吐率、最小化響應時間、同時避免過載的目的。使用帶有負載平衡的多個服務器組件,取代單一的組件,可以通過冗餘提高可靠性。負載平衡服務通常是由專用軟件和硬件來完成。

上面的定義不僅包含了網絡,還包含了計算的所有方面。操作系統、網絡以及容器編排器等都有各自的負載均衡技術,用於使用各自的資源進行各自的任務調度。本文僅就網絡負載均衡進行探討。


圖 1:網絡負載均衡概覽


圖 1 對網絡負載均衡進行了一個高層次的概括。多個客戶端向多個後端發起資源請求,負載均衡器處於客戶端和後端之間,簡單來說完成如下任務:

  • 服務發現:系統中有哪些後端可用?這些後端的地址(也就是:負載均衡器如何同這些後端通信)?

  • 健康檢查:哪些後端是健康的可以用於接收請求?

  • 負載均衡:用什麼算法來把獨立的請求分發給健康的後端?

在分佈式系統中合理的使用負載均衡能帶來很多好處:

  • 命名抽象:每個客戶端不再需要知道每一個後端(服務發現),客戶端可以通過預定義的機制來找到負載均衡器,然後讓負載均衡器完成命名解析功能。這些機制包括內置庫,以及路人皆知的 DNS/IP/端口 地址,後面會深入討論。

  • 錯誤隔離:通過健康檢查以及一些其他的算法和技術,負載均衡器的路由方法能夠有效的繞過癱瘓或過載的後端。這樣運維人員在面對系統故障時,就可以更加從容的進行錯誤處理。

  • 成本和性能收益:分佈式系統的網絡的一致性比較差。系統通常要跨越多個網絡區域。同一區域內,網絡資源通常是低售的;而在跨區域的情況下,超售則是常態(超售和低售的鑑別,是通過網卡上可消耗的帶寬和路由器之間的可用帶寬進行比對得出的結論)。智能的負載均衡會盡可能保證通信在同一區域內進行,從而提高性能(降低延遲)並降低總體系統成本(降低區域間的帶寬和光纖需求)。

負載均衡器 vs 代理服務器

業內談到網絡負載均衡器,Load Balancer 以及 Proxy 這兩個術語經常會同樣對待,本文中也把這兩個詞條等價處理(賣弄一下:並非所有的代理都是負載均衡器,但是負載均衡是主流代理的首要功能)。

有人可能會問,有的負載均衡功能是作爲客戶端庫的內置功能完成的,這種負載均衡器就不是代理服務器。這一話題本就容易混淆,這一質問更加讓人糊塗。文中會詳述這種負載均衡器的拓撲,這種嵌入的負載均衡方式只是代理的一種特例,應用通過內嵌的庫來完成代理職能,跟典型的負載均衡器的區別僅在於進程內外而已,其整體抽象是一致的。

四層(連接/會話)負載均衡

業界在討論負載均衡技術的時候,經常會分爲兩類:L4 和 L7。這一分類來源於 OSI 模型的四層和七層的定義。OSI 模型無法很好的描述負載均衡方案中的複雜性,一個四層負載均衡在完成傳統的四層協議任務例如 UDP 和 TCP 之外,往往還會加入了其他層次的內容。例如一個四層的 TCP 負載均衡還支持 TLS 功能,這算七層負載均衡了麼?


圖 2:TCP 終端四層負載均衡

圖 2 展示了一個傳統的四層 TCP 負載均衡器。這個例子中,客戶端向負載均衡器發起了一個 TCP 連接,負載均衡器 終結 了這一連接(也就是說直接響應了 SYN),接下來選擇一個後端,然後創建了到後端的新的 TCP 連接(就是發起了新的 SYN)。圖中的細節不需太過關注,後面的四層負載均衡章節會進行詳細討論。

本節的關鍵點是四層負載均衡一般只在四層的 TCP/UDP 進行操作。籠統的說,負載均衡器負責操作這些字節,保證同一會話的字節們只跟同一個後端打交道。四層負載均衡對通信中的應用細節是一無所知的。通信內容可以是 HTTP、Redis、MongoDB 或者任何應用協議。

七層(應用)負載均衡

四層負載均衡很簡單,目前還在大面積使用。四層負載均衡有什麼短處,以至於需要七層(應用)負載均衡呢?例如下面幾個四層的案例:

  • 兩個 gRPC/HTTP2 客戶端要連接到後端,所以通過四層負載均衡器來完成這一過程。

  • 四層負載均衡器爲每個接入的 TCP 連接創建一個外發的 TCP 連接,這樣就有了兩個接入、兩個外發的連接。

  • 然而客戶端 A 的請求頻率是每分鐘 1 請求,而客戶端 B 的頻率是每秒鐘 50 請求。

在上述場景中,爲客戶端 A 服務的後端,其負載水平僅相當於爲客戶端 B 服務的後端的約 1/3000 左右,這明顯違背了負載均衡器的初衷。在所有多工、保持連接的協議中都會發生這樣的情況(多工意思是在單一四層連接中並行發送應用請求;保持連接則意味着在沒有活動請求的情況下,也不會關閉連接)。出於性能方面的考慮(創建連接的成本通常較高,尤其是當使用 TLS 對連接進行加密的情況下),所有的現代協議都包含這兩個特性,所以隨着時間的推移,四層負載均衡的負載不均的情況會越發明顯。七層負載均衡能夠解決這一問題。


圖三:HTTP/2 七層終端負載均衡


圖 3 描述了七層的 HTTP/2 負載均衡。這裏客戶端發起了對負載均衡的單個連接。負載均衡器連接到了兩個後端。當客戶端向負載均衡器發送兩個 HTTP/2 流的時候,兩個流會分別送往不同後端。這樣多工客戶端的大量不同的請求會被高效的分發給多個後端。這就是七層負載均衡對現代協議的重要性的來由(因爲對應用流量的洞察能力,七層負載均衡還有很多其他好處,後面會詳細描述)。

七層負載均衡和 OSI 模型

之前四層負載均衡章節中說過,用 OSI 模型來描述負載均衡是有困難的。OSI 描述的第七層,涵蓋了負載均衡的多方面功能的臭顯。比如對 HTTP 來說,有以下幾個低級一些的層次:

  • 可選的 TLS。網絡界對 TLS 究竟應該屬於 OSI 模型的哪一層素有爭議。爲討論方便,我們放在七層。

  • 物理的 HTTP 協議(HTTP/1或 HTTP/2)。

  • 邏輯 HTTP 協議(Header、Body 和 Trailer)。

  • 消息協議(gRPC、REST 等)。


一個成熟的的七層負載均衡器應該照顧到上面描述的每一層次。另一個七層負載均衡器可能只支持七層分類中的特性的一個子集。總而言之,七層負載均衡器的範疇包含了遠超四層的爲數衆多的功能(例子中只提到了了 HTTP;Redis、Kafka、MongoDB 等也都是七層應用協議的例子,也都應受益於七層負載均衡)。

2


負載均衡器特性

下面簡單彙總一下負載均衡器的高層功能。並非所有負載均衡器都提供了所有功能。

服務發現

服務發現就是負載均衡器用於決定可用後臺列表的過程。這一功能的實現方式花樣百出,下面舉一些例子:

  • 靜態配置文件。

  • DNS。

  • Zookeeper、Etcd、Consul 等。

  • Envoy 的 統一數據平面 API。

健康檢查

負載均衡器使用健康檢查功能,來檢測後端是否可用。健康檢查有兩種實現思路:

  • 主動式:負載均衡器週期性的向後端發送 ping (例如一個發送到/healthcheck端點的 HTTP 請求),以此判斷後端的健康情況。

  • 被動式:負載均衡器通過對主數據流的分析來確定健康情況。比如一個四層負載均衡器,在發現連續三個連接錯誤的情況下,就會判定一個後端不可用;七層負載均衡可能會在連續三個 HTTP 503 響應之後判定這一後端爲不健康狀態。

負載均衡

是的,負載均衡器必須爲負載做均衡。有了一系列的健康後端,如何選擇後端來響應一個請求或者連接呢?負載均衡算法是一個活躍的研究領域,有 Round Robin 這樣的簡單辦法,也有通過延遲和後端負載情況進行判斷的複雜方案。 Power of 2 least request load balancing 一文,介紹了最流行的兼顧性能和簡易的負載均衡算法之一。

隨機選擇兩個後端,進一步選擇其中負載較低的一個。

Session 粘連

在某些應用中有一個重要需求:同一會話的請求需要到達同一後端。對於緩存、臨時複雜狀態等場景來說這是很必要的。對於“同一會話”的定義有多種形式,可能包括 HTTP Cookie、客戶端連接的屬性以及其他屬性。很多七層負載均衡器具有一些對會話粘連的支持。然而我認爲會話粘連是一種天然易碎的情況(處理會話的後端可能會癱瘓),所以對於依賴會話的系統設計應該多加小心。

TLS 終端

TLS 這一話題,不管是邊緣服務還是服務間通訊,都值得大書特書。因此很多七層負載均衡器在 TLS 處理方面都做了大量工作,其中包含終端、證書校驗和綁定,使用 SNI 提供證書等功能。

觀測性

我常說:“觀測性、觀測性、觀測性。”,網絡是一個天生不可靠的東西,負載均衡器應該提供狀態、跟蹤以及日誌,協助運維人員甄別故障,從而進行修復。負載均衡器的檢測輸出差距很大。高級的負載均衡器供應包含數字統計、分佈式跟中和自定義日誌的大量輸出。我認爲增強的觀測性並不是從天而降的,負載均衡器需要做出很多附加工作來完成這一任務。對性能造成的負面影響,相對於這一系列數據的好處來說,不值一提。

安全性和拒絕服務攻擊防範

在邊緣部署拓撲(後面會講解)中,負載均衡器經常需要實現各種包含頻率限制、認證以及 DoS 防範(例如 IP 地址的標記和辨識、Tarpitting等方式)等在內的安全功能。

配置和控制平面

負載均衡器應該是可配置的。在大規模部署中,這是一個重要的工作量。通常來說,用來配置負載均衡器的系統被稱爲“控制平面”,會有多種實現。拙作 Service Mesh Data Plan vs Control Plan 中對這一部分內容作了更深入的探討。

還有很多

這部分只是對於負載均衡器的功能層面作了一些介紹。下面還會在七層負載均衡器方面做更多的深入討論。

3


負載均衡器的拓撲分類

我們已經對負載均衡器的概念作了一些概括的介紹,四層和七層負載均衡器的區別,以及負載均衡器特性的彙總,接下來我們會針對分佈式系統中的負載均衡器部署拓撲進行一些探討(下面的每一種拓撲都是適用於四層和七層負載均衡器的)。

中間代理


圖 4:中間代理負載均衡拓撲


圖 4 描述的這種拓撲對多數讀者來說都是最熟悉的。這一類別包括了 Cisco、Juniper、F5 等硬件產品;雲軟件解決方案例如 Amazone 的 ALB 和 NLB 以及 Google 的 Cloud Load Balancer,還有 HAProxy、NGINX 以及 Envoy 這樣的純軟件自主方案。中間代理方案的優勢在於對用戶提供的簡便性。

一般情況下用戶只要通過 DNS 連接到負載均衡器即可,無需擔心其他情況;弱勢在於,負載均衡器存在單點失敗的風險,同時也是可能的性能瓶頸。中間代理通常是一個不便運維的黑盒子。問題出現在哪裏?是客戶端還是物理網絡?是中間代理還是後端?很難界定。

邊緣代理


圖 5:邊緣代理負載均衡拓撲


圖 5 實際上是中間代理的一種變體,這種負載均衡器可以通過 Internet 進行訪問。在這一場景下,負載均衡器通常需要提供一些附加的 “API 網關”類功能,例如 TLS 終端、頻率限制、認證以及流量路由等。優勢和劣勢跟中間服代理類似。在一個大的面向 Internet 的分佈式系統中,邊緣服務器通常是一個必要的組成部分。

客戶端通常會使用某個不受服務提供商控制的網絡庫,通過 DNS 來訪問這一系統(後面將會討論的嵌入客戶庫或者 Sidecar 代理拓撲都不適合直接運行在客戶端)。另外爲了安全方面的考慮,爲所有的面向 Internet 的流量使用單一的網關來提供入站流量是一個普遍要求。

嵌入式客戶庫

圖 6:通過嵌入客戶端庫實現負載均衡


爲了克服隨中間代理而出現的單點失敗以及性能問題,很多成熟架構把負載均衡直接植入如圖 6 所示的客戶端庫中。不同的庫所支持的功能差別很大,此類產品中最知名的功能豐富的包括 Finagle、Eureka/Ribbon/Hystrix 以及 gRPC(大致基於 Google 的一個稱爲 Stubby 的內部系統)。這種方式的好處是把所有負載均衡特性完全分佈到每個客戶端,從而避免了前面說到的單點失敗和性能瓶頸。

這種做法的弱勢也很明顯,一個組織使用的所有語言,都需要實現這種客戶端庫。分佈式架構下,這種多語言支持的要求會越來越多。這種環境裏,每種語言的網絡庫實現造成的成本會讓人望而卻步。最後,在大的服務架構中進行庫升級也是一個很大的挑戰,而在生產環境中並行運行不同的版本,又會給運維造成更大壓力。

結合上面的優劣勢分析,可以知道,在能夠限制編程語言使用,並克服升級痛苦的情況下,這種架構是可以獲得成功的。

Sidecar 代理

圖 7:Sidecar 代理實現負載均衡


嵌入式客戶庫的一個變體就是圖 7 中的 Sidecar 代理拓撲。近年來,這一拓撲以 “Service Mesh” 的概念日益流行。Sidecar 代理背後的思路是,以進程間通信造成的些許延遲爲代價,在無需顧慮編程語言鎖定的情況下獲得嵌入客戶端庫的各種優點。目前流行的 Sidecar 負載均衡包括 Envoy、NGINX、HAProxy 以及 Linkerd,我的兩篇文章:Introducing Envoy 和 Service Mesh Data Plan vs Control Plan 對這種結構進行了更細緻的描寫。

不同負載均衡器拓撲的總結和優劣勢

  • 中間代理拓撲是最簡單的最典型的方式。他的弱點在於:故障單點、伸縮瓶頸以及黑箱操作。

  • 邊緣代理拓撲和中間代理類似,通常無法忽略。

  • 嵌入客戶端庫的方式提供了最好的性能和伸縮性,不過面向多種語言的開發,和升級所有服務的庫都是很大的挑戰。

  • Sidecar 代理拓撲比嵌入式客戶端庫要弱,但也避免了這種方式的兩大難點。


總的來說,我認爲在服務對服務的情況下,Sidecar 代理拓撲(Service Mesh)會逐漸代替所有其他拓撲形式。爲了處理進入 Service Mesh 之前的流量,邊緣代理拓撲會長期存在。


4


四層負載均衡的現狀

四層負載均衡器還有用麼?

本文已經談論了很多七層負載均衡器對現代協議的好處,後面還會談到七層負載均衡的功能細節。這是否意味着四層負載均衡器無需存在了?不是的。雖然我認爲最終七層負載均衡會完全在服務對服務的場景中取代四層負載均衡器,但四層負載均衡器對邊緣通信還是非常有意義的,這是因爲所有現代的大型分佈式架構都是用了兩層的四層/七層負載均衡架構來處理互聯網流量。在七層負載均衡器之前部署獨立的四層負載均衡器的好處是:

  • 七層負載均衡器要在應用層面進行更多的精密分析、變換以及路由工作,對於原始流量(每秒數據包或每秒字節數)的負載,其能力要弱於優化過的四層負載均衡器。這一現實使得四層負載均衡器更便於應對拒絕服務攻擊(例如 SYN flood、通用包 flood 攻擊等)。

  • 相對於四層負載均衡器,七層負載均衡器的開發更加活躍,部署更加頻繁,也會有更多 Bug。有了前置的四層負載均衡器,就可以在七層負載均衡器升級期間進行健康檢查和排空,現代四層負載均衡器通常使用 BGP 和 ECMP(後續章節會詳細講解),七層負載均衡的部署通常會較爲簡單。最後因爲七層負載均衡器相對來說複雜度較高,因此也更容易出現問題,有了前端的四層負載均衡,就可以在出現問題的時候利用路由功能繞過故障節點,提高系統的總體穩定性。

下文中我會講到集中不同設計的中間/邊緣四層負載均衡器。後面提到的設計通常是無法用在客戶庫或 Sidecar 拓撲中的。

TCP/UDP 終端負載均衡器

圖 8:四層終端負載均衡器


還在應用的第一種四層負載均衡器是圖 8中的終端負載均衡器。這和我們介紹四層負載均衡的時候講到的內容是一致的。這種類型的負載均衡器中,使用了兩個的獨立的 TCP 連接:一個用於客戶端和負載均衡器之間;另一個用在負載均衡器和後端之間。

四層終端負載均衡器還有兩個原因:

  1. 實現相對簡單。

  2. 靠近客戶端的連接終端對性能有顯著影響。尤其是如果客戶使用有損網絡(例如蜂窩網)的話,在進入穩定的有線傳輸到最終目的之前,是容易發生重傳的。換句話說,這種負載均衡器適用於在存在點(Point of Presence )場景下的原始 TCP 連接。


TCP/UDP 透傳負載均衡器

圖 9:透傳負載均衡器


四層負載均衡器的另一種類型就是圖 9所說的透傳負載均衡器。這種類型的負載均衡過程中,TCP連接沒有被負載均衡器終結,每個鏈接的數據包,在經過連接分析和網絡地址轉換(NAT)過程之後,都被轉發給一個選中的後端。首先讓我們定義一下連接跟蹤和 NAT:

  • 連接跟蹤:跟蹤全部活動 TCP 連接的過程。這裏包括很多內容,例如握手是否完成,是否收到 FIN,連接發呆了多久,這個連接轉發給哪一個後端等。

  • NAT:是使用連接跟蹤數據,來更改數據包的 IP/端口信息使之穿過負載均衡器的過程。


有了連接跟蹤和 NAT,負載均衡器就能把客戶端的 TCP 流量幾乎原封不動的的轉發給後端。例如客戶端同1.2.3.4:80進行通信,選中的後端是10.0.0.2:9000。客戶端的 TCP 數據包會到達位於1.2.3.4:80的負載均衡器。負載均衡器會把目標 IP 和端口替換爲10.0.0.2:9000;同時還會把源 IP 替換爲負載均衡器的 IP。當後端響應 TCP 連接時,數據包就會返回給負載均衡器,負載均衡器中的鏈接跟蹤和 NAT 再次發揮作用,反向送回數據包。

爲什麼會使用這一種負載均衡器,而不是前面提到的終端型呢?

  • 性能和資源消耗:透傳型的負載均衡器沒有終結 TCP 連接,無需緩存任何的 TCP 連接窗口。每個連接的狀態存儲非常小,通常使用高效的哈希表查詢即可。正因如此,相對終端負載均衡器來說,透傳型負載均衡器能夠處理更大數量的活動鏈接,單位時間內處理更多的數據包。

  • 允許後端進行擁塞控制TCP 擁塞控制 是一種機制,讓 Internete 端點對外發數據進行流量控制,防止超量使用帶寬和緩衝。

  • 爲直接服務器返回(Direct Server Return = DSR)做基線,以及四層負載均衡集羣:透傳負載均衡也是高級四層負載均衡(例如後面將要說到的 DSR 和使用分佈式一致性哈希的集羣)的基礎。


Direct Server Return (DSR)

圖 10:四層 DSR

圖 10展示的就是 DSR 負載均衡。DSR 構建在前文提到的透傳負載均衡器的基礎之上。DSR 是一種優化方案,只有入站/請求數據包通過負載均衡;出站/響應數據包繞過負載均衡器直接返回給客戶端。使用 DSR 方案的有趣之處在於,很多負載的響應比請求數據量大很多(比如典型的 HTTP 請求和響應)。假設 10% 的流量是請求,另外 90% 是響應,如果使用了 DSR 負載均衡,僅需要 1/10 的容量就能夠滿足系統需要。從前的負載均衡非常昂貴,這一方案能夠顯著降低系統成本並提高可靠性(更少就是更好)。DSR 負載均衡器用下面的方式擴展了透傳負載均衡的概念:

  • 由於響應包不再經過負載均衡器,所以連接跟蹤僅有部分數據,負載均衡器無法知道完整的 TCP 連接狀態。然而還是可以通過對客戶數據包的觀察,對發呆超時的情況來推斷具體狀態。

  • 負載均衡器通常使用 GRE 來封裝 IP 包,並從負載均衡器發送到後端。這樣當後端接收到封裝後的數據包,可以解包並獲得客戶端的端口和地址。這樣後端就能直接跨過負載均衡器直接發送響應包給客戶端了。

  • DSR 負載均衡器的一個重要部分就是:後端部分的參與了負載均衡過程。後端需要合理的配置 GRE 隧道,並且需要根據網絡的低級細節來配置自己的連接跟蹤以及 NAT 等。


注意不管是 DSR 還是透傳負載均衡器,其中的連接跟蹤、NAT、GRE 等組成部分都有很多不同設計方式。這些設置從負載均衡器到後端都會涉及。這部分內容超出了本文的範圍,就不再深入進行了。

使用高可用配對方式實現容錯


圖 11:使用 HA 對和連接跟蹤實現容錯


到現在,我們要考慮四層負載均衡的容錯設計了。不管是 DSR 還是透傳負載均衡都需要一定數量的鏈接跟蹤和狀態數據存儲在負載均衡器中。負載均衡器宕機了會怎樣?——所有經過這一負載均衡器的連接都會斷掉。可能對應用產生顯著影響。

歷史上,四層負載均衡器是一種從典型供應商(Cisco、Juniper、F5 等)採購的硬件。這些設備非常昂貴,能夠處理大量通信。爲了防止單點失敗導致的所有連接中斷,引發應用故障,負載均衡器通常會使用高可用配對的方式進行部署,如圖 11 所示。典型的高可用負載均衡器配置會滿足如下設計:

  • 一對高可用邊緣路由器提供一系列的虛擬 IP(VIP)。這些邊緣路由器使用邊界網關協議(BGP)來發布虛擬 IP。主要邊緣路由器的 BGP 優先級高於備用邊緣路由器,所以正常情況下他會處理所有流量(BGP 是一個超級複雜的協議;爲了行文方便,可以理解 BGP 是一種機制,這種機制讓網絡設備可以宣稱自身能夠處理來自其他網絡設備的流量,並且每個連接都會有一個權重,從而影響連接的通信)。

  • 類似的,主要四層負載均衡向 BGP 權重較高的邊緣路由器宣告可用,所以在通常情況下,他會處理所有流量。

  • 兩個邊緣路由器和兩個負載均衡器是交叉連接的,這意味着如果一個邊緣路由器或者一個負載均衡器宕機,或者因爲某些原因 BGP 宣佈失效,備用設備就會接入,承載所有流量。


上面的設置是目前很多互聯網上的高流量應用還在持續使用的方式,但是這種方案有一些副作用:

  • VIP 必須通過高可用負載均衡器對流量進行正確的分配。如果單一 VIP 的容量超過了 HA 對,則 VIP 需要分割爲多個 VIP。

  • 系統資源使用率很低。通常會有一半的容量在閒置。過去的負載均衡器非常昂貴,所以這一閒置成本也是很高的。

  • 現代分佈式系統設計要求比主備模式更好的容錯設計。例如一個系統需要在多個同時出現故障的情況下保持運行。高可用負載均衡對如果遭遇同時故障,就會導致完全癱瘓。

  • 供應商提供的硬件設備價格昂貴,會導致對特定廠商的依賴。使用支持水平擴展的軟件方案對商業硬件設施進行替換,是目前普遍存在的迫切需要。

使用分佈式一致性哈希進行容錯和伸縮


圖 12:四層負載均衡器和一致哈希實現容錯和伸縮


前文介紹了通過高可用配對的方式來進行負載均衡器的容錯設置,以及隨之而來的問題。千禧年初,一些大的互聯網基礎設施提供商開始設計和部署新的圖 12 模式的並行四層負載均衡系統。這類系統的目標是:

  • 解決使用成對 HA 模式設計的負載均衡方案帶來的所有問題。

  • 從廠商專屬的專利硬件模式的負載均衡器中遷移出來,使用標準服務器和網卡配合商業軟件方案進行替代。


四層負載均衡器的設計是 fault tolerance and scaling via clustering and distributed consistent hashing 的最佳引用,具體工作模式是:

  • N 個邊緣路由器在同一 BGP 權重上,聲明所有的 任播 VIP。使用 ECMP(等價多路徑路由) 來保證所有單一 Flow 能夠到達同一個邊緣路由器。一個 Flow 通常是一個由源 IP/端口和目的 IP/端口 構成的元組。(簡單說,ECMP 是一個在使用一致性哈希連接的獨立加權網絡上分發數據包的方式)。邊緣路由器並不在意哪些數據包去了哪裏。一般會傾向於把來自於一個 Flow 所有數據包發送給同一套連接,以此避免亂序包導致的性能損失。

  • N 個四層負載均衡器向邊緣路由器在同一個 BGP 權重上聲明所有的 VIP。再次藉助 ECMP,邊緣路由器會選擇爲同一個 Flow 選擇同一個負載均衡器。

  • 每個四層負載均衡器會進行部分的連接跟蹤,爲這一 Flow 使用一致性哈希選擇一個後端。從負載均衡器到後端的數據包會使用 GRE 進行封裝。

  • 接下來使用 DSR 將相應包直接從後端通過邊緣路由器發送會客戶端。

  • 四層負載均衡器使用的一致性哈希算法是一個活躍的研究領域,其中涉及合理分配、減小延遲、後端變更成本以及最小化內存開支等各方面要素。這方面的完整討論也超出了本文範圍。


接下來看看這種設計如何克服 HA 配對方式的缺點:

  • 新的邊緣路由器和負載均衡器可以按需加入。一致性哈希會在各個層次上使用,在加入新機器的時候,儘可能降低受影響的 Flow 數量。

  • 在保持對突發消耗的支持能力以及容錯能力的同時,可以提高資源的使用率。

  • 邊緣路由器和負載均衡都可以使用使用普通硬件,僅是傳統硬件負載均衡成本的幾分之一(下文會進一步說明)。


行文至此,有讀者可能會問:“爲什麼不讓邊緣路由器直接通過 ECMP 和後端進行通信?爲什麼我們還需要負載均衡器?”。答案是 DoS 防範以及後端運維難度。如果沒有負載均衡器支持,每個後端都需要加入 BGP,而且難於進行滾動更新。

所有的現代四層負載均衡系統都在向着這一方案(或其變體)遷移。兩個最爲公衆所知的例子就是 Google 的 Maglev 以及 Amazon 的 Network Load Balancer (NLB)目前還沒有任何開源負載均衡器實現了這一設計,然而據我所知,有公司要在 2018 年發佈一個這樣的產品。我很期待他的出現,這一產品將會填補開源網絡組件的重要空白。

當前七層負載均衡的技術狀態


Current state of the art in L7 load balancing The proxy wars in tech currently is quite literally the proxy wars. Or the "war of the proxies". Nginx plus, HAProxy, linkerd, Envoy all quite literally killing it. And proxy-as-a-service/routing-as-a-service SaaS vendors raising the bar as well. Very interesting times!

是的,的確是這樣。近幾年我們看到七層負載均衡/代理技術的開發工作開始復興。隨着分佈式微服務系統的不斷推進,這方面也會不斷進步。從基礎上看,目前對於靠不住的網絡的依賴越發嚴重,帶來更高的運維難度。從長遠看,自動伸縮、容器編排等技術的大量使用,意味着靜態 IP、靜態文件的時代已經過去了。系統不僅更多的使用網絡,而且更加動態,需要新的負載均衡功能。在本節中我們簡單歸納一下現在七層負載均衡器的功能。

協議支持

現代七層負載均衡器加入了很多不同協議的顯式支持。負載均衡器對應用通訊認識越多,就越能做好監控輸出、高級負載均衡和路由等功能。例如目前 Envoy 顯式的支持七層協議解析和路由的範圍包括 HTTP/1、HTTP/2、gRPC、Redis、MongoDB 以及 DynamoDB。包括 MySQL 和 Kafka 在內的更多協議會逐漸添加進來。

動態配置

如上文所述,分佈式系統的大行其道,需要有動態配置能力來提高系統的動態和控制能力。Istio就是一個這種系統的例子。請參考 Service Mesh Data Plan vs Control Plan 來獲取更多這方面的內容。

高級負載均衡

七層負載均衡器一般都有內置的高級負載均衡支持,例如超時、重試、頻率控制、斷路器、Shadow、緩衝、基於內容的路由等。

可觀測性


上文中也提到過,負載均衡的一個常見功能,越來越多的動態系統被部署,調試難度也水漲船高。健壯的協議規範觀測輸出可能是未來七層負載均衡器要提供的最重要功能之一。統計數字、分佈式跟蹤以及可以定義日誌的輸出,目前已經成爲對器層負載均衡解決方案的必須要求。

擴展性

現代七層負載均衡器需要能夠簡單的加入定製功能。這一功能可以通過編寫可插接過濾器,並載入到負載均衡器的方式來實現。很多負載均衡器還支持腳本擴展,例如 Lua。

容錯

在講四層負載均衡的容錯時頗費了一番口舌。七層負載均衡的容錯又怎樣呢?一般來說我們認爲七層負載均衡器(的工作負載)是無狀態的可拋棄的。使用普通軟件就能夠簡單的對七層負載均衡器進行水平擴展。另外七層負載均衡的流量處理和狀態跟蹤的複雜度要遠超四層。設置七層負載均衡器的 HA 配對在技術上是可行的,但會非常繁雜。

總的說來,不管是四層還是七層的負載均衡,業界都在嘗試走出 HA 配對模式,轉向一致性哈希爲基礎的水平擴展方式。

更多

七層負載均衡器正在高速發展。可以參考 Envoy 架構概覽

5


全局負載均衡和中心控制平面


圖 13:全局負載均衡


未來會有越來越多的獨立負載均衡器以商品設備的面目呈現。我認爲真正的創新和商業機會來自於控制平面。圖 13展示了一個全局負載均衡系統。在本例中有一些不同的東西:

  • 每個 Sidecar 代理和三個不同區域的後端進行通信。

  • 如圖,90% 的流量會被髮送到 C 區,A B 兩區分別得到 5%。

  • Sidecar 代理和後端都會週期性的向全局負載均衡器進行彙報。這樣全局負載均衡器就可以根據延遲、成本、負載、失敗率等數據進行精密決策。

  • 全局負載均衡週期性的使用當前的路由信息配置每個 Sidecar 代理。

全局負載均衡能做一些單一負載均衡器做不到的事情,例如:

  • 對分區故障的自動檢測和路由繞行。

  • 應用全局的安全和路由策略。

  • 使用機器學習和神經網絡,對異常流量進行檢測和防範,包括分佈式拒絕服務攻擊。

  • 提供中央界面和可視化支持,讓工程師能夠以聚合的角度,對整個分佈式系統進行監控和運維。

全局負載均衡器要成爲現實,他的數據平面必須具有強大的動態配置能力。請參考我的博客:Envoy's universal data plane API,以及 Service Mesh Data Plan vs Control Plan 。

6


從硬件到軟件的變革


這裏只是簡要的提到了硬件和軟件的問題,主要聚焦在四層負載均衡高可用方面的歷史問題。這一領域的業界趨勢又如何呢?

一推雖說略顯浮誇,但卻很好的描述了技術趨勢:

  • 歷史上的負載均衡器和路由器都曾經是昂貴的專屬硬件

  • 逐漸的,多數三層四層網絡設備都被替換爲通用服務器硬件和網卡,以及基於 IPVS、DPDK 和 fd.io之類的框架的特定軟件方案。一個現代的成本低於 $5k 的數據中心,運行 Linux 和自定義的基於 DPDK 的 user-space 應用,能夠輕鬆用超小數據包跑滿 80Gbps 的網絡。另外廉價的基於 ASICs 的基礎路由器/交換機也能夠完成 ECMP 路由工作,並能支撐和通用路由器同級別的帶寬和包速率。

  • Nginx、HAProxy 以及 Envoy 這樣的七層軟負載均衡,也正快速發展,逐步進入過去由 F5 這樣的廠商的專屬領域。此外,七層負載均衡器正激進的向通用軟件方案的方向邁進。

  • 同時,主要雲提供商推動的 IaaS、CaaS 以及 FaaS 潮流,使得只有一小部分人需要理解物理網絡(這屬於黑科技,以及“我們不再需要深入瞭解”的範圍了)。

7


結論,以及負載均衡器的未來


綜上所述,本文的主旨:

  • 負載均衡器是現代分佈式系統的關鍵組件。

  • 有兩種負載均衡器:四層和七層。

  • 四層和七層負載均衡器都與現代架構相關。

  • 四層負載均衡器正在朝着基於一致性哈希的水平擴展方案的方向進行遷移。

  • 由於動態微服務架構的成長,七層負載均衡器得以快速發展。

  • 控制平面和數據平面的拆分,和全局負載均衡,是負載均衡的未來發展方向和機會來源。

  • 業界正激進的邁向標準硬件和軟件的開源解決方案。我相信傳統的像 F5 這樣的負載均衡廠商會被開源軟件和雲供應商取代。傳統的路由器、交換機廠商,例如 Arista/Cumulus 等,短期內會有更好的發展,但最終也會被共有云提供商及其自研物理網絡所取代。


總的說來,我認爲這是計算器網絡的奇蹟年代。多數系統開始向開源和軟件方向轉變,極大的提高了迭代速度。未來,分佈式系統又向無服務器計算進軍,底層網絡和負載均衡系統的複雜性也勢必齊頭並進,水漲船高。



原文:https://blog.envoyproxy.io/introduction-to-modern-network-load-balancing-and-proxying-a57f6ff80236

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章