[譯] 現代網絡負載均衡與代理導論

2021-02-14 企業與信息安全

譯者序

本文翻譯自 Envoy 作者 Matt Klein 2017 年的一篇英文博客 Introduction to modern network load balancing and proxying 。

Service mesh 是近兩年網絡、容器編排和微服務領域最火熱的話題之一。Envoy 是目前 service mesh 數據平面的首選組件。Matt Klein 是 Envoy 的設計者和核心開發。

文章循序漸進,從最簡單的中間代理(middle proxy)負載均衡,逐步過渡到大型網際網路公 司經典的 L4/L7 兩級架構,再到包括 service mesh 在內的業界最新負載均衡實踐。原文 標題雖為 「Introduction」,但「入門」這個詞在今天已經被用爛了,無法顯示出本文甩開其 他大部分入門系列幾條街的水平,故翻譯為「導論」,以內容而論,這也確實比學校的某些導 論教材強多了。

由於譯者水平有限,本文不免存在遺漏或錯誤之處。如有疑問,請查閱原文。

以下是譯文。

近期我注意到,關於現代網絡負載均衡和代理的入門級教學材料非常稀少(dearth)。我問自己:為什麼會這樣呢?負載均衡是構建可靠的分布式系統最核心的概念之 一。因此網上一定有高質量的相關材料?我做了大量搜索,結果發現信息確實相當稀少。Wikipedia 上面負載均衡 和代理伺服器 詞條只介紹了一些概念,但並沒有深入 這些主題,尤其是和當代的微服務架構相關的部分。Google 搜索負載均衡看到的大部分都 是廠商頁面,堆砌大量熱門的技術詞彙,而無實質細節。

本文將給讀者一個關於現代負載均衡和代理的中等程度介紹,希望以此彌補這一 領域的信息缺失。誠實地說,這個主題相當龐大,足以寫一整本書出來。為了使本文不至於 過長,我將努力把一些複雜問題簡單化;視興趣和反饋情況,後面我可能會通過額外的文章 單獨討論某一主題。

好了,以上就是我寫作本文的原因。現在讓我們正式開始吧!

1 網絡負載均衡和代理(proxy)是什麼?

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.

以上定義涵蓋了計算的各個方面,不單是網絡。作業系統使用負載均衡在不同物理處理器上 調度任務,K8S 這樣的容器編排引擎通過負載均衡在計算機集群上調度任務,網絡負載均衡 器在可用的後端之間調度網絡任務。本文接下來只討論網絡負載均衡。

圖 1:網絡負載均衡架構圖

圖 1 是網絡負載均衡的高層架構圖。若干客戶端正在訪問若干後端服務,它們中間是一個 負載均衡器;從高層看,負載均衡器完成以下功能:

負載均衡使用得當可以給分布式系統帶來很多好處:

命名抽象(Naming abstraction):客戶端可以通過預設的機制訪問 LB,域名解析 工作交給 LB,這樣每個客戶端就無需知道每個後端(服務發現)。預設的機制包括內置 庫、眾所周知的 DNS/IP/port,接下來會詳細討論

容錯:通過健康檢查和多種算法,LB 可以將請求有效地路由到負載過高的後端 。這意味著運維人員可以從容地修復異常的後端,而不用慌張

成本和性能收益:分布式系統的網絡很少是同構的(homogeneous)。系統很可能跨 多個網絡 zone (可用區)和 region(相隔較遠的地理區域,這兩者都是雲計算術語, 有嚴格定義,想進一步了解請自行搜索)。在每個 zone 內部,網絡的利用率相對較低 ;zone 之間,利用率經常達到上限。(這裡利用率的衡量公式:網卡帶寬/路由器 之間帶寬)。智能負載均衡可以最大限度地將請求流量保持在 zone 內部,既提高了性 能(延遲降低),又減少了整體的系統成本(減少跨 zone 帶寬及光纖成本)

1.1 負載均衡器 vs 代理

在業內討論網絡負載均衡器的時候,負載均衡器(load balancer)和代理(proxy)兩個 術語經常(大體上)無差別混用。本文中也將沿用這種慣例,認為二者整體上是對等的。(嚴格地從學術角度來說,不是所有代理都是負載均衡器,但絕大部分代理的核心功能都包 括負載均衡。)

有人可能會說,當負載均衡內嵌到客戶端庫作為庫的一部分的時候,負載均衡器並不是一 個代理。對此我的意見是,這種區分只是給本已令人困惑的主題又增加了不必要的複雜性。本文後面會討論負載均衡器拓撲的類型,其中將把嵌入式負載均衡器拓撲作為一種特殊的代 理;應用通過內嵌的庫進行代理轉發,這個庫提供的抽象和一個位於應用進程之外的 負載均衡器是一樣的。

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

現在,當業內討論負載均衡的時候,所有解決方案通常分為兩類:L4 和 L7。這 兩者分別對應 OSI 模型的 4 層和 7 層。不過我認為使用這個術語相當不幸,在後面討論 L7 負載均衡的時候會明顯看到這一點。OSI 模型是一個很差的對負載均衡解決方案複雜度的近似,這些解決方案包含 4 層協議,例 如 TCP 和 UDP,但經常又包括一些 OSI 其他協議層的內容。比如,如果一個 L4 TCP LB 同時支持 TLS termination,那它現在是不是一個 L7 LB?

圖 2:TCP L4 termination 負載均衡

圖 2 是傳統的 L4 TCP 負載均衡器。這種情況下,客戶端建立一個 TCP 連接到 LB。LB 終止(terminate)這個連接(例如 ,立即應答 SYN 包),選擇一個後端,然後建立一個新的 TCP 連接到後端(例如,發送一 個新的 SYN 包)。不要太在意圖中的細節,我們在後面章節會專門討論 L4 負載均衡。

