負載均衡泛談

【導讀】web 服務開發,部署時經常要考慮負載均衡。那麼負載均衡是什麼?都有什麼可以使用的工具和技術?

維基百科將負載均衡定義如下: 在計算中,負載均衡改進了跨多個計算資源 (如計算機、計算機集羣、網絡連接、中央處理單 元或磁盤驅動器) 的工作負載分佈。負載均衡的目的是優化資源的使用,最大限度地提高吞 吐量,最大限度地減少響應時間,並避免任何單一資源的過載。使用具有負載均衡的多個組 件而不是單個組件,可以通過冗餘提高可靠性和可用性。負載均衡通常涉及專用軟件或硬件, 如多層交換機或域名系統服務器。

上述定義適用於計算的所有方面,而不僅僅是網絡。操作系統使用負載均衡來跨 cpu 調度任務,容器編排 (如 Kubernetes) 使用負載均衡來跨計算集羣調度任務,網絡負載均衡器 使用負載均衡來跨可用後端調度網絡任務。

四層和七層負載均衡

客戶端建立一個到負載均衡 器的 TCP 連接。負載均衡器終結該連接 (即直接響應 SYN),然後選擇一個後端,並與該後端建立一個新的 TCP 連接 (即發送一個新的 SYN)。四層負載均衡器通常只在四層 TCP/UDP 連接 / 會話級別上運行。因此, 負載均衡器通過轉發數據,並確保來自同一會話的字節在同一後端結束。四層負載均衡器 不知道它正在轉發數據的任何應用程序細節。數據內容可以是 HTTP, Redis, MongoDB,或任 何應用協議。

四層負載均衡很簡單,並且仍然被廣泛使用。四層負載均衡有哪些缺點是七層 (應用) 負載均衡來解決的呢? 以下幾個四層案例:

兩個 gRPC/HTTP2 客戶端通過四層負載均衡器連接想要與一個後端通信。四層負載均衡器爲每個入站 TCP 連接創建一個出站的 TCP 連接,從而產生兩個入站和兩個出站的連接(CA ==> loadbalancer ==> SA, CB ==> loadbalancer ==> SB)。假設,客戶端 A 每分鐘發送 1 個請求,而客戶端 B 每秒發送 50 個請求,則 SA 的負載是 SB 的 50 倍。所以四層負載均衡器問題隨着時 間的推移變得越來越不均衡。

上圖 顯示了一個七層 HTTP/2 負載均衡器。在本例中,客戶端創建一個到負載均衡器的 HTTP/2 TCP 連接。負載均衡器創建連接到兩個後端。當客戶端向負載均衡器發送兩個 HTTP/2 流時,流 1 被髮送到後端 1,流 2 被髮送到後端 2。因此,即使請求負載有很大差 異的客戶端也會在後端之間實現高效地分發。這就是爲什麼七層負載均衡對現代協議如此 重要的原因。

七層負載均衡器最終將會在服務對服務通信中完全取代四層負載均衡器,但四層負載均衡器仍然是非常重要的。一般在邊緣部署中,將專用四層負載均衡器置於七層負載均衡器之前。

七層負載均衡的現狀

  1. 協議支持。Envoy 明確支持七層協議解析和路由包括 HTTP/1, HTTP2, gRPC, Redis, MongoDB,和 DynamoDB。未來可能會添加更多協議,包括 MySQL 和 Kafka。

  2. 動態配置。分佈式系統要求有可動態配置的功能來控制系統,Istio 就是這種系統的一個例子。

  3. 高級負載均衡。七層負載均衡器現在通常內置了很多高級負載均衡功能,例如超時、重試、速率限制、斷路、Shadow、緩衝、基於內容的路由等。

  4. 可觀察性。越來越動態的系統正在被部署,隨之越來越 難以調試。

  5. 可擴展性。很多負載均衡器都支持腳本,比如 Lua。

  6. 容錯