本節想說明的是,典型情況下,L4 負載均衡器只工作在 L4 TCP/UDP connection/session 。因此,LB 在雙向來迴轉發字節,保證屬於同一 session 的字節永遠落到同一後端。L4 LB 不感知其轉發字節所屬應用的任何細節。這些字節可能是 HTTP、Redis、MongoDB,或者 任何其他應用層協議。

1.3 L7(應用層)負載均衡

L4 負載均衡很簡單,應用範圍也很廣。那麼,相比於 L7 (應用層)負載均衡,L4 有哪些 缺點?設想如下 L4 特殊場景:

兩個 gRPC/HTTP2 客戶端想連接到後端,因此它們通過 L4 LB 建立連接

L4 LB 為每個(從客戶端)進來的連接建立一個出去的(到後端)的連接,因此 最終由兩個進來的連接和兩個出去的連接

客戶端 A 的連接每分鐘發送 1 個請求,而客戶端 B 的連接每秒發送 50 個請求

在以上場景中,選中的處理客戶端 A 請求的後端比選中的處理客戶端 B 請求的後端,負 載要相差 3000x 倍。這個問題非常嚴重,與負載均衡的目的背道而馳。而且要注意, 對任何 multiplexing,kept-alive (多路復用,保活)協議,都存在這個問題。( Multiplexing 表示通過單個 L4 連接發送並發應用的請求,kept-alive 表示當沒有主動的 請求時也不要關閉連接)。出於性能考慮(創建連接的開銷是非常大的,尤其是連接是使用 TLS 加密的時候),所有現代協議都在演進以支持 multiplexing 和 kept-alive,因此 L4 LB 的阻抗不匹配問題(impedance mismatch)隨時間越來越彰顯。這個問題被 L7 LB 解決 了。

圖 3:HTTP/2 L7 負載均衡

圖 3 是一個 L7 HTTP/2 負載均衡器。這種情況下,客戶端與 LB 只建立一個 HTTP /2 TCP 連接。LB 接下來和兩個後端建立連接。當客戶端向 LB 發送兩個 HTTP/2 流(streams )時,stream 1 會被發送到後端 1,而 stream 2 會被發送到後端 2。因此,即使不同客戶 端的請求數量差異巨大,這些請求也可以被高效地、平衡地分發到後端。這就是 L7 LB 對 現代協議如此重要的原因。L7 負載均衡具備檢測應用層流量的能力,這帶來了大量額外的 好處,我們後面會更詳細看到。

1.4 L7 負載均衡和 OSI 7 層模型

前面討論 L4 負載均衡時我說過,使用 OSI 模型描述負載均衡特性是有問題的。原因是, 對於 L7,至少按照 OSI 模型的描述,它本身就包括了負載均衡抽象的多個獨立層級( discrete layers),例如,對於 HTTP 流量考慮如下子層級:

可選的 TLS (Transport Layer Security)層。網絡領域的人們還在爭論 TLS 到底屬於 OSI 的哪一層。本文出於討論目的將假設它屬於 L7

物理 HTTP 協議(HTTP/1 或者 HTTP/2)

邏輯 HTTP 協議(headers, body data, trailers)

消息協議(gRPC, REST 等等)

一個複雜的 L7 LB 可能會提供與以上全部子層級相關的特性,而另一個 L7 LB 可能會認為 其中只有一部分才屬於 7 層的功能,因此只提供這個子集的功能。也就是說,如果要比較 負載均衡器的特性(features),L7 的範圍比 L4 的複雜的多。(當然,這裡我們只涉及 了 HTTP;Redis、Kafka、MongoDB 等等都是 L7 LB 應用層協議的例子,它們都受益於 7 層 負載均衡。)

2 負載均衡器特性

本節將簡要總結負載均衡器提供的高層特性(high level features)。但並不是所有負載 均衡器都提供這裡的所有特性。

2.1 服務發現

服務發現是負載均衡器判斷它有哪些可用後端的過程。用到的方式差異很大,這裡給出幾個 例子:

靜態配置文件

DNS

Zookeeper, Etcd, Consul 等待

Envoy 的通用數據平面 API(universal data plane API)

2.2 健康檢查

健康檢查是負載均衡器判斷它的後端是否可以接收請求的過程。大致分為兩類:

2.3 負載均衡

LB 必須保證負載是均衡的。給定一組健康的後端,如何選擇哪個後端來處理一個連接或一 個請求呢?負載均衡算法是一個相對活躍的研究領域,從簡單的隨機選擇、Round Robin, 到更複雜的考慮各種延遲和後端負載狀態的算法。最流行的負載均衡算法之一是冪次最少 請求(power of 2 least request)負載均衡。

2.4 Sticky Session(黏性會話)

對於一些特定應用,保證屬於同一 session 的請求落到同一後端非常重要。這可能需要考 慮緩存、結構複雜的臨時狀態等問題。session 的定義也並不相同,可能會包括 HTTP cookies、客戶端連接特性(properties),或者其他一些屬性。一些 L7 LB 支持 sticky session。但這裡我要說明的是,session stickiness 本質上是脆弱的(處理/保持 session 的後端會掛掉),因此如果設計的系統依賴這個特性,那要額外小心。

2.5 TLS Termination

關於 TLS 以及它在邊緣服務(edge serving)和安全的 service-to-service 通信中扮演的 角色,值得單獨寫一篇文章,因此這裡不詳細展開。許多 L7 LB 會做大量的 TLS 處理工作 ,包括 termination、證書驗證和綁定(verification and pinning)、使用 SNI 提供證書服務等等。

2.6 可觀測性(observability)

我在技術分享中喜歡說:「可觀測性、可觀測性、可觀測性。」網絡在本質上是不可靠的,LB 通常需要導出統計、跟蹤和日誌信息,以幫助運維判斷出了什麼問題並修復它。負載均衡器 輸出的可觀測性數據差異很大。最高級的負載均衡器提供豐富的輸出,包括數值統計、分布 式跟蹤以及自定義日誌。需要指出的是,豐富的可觀測數據並不是沒有代價的,負載均衡器 需要做一些額外的工作才能產生這些數據。但是,這些數據帶來的收益要遠遠大於為產生它 們而增加的那點性能損失。

2.7 安全和 DoS 防禦

至少(尤其)在邊緣部署拓撲(下面會看到)情況下,負載均衡器通常需要實現很多安全特 性,包括限速、鑑權和 DoS 防禦(例如,給 IP 地址打標籤及分配標識符、 tarpitting等等)。

2.8 配置和控制平面

負載均衡器要可以配置。在大型部署場景中,這可能是一項很大的工作。一般地,將配 置負載均衡器的系統稱為「控制平面」,其實現方式各異。想了解更多關於這一方面的信息, 可以參考我之前關於 service mesh 數據平面和控制平面的博客。

2.9 其他更多特性

本節對負載均衡器提供的功能做了一個非常淺的介紹。更多內容我們會在下面討論 L7 LB 的時候看到。

3 負載均衡器的拓撲類型

前面我們已經覆蓋了負載均衡器的高層概覽,L4 和 L7 負載均衡器的區別,以及負載均衡 器的功能特性等內容,接下來介紹它的分布式部署拓撲(下面介紹的每種拓撲都適用於 L4 和 L7 負載均衡器)。

3.1 中間代理(middle proxy)

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

圖 4 所示的中間代理拓撲應該是大家最熟悉的負載均衡方式。這一類型的方案包括:

硬體設備:Cisco、Juniper、F5 等公司的產品

雲軟體解決方案:Amazon 的 ALB 和 NLB,Google 的 Cloud Load Balancer

純軟體方案:HAProxy、 NGINX、Envoy 等等

中間代理模式的優點是簡單,用戶一般只需要通過 DNS 連接到 LB,其他的事情就 不用關心了。缺點是,這種模式下負載均衡器(即使已經做了集群)是單點的(single point of failure),而且橫向擴展有瓶頸。

中間代理很多情況下都是一個黑盒子,給運維帶來很多困難。例如發生故障的時候,很難判 斷問題是出在客戶端,中間代理,還是後端。

3.2 邊緣代理(edge proxy)

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

圖 5 所示的邊緣代理拓撲其實只是中間代理拓撲的一個變種,這種情況下負載均衡器是可 以從網際網路直接訪問的。這種場景下,負載均衡器通常還要提供額外的 「API 網關」功能, 例如 TLS termination、限速、鑑權,以及複雜的流量路由等等。

中間代理拓撲的優缺點對邊緣代理也是適用的。需要說明的是,對於面向網際網路的分布式系 統,部署邊緣代理通常是無法避免的。客戶端一般通過 DNS 訪問系統,而它使用什麼網 絡庫,服務方是控制不了的(下文會看到的客戶端內嵌庫或 sidecar 代理拓撲在此不適用)。另外,從安全的角度考慮,所有來自網際網路的流量都通過唯一的網關進入系統是比較好的。

3.3 客戶端內嵌庫(embedded client library)

圖 6:客戶端內嵌庫實現負載均衡

為了解決中間代理拓撲固有的單點和擴展問題,出現了一些更複雜的方案,例如將負載均衡 器已函數庫的形式內嵌到客戶端,如圖 6 所示。這些庫支持的特性差異非常大,最知名的 庫包括 Finagle、Eureka/Ribbon/Hystrix、gRPC( 大致基於一個 Google 內部系統 Stubby)。

這種拓撲的最大優點是:將 LB 的全部功能下放到每個客戶端,從而完全避免了單點 和擴展問題。缺點是:必須為公司使用的每種語言實現相應的庫。分布式架構正在變 得越來越 「polyglot」(multilingual,多語言化)。在這種情況下,為多種語言實現一個 複雜的網絡庫是非常難的(prohibitive)。最後,對大型服務架構,進行客戶端升級也是 一件極其痛苦的事情,最終很可能導致生產集群中同時運行多個版本的客戶端,增加 運維和認知(cognitive)負擔。

雖然如此,但是那些在能夠限制語言數量增加(proliferation)而且能夠解決客戶端升級 痛苦的公司,這種拓撲還是取得了成功的。

3.4 sidecar 代理

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

客戶端內嵌庫拓撲的一個變種是 sidecar 拓撲,如圖 7 所示。近年來這種拓撲非常流行, 被稱為服務網格(service mesh)。sidecar 代理模式背後的思想是:通過將流量導到其 他進程的方式,犧牲一點(延遲)性能,實現客戶端內嵌庫模式的所有好處,而無任何語言 綁定(language lock-in)。寫作本文時,最流行的 sidecar 代理有 Envoy、NGINX、 HAProxy、Linkerd。想了解 sidercar 模式負載均衡的更多信息,請查看我之前介紹 Envoy 的博客 ,以及 service mesh 數據平面 vs 控制平面的博客 。

3.5 不同拓撲類型的優缺點比較

中間代理拓撲是最簡單的負載均衡方式,缺點是單點故障、擴展性問題、以及黑盒運維

邊緣代理拓撲和中間代理拓撲類似,但一些場景必須得用這種模式

客戶端內嵌庫拓撲提供了最優的性能和擴展性,但必須為每種語言實現相應的庫,並且升 級非常痛苦

sidecar 代理拓撲性能不如客戶端內嵌庫好,但沒有後者的那些缺點