負載均衡器提供的高級功能

  1. 服務發現

  2. 靜態配置文件。

  3. DNS。

  4. Zookeeper,Etcd,Consul 等

  5. Envoy 通用數據平面 API。

  6. 健康檢查,確定後端是否可用來提供服務的過程。

  7. 主動方式: 負載均衡器按固定的時間間隔 ping 後端 (例如,向一個 / healthcheck 端點發 送 HTTP 請求) 將,來評估它的運行健康狀況。

  8. 被動方式: 負載均衡器從主要數據流來識別運行健康狀況。例如,如果連續出現三個連 接錯誤,則四層負載均衡器可能會確定後端不可用。如果連續有三個 HTTP 503 響應代 碼,則七層負載均衡器可能會確定後端不健康。

  9. 負載均衡,負載均衡器必須實現負載的均衡! 從簡單的算法 (如隨機選擇和輪詢),到考慮可變延遲和後端負載來判斷更復雜的算法。

  10. 會話保持,在某些應用程序中,對於同一會話的請求到達同一的後端非常重要。會話的定義各不相同,可能包括 HTTP cookie、客戶端連接的屬性或其 他一些屬性。

  11. TLS 終結

  12. 可觀察性, 網絡本質上是不可靠的,負載均衡 器通常負責導出統計信息,跟蹤信息和日誌,幫助管理員找出問題所在,以便他們解決問題。數據帶來的好處遠遠超過了對性能影響。

  13. 安全性和 Dos 防範

  14. 配置和控制平面,通常,配置負載均衡 器的系統稱爲 “控制平面”,其實現方式差異很大。

拓撲類型

  1. 中間代理

  2. 邊緣代理,實際上只是中間代理拓撲的一種變體

  3. 嵌入式客戶端庫,爲了避免中間代理拓撲固有的單點故障和擴展問題,更成熟的基礎架構已朝着 通過將負載均衡嵌入到客戶端庫的方式來實現。

  4. Sidecar 代理,嵌入式客戶端庫負載均衡的一種變體。Sidecar 代理背後的思路是,以各進程間通信而導致的輕微延遲損失 爲代價,無需任何編程語言鎖定即可獲得嵌入式庫方法的各種優點。

代理的其它實現方式

通過 iptables 實現 proxy

深入理解 Kubernetes 網絡模型 - 自己實現 kube-proxy 的功能用戶空間代理程序的主要瓶頸來自內核 - 用戶空間切換和數據複製。如果我們可以完全在內核空間中實現代理,它將在性能上大大提高,從而擊敗用戶空間的代理。iptables 可用於實現這一目標。

通過 ipvs 實現 proxy

雖然基於 iptables 的代理在性能上優於基於用戶空間的代理,但在集羣服務過多的情況下也會導致性能嚴重下降。本質上,這是因爲 iptables 判決是基於鏈的,它是一個複雜度爲 O(n) 的線性算法。iptables 的一個好的替代方案是 IPVS——內核中的 L4 負載均衡器,它在底層使用 ipset(哈希實現),因此複雜度爲 O(1)。

$ yum install -y ipvsadm
$ ipvsadm -ln
# 增加service
$ ipvsadm -A -t $CLUSTER_IP:$PORT -s rr
$ ipvsadm -a -t $CLUSTER_IP:$PORT -r $POD1_IP -m
$ ipvsadm -a -t $CLUSTER_IP:$PORT -r $POD2_IP -m

通過 bpf 實現 proxy

這也是一個 O(1) 代理,但是與 IPVS 相比具有更高的性能。如果你有足夠的時間和興趣來閱讀 eBPF/BPF,可以考慮閱讀 Cilium: BPF and XDP Reference Guide

需要實現一段代碼,編譯並加載到內核中

使用 eBPF 在生產環境調試 Go 應用在功能上,eBPF 允許你在一些事件(如定時器、網絡事件或函數調用)發生時運行受限的 C 代碼,當觸發一個函數調用時,我們把這些函數稱爲 probe,它們可以用來運行在內核內的函數調用上(kprobes),也可以運行在用戶空間程序的函數調用上(uprobes)。eBPF 允許內核運行 BPF 字節碼,通常都是 C 語言的限制子集,通常先用 Clang 將 C 代碼編譯成 BPF 字節碼,然後對字節碼進行驗證以確保其安全執行。

eBPF 提供的是基本功能模塊(building blocks)和程序附着點(attachment points)。我們可以編寫 eBPF 程序來 attach 到這些 hook 點完成某些高級功能。BPF C 與普通 C 差異有多大?BPF 校驗器可能最清楚地見證了近幾年 BPF C 的發展歷史。現在我們有了 BPF-to-BPF 函數調用、有限循環(bounded loops)、全局變量、靜態 鏈接(static linking)、BTF(BPF Type Format,在 tracing 場景尤其有用;其 他方面也有用到,使內核成爲可自描述的 self-descriptive)、 單個 BPF 程序的最大指令數(instructions/program)從原來的 4096 條放大到了 100 萬條。

轉自:bert.li@ximalaya.com

qiankunli.github.io/2020/09/18/load_balance.html

本文由 Readfog 進行 AMP 轉碼,版權歸原作者所有。
來源https://mp.weixin.qq.com/s/lNxEskUSvte1kRfwnV9MQg