總體上我認為在 service-to-service 通信中, sidecar (service mesh)正在逐漸取代 其他所有拓撲類型。另外,在流量進入 service mesh 的地方,總是需要一個邊緣代理拓撲 負載均衡器。

4 當前 L4 負載均衡最新技術 (state of the art)4.1 L4 負載均衡還有用嗎?

我們前面已經解釋了為什麼 L7 負載均衡器對現代協議如此重要,接下來詳細討論 L7 LB 的 功能特性。這是否意味著 L4 LB 沒用了?不!雖然我認為在 service-to-service 通信中 L7 負載均衡最終會完全取代 L4 負載均衡,但 L4 負載均衡在邊緣仍然是非常有用的,因為幾 乎所有的現代大型分布式架構都是在網際網路流量接入處使用 L4/L7 兩級負載均衡架構。在邊緣 L7 負載均衡器之前部署 L4 負載均衡器的原因:

L7 LB 承擔的更多工作是複雜的分析、變換、以及應用流量路由,他們處理原始流量的能 力(按每秒處理的包數和字節數衡量)比經過優化的 L4 負載均衡器要差。這使得 L4 LB 更適合處理特定類型的攻擊,例如 SYN 泛洪、通用包(generic packet)泛洪攻擊等

L7 LB 部署的更多更頻繁,bug 也比 L4 LB 多。在 L7 之前加一層 L4 LB,可以在調整 L7 部署的時候,對其做健康檢查和流量排除(drain),這比(單純使用)現代 L4 LB 要簡單的多,後者通常使用 BGP 和 ECMP(後面會介紹)。最後,因為 L7 功能更複雜, 它們的 bug 也會比 L4 多,在前面有一層 L4 LB 能及時將有問題的 L7 LB 拉出

接下來的幾節我將介紹中間/邊緣代理 L4 LB 的幾種不同設計。這些設計通常不適用於客戶 端內嵌庫和 sidecar 代理拓撲模式。

4.2 TCP/UDP termination 負載均衡

圖 8:TCP L4 termination 負載均衡

第一種現在仍在用的 L4 LB 是 termination LB,如圖 8 所示。這和我們最 開始介紹 L4 負載均衡器時看到的圖是一樣的(圖 2)。這種模式中,會使用兩個獨立的 TCP 連接:一個用於客戶端和負載均衡器之間,一個用於負載均衡器和後端之間。

L4 負載均衡器仍然在用有兩個原因:

他們實現相對簡單

連接 terminate 的地方離客戶端越近,客戶端的性能(延遲)越好。特別地,如果在一 個有丟包的網絡(lossy network,例如蜂窩網)中將 termination LB 部署的離客戶端 很近,重傳可能就會更快的發生(retransmits are likely to happen faster prior to the data being moved to reliable fiber transit en-route to its ultimate location)。換句話說,這種負載均衡方式可能會用於入網點(POP,Point of Presence)的 raw TCP connection termination

4.3 TCP/UDP passthrough 負載均衡

圖 9:TCP passthrough 負載均衡

第二種 L4 負載均衡是 passthrough,如圖 9 所示。在這種類型中,TCP 連接不會被負載 均衡器 terminate,而是在建立連接跟蹤和網絡地址轉換(NAT)之後直接轉發給選中的後 端。我們首先來定義連接跟蹤和 NAT:

使用連接跟蹤和 NAT 技術,負載均衡器可以將大部分 raw TCP 流量從客戶端轉發到後端。例如,我們假設客戶端正在和負載均衡器 1.2.3.4:80 通信,選中的後端是 10.0.0.2:9000。當客戶端的 TCP 包到達負載均衡器時,負載均衡器會將包的目的 IP/port (從 1.2.3.4:80)換成 10.0.0.2:9000,以及將源 IP/port 換成負載均衡器 自己的 IP/port。當應答包回來的時候,負載均衡器再做相反的轉換。

為什麼這種比 terminating LB 更複雜的 LB 類型,會在某些場景中替換前者使用呢?幾點原因:

性能和資源消耗:passthrough LB 不會 terminate TCP 連接,因此無需緩存任何 TCP 連接窗口。每個連接的狀態數據非常小,通常可以通過哈希表直接查詢。因此, passthrough LB 的性能(packets per second,PPS,每秒處理的包數)要比 terminating LB 高很多

允許後端進行自主擁塞控制:TCP 擁塞控制 是一種避免發送太快導致 超過網絡帶寬或緩衝區的機制。passthrough LB 不 terminate TCP 連接,因此它不參與 擁塞控制。這使得後端可以根據應用的類型自主決定採用哪種擁塞控制算法。而且,這種 方式還使得驗證擁塞控制的改動更容易(例如,最近的 BBRrollout)

是 Direct server return (DSR) 和 L4 LB 集群化的基礎:很多高級的 L4 負載 均衡技術基於 passthrough LB,例如 DSR 和一致性哈希集群(下面討論)

4.4 DSR(直接伺服器返回)

圖 10:L4 Direct server return (DSR,直接伺服器返回)

DSR LB 如圖 10 所示,它基於 passthrough LB,對後者的改進之處是:只允許進來的流量 /請求(ingress/request)經過 LB,而出去的流量/響應(egress/response)直接 從伺服器返回到客戶端。

設計 DSR 的主要原因是:在一些場景中,響應的流量要遠遠大於請求的流量(例如典 型的 HTTP request/response 模式)。假設請求佔 10% 的流量,響應佔 90%,使用 DSR 技術,只需 1/10 的帶寬就可以滿足系統需求。因為早期的負載均衡器非常昂貴,這種 類型的優化可以極大地節省成本,還提高了負載均衡器的可靠性(流量越低肯定越好)。DSR 在如下方面擴展了 passthrough LB:

LB 仍然做一部分連接跟蹤工作。因為響應不再經過 LB,LB 無法知道 TCP 連接 的完整狀態。但是,它仍然可以根據客戶端的包以及多種類型的 idle timeout,( strongly)推測連接的狀態

與 NAT 不同,負載均衡器通常使用 GRE(Generic Routing Encapsulation)將 IP 包封 裝發送到後端。後端收到後進行解封裝,就可以拿到原始的 IP 包,裡面有客戶端的 IP 和 port 信息。因此後端可以直接將應答包發給客戶端,而需要經過 LB

DSR 非常的重要一點是:後端參與負載均衡過程。後端需要配置正確的 GRE 隧道, 視網絡設置的底層細節,GRE 可能還需要自己的連接跟蹤和 NAT

注意,不管是在 passthrough 還是 DSR 設計中,負載均衡器和後端之間的連接跟蹤、NAT 、GRE 等等都有多種設置方式。但不幸的是這個話題超出本文的討論範圍。

4.5 通過 HA pair 實現容錯

圖 11:通過 HA pair 和 連接跟蹤實現 L4 容錯

到目前為止,我們討論的都是單個 L4 LB。passthrough 和 DSR 都需要 LB 保存一些連接跟 蹤的狀態。假如 LB 掛了呢?如果一個 LB 實例掛了,那所有經過這個 LB 的連接都 會受到影響。視應用的不同,這可能會對應用性能產生很大影響。

歷史上,L4 負載均衡器是從一些廠商(Cisco、Juniper、F5 等等)購買的硬體設備,這些 設備非常昂貴,可以處理大量的網絡流量。為了避免單個負載均衡器掛掉導致應用不可用, 負載均衡器通常都是以高可用對(high availability pair)方式部署的,如圖 11 所示。典型的 HA 負載均衡器設置包括:

一對 HA 邊緣路由器提供若干虛擬 IP(virtual IP,VIP),並通過 BGP (Border Gateway Protocol) 協議通告 VIP。主(primary)邊緣路由器的 BGP 權重比備(backup )邊緣路由器的高,在正常情況下處理所有流量。(BGP 是一個非常複雜的協議,出於本 文討論目的,可以認為 BGP 就是一種對外宣告哪個網絡設備配置了哪個 IP 的機制,每個 設備有一個表示處理網絡流量的權重)

類似地,primary L4 LB 向邊緣路由器宣告它的權重比 backup LB 大,因此正常情況下它 處理所有流量

primary LB 交叉連接(cross-connected)到 backup LB,共享所有的連接跟蹤狀態。因 此,假如 primary LB 掛了,backup LB 可以馬上接管所有活動連接

兩個邊緣路由器和兩個負載均衡器都是交叉連接的。這意味著,如果一個邊緣路由器或一 個負載均衡器掛了,或者由於某種原因之前聲明的 BGP 權重收回了(withdraw), backup 馬上可以接受所有流量

以上就是許多大流量網際網路應用今天仍然在使用的架構。然而,以上架構也有很大的不足:

VIP 需要做容量規劃,並正確 sharding 給兩個負載均衡器實例。如果一個 VIP (的連 接數?)增長超過了單個 HA pair 的容量,那這個 VIP 需要分裂成多個 VIP

資源利用率很低,平穩狀態下 50% 的容量是空閒的。考慮到有史以來硬體負載均衡器都 是非常昂貴的,這意味著大量的資金沒有得到有效利用

現代分布式系統設計追求比 active/backup 更高的容錯(fault tolerance)性。例如, 理想情況下,一個系統有多個實例同時掛掉仍能繼續運行。而 HA LB pair 的主備實例同 時掛掉時,服務就徹底掛了

供應商提供的專有大型硬體設備非常昂貴,導致用戶被鎖死到廠商(vendor lock-in,即買了某個廠商的設備後,後期只能繼續買這個廠商的設備或服務)。通常期 望的是,可以用基於通用伺服器的、水平擴展性良好的純軟體方案代替這些硬體設備

4.6 基於集群和一致性哈希的容錯和可擴展

圖 12:基於負載均衡器集群和一致性哈希實現 L4 容錯和可擴展

前一節介紹了通過 HA pair 實現 L4 LB 的容錯,以及這種設計固有的問題。從 2000s 初 期到中期,大型因特性基礎設施(公司)開始設計和部署全新的大規模並行 L4 負載均衡系 統,如圖 12 所示。這些系統的設計目標是:

這種 L4 LB 設計最合適的名稱是基於集群化和一致性哈希的容錯和可擴展( fault tolerance and scaling via clustering and distributed consistent hashing)。它的工作原理如下:

N 個邊緣路由器以相同的 BGP 權重通告所有 Anycast VIP。通過 ECMP(Equal-cost, Multi-path routing)保證每個 flow 的所有包都會到達同一個邊緣路由器。一個 flow 通常是 4 元組:源 IP/port 和目的 IP/port。簡單來說,ECMP 是一種通過一致性哈 希將包分發到一組權重相同的網絡設備的方式。雖然邊緣路由器通常並不關心每個包要 發往哪裡,但一般都是希望同一 flow 的所有包都以相同路徑經過各個設備,因為這可以 避免亂序代理的性能下降

N 個 L4 LB 以相同的 BGP 權重向所有的邊緣路由器通告所有的 VIP。仍然使用 ECMP,邊緣路由器會為相同 flow 的包選擇相同的 LB

每個 L4 LB 實例會做部分連接跟蹤(partial connection tracking)工作,然後使用 一致性哈希為每個 flow 選擇 一個後端。通過 GRE 封裝將包從 LB 發送到後端

然後使用 DSR 將應答包從後端直接發送到邊緣路由器,最後到客戶端

L4 LB 用到的一致性哈希算法是一個熱門的研究領域。需要在平衡負載、最小化延遲、最 小化後端變化帶來的擾動、最小化內存開銷等等之間做取捨。關於這一話題的完整討論超 出了本篇的範圍

我們來看看以上的設計是如何避免了 HA pair 的不足的:

邊緣路由器和負載均衡器實例可以按需添加。每一層都用到了 ECMP,當新實例加入的時 候,ECMP 能最大程度地減少受影響的 flow 數量

在預留足夠的突發量(burst margin)和容錯的前提下,系統的資源利用率想達到多高就 可以到多高

邊緣路由器和負載均衡器都可以基於通用硬體搭建,成本只是傳統硬體 LB 的很小 一部分(後面有更多信息)

很多讀者可能會問:「為什麼不讓邊緣路由器通過 ECMP 直接和後端通信?為什麼我們還需 要這一層負載均衡器?」這樣做主要的原因是防止 DoS 攻擊,以及方便後端的運維。沒 有這一層負載均衡,後端就得直接參與 BGP,當對後端集群進行滾動(rolling)部署時受 影響程度會大很多。

所有現代 L4 負載均衡系統都在朝著這種設計(或其變種)演進。其中最有名的兩個分別是 來自 Google 的 Maglev 和來自 Amazon 的 Network Load Balancer 。基於這種設計的開源方案目前還沒有,但據我所知,有一家公司準備在 2018 年開源他們 的產品。對此我非常興奮,因為現代 L4 LB 是網絡領域的開源產品中仍然缺失的重要部分 。

5 當前 L7 負載均衡最新技術 (state of the art)

是的,的確如此。過去幾年見證了 L7 負載均衡器/代理的一陣復興(resurgence)浪潮, 這緊跟了分布式系統微服務化的發展趨勢。本質上,當使用更加頻繁時,天生有損的網絡( inherently faulty network)越來越難以有效運維。而且,自動擴縮容(auto scaling) 、容器調度器等技術的崛起,意味著通過靜態文件配置靜態 IP 的方式早就過時了。系統不 僅使用網絡更加頻繁,而且使用的方式越來越動態,需要負載均衡器提供更多的功能。本節 我將簡要現代 L7 負載均衡器發展最快的幾個領域。

5.1 協議支持

現代 L7 負載均衡器正在顯示地添加對更多協議的支持。負載均衡器對應用層協議了解的越 多,就可以處理越多更複雜的事情,包括觀測輸出、高級負載均衡和路由等等。例如,在寫 作本文時,Envoy 顯式支持如下 L7 協議的解析和路由:HTTP/1、HTTP/2、gRPC、Redis、 MongoDB、DynamoDB。未來可能會添加包括 MySQL 和 Kafka 在內的更多協議。

5.2 動態配置

如前面描述的,分布式系統越來越動態的本質需要同時在兩方面做投資:動態和響應式控制 。Istio 即使這種系統的一個例子。更多信息請查看我之前的 service mesh 數據平面 vs 控制平面的博客 。

5.3 高級負載均衡

L7 LB 現在一般都內置高級負載均衡的特性,例如超時、重試、限速、熔斷( circuit breaking)、流量鏡像(shadowing)、緩存、基於內容的路由等等。

5.4 可觀測性

前面在介紹通用負載均衡器特性時講到,隨著部署的系統越來越動態,debug 也越來越困難 。健壯的協議特定的(protocol specific)可觀測性輸出可能是現代 L7 LB 提供的最 重要的特性。輸出數值統計、分布式跟蹤以及自定義日誌等功能現在幾乎是 L7 負載均衡解 決方案的標配。

5.5 可擴展性

現代 L7 LB 的用戶常常希望能夠輕鬆地對它擴展以添加自定義的功能。這可以通過 編寫可插拔的過濾器,然後加載到負載均衡器實現。一些負載均衡器還支持腳本編程,典型 的是通過 Lua。

5.6 容錯

前面介紹了很多 L4 LB 容錯的內容。那麼 L7 LB 的容錯又如何呢?通常來說,我們認 為 L7 LB 是易消耗的和無狀態的(expendable and stateless)。基於通用軟體使得 L7 負載均衡器可以輕鬆地實現水平擴展。進一步,L7 LB 的處理過程和狀態跟蹤比 L4 LB 要複雜的多。搭建一個 L7 LB HA pair 技術上是可行的,但代價相當大。

總體來說,不管是在 L4 還是在 L7 負載均衡領域,業界都在從 HA pair 架構轉向基於一 致性哈希的水平可擴展架構。

5.7 其他

L7 負載均衡器正在以蹣跚的步伐演進。以 Envoy 作為例子,讀者可以查看它的 架構綜述 。

6 全局負載均衡和集中式控制平面

圖 13:全局負載均衡

未來的負載均衡會越來越將單個負載均衡器看做通用設備(commodity device)。我個人 覺得,真正的創新和商業機會全部都會在控制平面。圖 13 展示了全局負載均衡系統的一 個例子。這個例子包含如下內容:

每個 sidecar 同時和位於三個 zone 的後端通信

圖上可以看到,90% 的流量到了 zone C,而 zone A 和 B 各只有 5%

sidecar 和後端都定期向全局負載均衡器匯報狀態。這使得全局負載均衡器可以基於 延遲、代價、負載、當前失敗率等參數做出決策

全局負載均衡器定期配置每個 sidecar 的路由信息

全局負載均衡器可以做越來越複雜、單個負載均衡器無法完成的事情。例如:

自動檢測和路由 zonal failure(可用區級別失敗)

應用全局安全和路由策略

使用機器學習和神經網絡技術檢測和緩解流量異常,包括 DDoS 攻擊

提供集中式 UI 和可視化平臺,方便工程師理解和運維整個分布式系統

為了實現分布式負載均衡,作為數據平面使用的負載均衡器必須具有支持複雜的動態配置的 能力。這一話題的更多信息請參考我之前關於 Envoy’s universal data plane API 以 及service mesh data plane vs. control plane 的博客。

7 從硬體進化到軟體

到目前為止本文只是對硬體和軟體做了簡要對比,大部分內容是在介紹傳統 L4 LB HA pair 的時候。那麼,這一領域當前的趨勢是什麼呢?

上面這條 tweet 是一個很幽默的誇張,但確實很好地總結了當前的趨勢:

從歷史來說,路由器和負載均衡器都是廠商提供的專有硬體,非常昂貴。

越來越多的專有 L3/L4 網絡設備被通用伺服器、通用網卡,以及基於 IPVS、DPDK、fd.io 等框架的特殊軟體方案 代替。一臺現代數據中心的價格 $5K 以下機器,基於 DPDK 開發用戶態應用程式在 Linux 發小包,很容易就可以用滿 80Gbps的網卡帶寬。同時,人們正在將價格便宜的、ECMP 路由聚 合帶寬能力驚人的基礎路由器/交換機 ASICs 組裝成通用路由器。

NGINX、HAProxy 以及 Envoy 這樣的功能複雜的 L7 負載均衡器正在快速迭代,並不斷侵 蝕原來硬體廠商例如 F5 的地盤。因此,L7 LB 也在非常有氣勢地朝著通用軟體方案邁進。

同時,工業界幾個主要雲廠商主導的以 IaaS、CaaS、FaaA 為整體演進的趨勢,意味著將 來只有很少一部分工程師需要了解物理的網絡是如何工作的(這些就是「黑科技」)。

8 總結及展望

最後總結,本文的核心內容:

負載均衡器是現代分布式系統的一個核心組件

有兩類通用負載均衡器:L4 和 L7

L4 和 L7 負載均衡器在現代架構中都有很重要的應用場景

L4 負載均衡器正在朝著基於分布式一致性哈希的水平可擴展架構演進

L7 負載均衡器近年來投入的資源非常大,源於最近火熱的動態微服務架構的需求

全局負載均衡,以及控制平面和數據平面的分離是負載均衡的未來,將來大部分創新 和商業機會也都會在這兩個方向

對於網絡解決方案,工業界正在大步邁向通用開源硬體和軟體解決方案。我相信傳統 負載均衡廠商,比如 F5,會是最先被開源軟體和雲廠商幹掉的。傳統路由器/交換機廠商 ,例如 Arista/Cumulus 等,由於 on-premises deployments (本地部署)的需求,我認 為存在時間會更長一些,但最終會被雲廠商和他們的自研物理網絡幹掉

總體來說,我認為這是計算機網絡的一個令人振奮的時代。朝著開源和軟體方向的轉變使得 大部分系統的迭代速度有了數量級(orders of magnitude)的提高。而且,隨著分布系統 基於 serverless 設計,繼續朝著動態化的目標長徵,底層網絡和負載均衡系統的複雜 性也會成比例的(commensurately)增加。

相關焦點

  • Nginx 反向代理與負載均衡
    作者:chenhongdong連結:juejin.im/post/5b01336af265da0b8a67e5c9什麼是反向代理與負載均衡
  • Nginx代理功能與負載均衡詳解
    Nginx的代理功能與負載均衡功能是最常被用到的,關於nginx的基本語法常識與配置已在上篇文章中有說明,這篇就開門見山,先描述一些關於代理功能的配置
  • 反向代理、負載均衡!優秀的 Nginx 是如何做到的?
    基於 REST 架構風格,以統一資源描述符(Uniform Resources Identifier)URI 或者統一資源定位符(Uniform Resources Locator)URL 作為溝通依據,通過 HTTP 協議提供各種網絡服務。然而,這些伺服器在設計之初受到當時環境的局限,例如當時的用戶規模,網絡帶寬,產品特點等局限並且各自的定位和發展都不盡相同。
  • 正向代理、反向代理、Nginx負載均衡方式
    於是我先連上代理伺服器,告訴他我需要那個無法訪問網站的內容,代理伺服器去取回來,然後返回給我。從網站的角度,只在代理伺服器來取內容的時候有一次記錄,有時候並不知道是用戶的請求,也隱藏了用戶的資料,這取決於代理告不告訴網站。
  • HAProxy配置為代理與負載均衡器之實踐
    HAProxy,中文譯為高可用代理,它是一種用C語言編寫的免費,快速,可靠的解決方案,可為基於TCP/HTTP的應用程式提供高可用負載均衡和代理伺服器。在開始配置代理之前,我們來看一下HAProxy配置中的一些基本概念,如ACL,後端和前端。
  • 掃盲負載均衡
    「反向代理」的概念大於「負載均衡」,且「反向代理」的職責之一是負載均衡。「反向代理」這個概念,除了期望它具備負載均衡的功能之外,還可以做哪些功能呢?「反向代理」具備緩存功能實現緩存和動靜分離的一種手段就是在真正的後端伺服器處理請求之前,將一部分靜態數據放在「反向代理」上。
  • (實用篇)詳解 Nginx代理功能與負載均衡
    本篇文章主要介紹了詳解 Nginx代理功能與負載均衡,先描述一些關於代理功能的配置,再說明負載均衡詳細,有興趣的可以了解一下。 序言Nginx的代理功能與負載均衡功能是最常被用到的,關於nginx的基本語法常識與配置已在上篇文章中有說明,這篇就開門見山,先描述一些關於代理功能的配置,再說明負載均衡詳細。
  • 負載均衡基礎知識
    以常見的TCP為例,負載均衡設備如果要根據真正的應用層內容再選擇伺服器,只能先代理最終的伺服器和客戶端建立連接(三次握手)後,才可能接受到客戶端發送的真正應用層內容的報文,然後再根據該報文中的特定欄位,再加上負載均衡設備設置的伺服器選擇方式,決定最終選擇的內部伺服器。  負載均衡設備在這種情況下,更類似於一個代理伺服器。
  • Nginx 反向代理、負載均衡圖文教程 !
    當然很多都是隨便一說的玩笑話,聽過一笑便可,不必當真,也不必抱怨了好了,今天就直接來說一下主題吧,前端要了解一些運維的Nginx用法,內容不多,簡單看看就好,這兩個功能在工作當中就夠用了,那麼首先來看個問題,什麼是反向代理與負載均衡什麼是反向代理與負載均衡什麼是反向代理當我們有一個伺服器集群,並且伺服器集群中的每臺伺服器的內容一樣的時候,同樣我們要直接從個人電腦訪問到伺服器集群伺服器的時候無法訪問
  • 一文詳解負載均衡和反向代理的真實區別
    二、SLB 的三種傳輸模式四層SLB:配置負載均衡設備上服務類型為tcp/udp,負載均衡設備將只解析到4層,負載均衡設備與client三次握手之後就會和RS建立連接;七層SLB:配置負載均衡設備服務類型為 http/ftp/https 等,負載均衡設備將解析報文到7層,在負載均衡設備與client三次握手之後,只有收到對應七層報文,才會跟RS建立連接。
  • 負載均衡詳解
    (一種把網絡請求分散到一個伺服器集群中的可用伺服器上去的設備) 負載均衡的作用(解決的問題):1.解決並發壓力,提高應用處理性能(增加吞吐量,加強網絡處理能力);2.提供故障轉移,實現高可用;3.通過添加或減少伺服器數量,提供網站伸縮性(擴展性);4.安全防護;(負載均衡設備上做一些過濾,黑白名單等處理)二、負載均衡分類
  • 鏈路負載均衡DNS四層及七層代理解決方案
    A10設備收到DNS查詢請求,將通過負載均衡算法均衡分發到各個運營商LDNS。A10設備選擇了某運營商的LDNS,會自動選擇相應運營商鏈路並用該運營商的地址做NAT。由於A10設備根據兩條運營商鏈路的帶寬比例來分發DNS請求,解決了之前由於DNS解析地址集中在某個運營商而引起的鏈路過度佔用,使得兩條鏈路的訪問比例得到了均衡,進而保證了帶寬佔比的均衡。
  • 負載均衡原理的解析
    三、反向代理負載均衡這個肯定大家都有所接觸,因為幾乎所有主流的Web伺服器都熱衷於支持基於反向代理的負載均衡。它的核心工作就是轉發HTTP請求。例如請求靜態文件,更適合使用前面介紹的基於DNS的負載均衡方式。4、反向代理伺服器可以監控後端伺服器,比如系統負載、響應時間、是否可用、TCP連接數、流量等,從而根據這些數據調整負載均衡的策略。
  • 圖文講解,如何使用 Nginx 反向代理、負載均衡
    來源:http://t.cn/AiKual8Y學到老活到老什麼是反向代理與負載均衡Nginx反向代理與負載均衡的實現nginx配置proxy_passUpstream模塊實現負載均衡工作中的簡單使用學到老活到老前端圈一直很新
  • linux負載均衡總結性說明(四層負載/七層負載)
    詳解如下:一,什麼是負載均衡1)負載均衡(Load Balance)建立在現有網絡結構之上,它提供了一種廉價有效透明的方法擴展網絡設備和伺服器的帶寬、增加吞吐量、加強網絡數據處理能力、提高網絡的靈活性和可用性。
  • Nginx 反向代理和負載均衡策略實戰案例
    首先,nginx能做反向代理【關於反向代理和正向代理此處不做說明了,感興趣的小夥伴自行谷歌】;比方說,我想在本地使用 www.glmapper1.com 的域名去訪問www.taobao.com。 那麼這個時候我們就可以通過nginx去實現。再者,nginx能實現負載均衡,什麼是負載均衡呢?
  • 簡述負載均衡和 CDN 技術
    在計算機上負載均衡也類似如此,我們的大BOSS客戶端將請求發送至伺服器,然而一臺伺服器是無法承受很高的並發量的,我們就會將請求轉發到其他伺服器,當然真正的負載均衡架構並不是由一臺server轉發的另一臺server,而在客戶端與伺服器端中間加入了一個負責分配請求的負載均衡硬體(軟體)。
  • 負載均衡原理的概述、原理解析
    負載均衡技術的實現,主要分為以下幾種:HTTP 重定向負載;DNS 域名解析負載;反向代理負載;IP 負載 (NAT 負載和 IP tunnel 負載);直接路由 (LVS—DR);IP隧道 (LVS—TUN)      負載均衡不能狹義地理解為分配給所有實際伺服器一樣多的工作量
  • 圖解大型網站--負載均衡架構
    負載均衡(Load Balancing) 負載均衡建立在現有網絡結構之上,它提供了一種廉價有效透明的方法擴展網絡設備和伺服器的帶寬
  • 不懂負載均衡?最通俗易懂的解釋來了!
    負載均衡技術常見的軟體負載均衡技術有以下幾種:1、基於DNS的負載均衡由於在DNS伺服器中,可以為多個不同的地址配置相同的名字,最終查詢這個名字的客戶機將在解析這個名字時得到其中一個地址,所以這種代理方式是通過DNS服務中的隨機名字解析域名和IP來實現負載均衡