一個支持高網絡吞吐量、基於機器性能評分的TCP負載均衡器gobalan
作者最近用golang實現了一個TCP負載均衡器,靈感來自grpc。幾個主要的特性就是:
- 支持高網絡吞吐量
- 實現了基於機器性能評分來分配worker節點的負載均衡算法
- 盡量做到薄客戶端,降低客戶端復雜性
背景
先介紹幾種常用的負載均衡機制,以下幾種負載均衡方案介紹來自grpc服務發現&負載均衡
根據負載均衡實現所在的位置不同,通常可分為以下四種解決方案:
集中式LB(Proxy Model)
在服務消費者和服務提供者之間有一個獨立的LB,通常是專門的硬件設備如 F5,或者基於軟件如 LVS,HAproxy等實現。LB上有所有服務的地址映射表,通常由運維配置注冊,當服務消費方調用某個目標服務時,它向LB發起請求,由LB以某種策略,比如輪詢(Round-Robin)做負載均衡后將請求轉發到目標服務。LB一般具備健康檢查能力,能自動摘除不健康的服務實例。 該方案主要問題:
單點問題,所有服務調用流量都經過LB,當服務數量和調用量大的時候,LB容易成為瓶頸,且一旦LB發生故障影響整個系統;
服務消費方、提供方之間增加了一級,有一定性能開銷。
進程內LB(Balancing-aware Client)
針對第一個方案的不足,此方案將LB的功能集成到服務消費方進程里,也被稱為軟負載或者客戶端負載方案。服務提供方啟動時,首先將服務地址注冊到服務注冊表,同時定期報心跳到服務注冊表以表明服務的存活狀態,相當於健康檢查,服務消費方要訪問某個服務時,它通過內置的LB組件向服務注冊表查詢,同時緩存並定期刷新目標服務地址列表,然后以某種負載均衡策略選擇一個目標服務地址,最后向目標服務發起請求。LB和服務發現能力被分散到每一個服務消費者的進程內部,同時服務消費方和服務提供方之間是直接調用,沒有額外開銷,性能比較好。該方案主要問題:
開發成本,該方案將服務調用方集成到客戶端的進程里頭,如果有多種不同的語言棧,就要配合開發多種不同的客戶端,有一定的研發和維護成本;
另外生產環境中,后續如果要對客戶庫進行升級,勢必要求服務調用方修改代碼並重新發布,升級較復雜。
獨立進程LB(External LB service)
該方案是針對第二種方案的不足而提出的一種折中方案,原理和第二種方案基本類似。
不同之處是將LB和服務發現功能從進程內移出來,變成主機上的一個獨立進程。主機上的一個或者多個服務要訪問目標服務時,他們都通過同一主機上的獨立LB進程做服務發現和負載均衡。該方案也是一種分布式方案沒有單點問題,一個LB進程掛了只影響該主機上的服務調用方,服務調用方和LB之間是進程內調用性能好,同時該方案還簡化了服務調用方,不需要為不同語言開發客戶庫,LB的升級不需要服務調用方改代碼。
該方案主要問題:部署較復雜,環節多,出錯調試排查問題不方便。
gRPC服務發現及負載均衡設計
gRPC開源組件官方並未直接提供服務注冊與發現的功能實現,但其設計文檔已提供實現的思路,並在不同語言的gRPC代碼API中已提供了命名解析和負載均衡接口供擴展。
其基本實現原理:
服務啟動后gRPC客戶端向命名服務器發出名稱解析請求,名稱將解析為一個或多個IP地址,每個IP地址標示它是服務器地址還是負載均衡器地址,以及標示要使用那個客戶端負載均衡策略或服務配置。
客戶端實例化負載均衡策略,如果解析返回的地址是負載均衡器地址,則客戶端將使用grpclb策略,否則客戶端使用服務配置請求的負載均衡策略。
負載均衡策略為每個服務器地址創建一個子通道(channel)。
當有rpc請求時,負載均衡策略決定那個子通道即grpc服務器將接收請求,當可用服務器為空時客戶端的請求將被阻塞。
優缺點分析
可以看到第一種負載均衡是在server端進行負載均衡(也叫Proxy負載均衡),第二種和第三種負載均衡方案都是在客戶端進行的負載均衡,這兩類負載均衡各有優缺點
Proxy負載均衡優缺點
優點
- 隱藏后端服務器。
反向代理能夠隱藏后端服務器,所有瀏覽器都不會與后端服務器直接交互,從而能夠確保調度者的控制權,提升集群的整體性能。 - 故障轉移
反向代理能夠更快速地移除故障結點。當監控程序發現某一后端服務器出現故障時,能夠及時通知反向代理服務器,並立即將其刪除。 - 合理分配任務
但反向代理服務器支持手動設定每台后端服務器的權重。我們可以根據服務器的配置設置不同的權重,權重的不同會導致被調度者選中的概率的不同。
缺點
- 調度者壓力過大
由於所有的請求都先由反向代理服務器處理,那么當請求量超過調度服務器的最大負載時,調度服務器的吞吐率降低會直接降低集群的整體性能。 - 制約擴展
當后端服務器也無法滿足巨大的吞吐量時,就需要增加后端服務器的數量,可沒辦法無限量地增加,因為會受到調度服務器的最大吞吐量的制約。
客戶端負載均衡優缺點
優點
- 客戶端和提供服務的服務器進行直連,沒有了Proxy負載均衡器的瓶頸,並且容易擴展。
缺點
- 客戶端邏輯會變得復雜,它需要追蹤服務端的機器負載和健康度,需要實現負載均衡算法。第二種負載均衡機制還依賴客戶端的實現語言,需要為不同語言實現不同的負載均衡版本。
- 客戶端必須是受信任的,因為客戶端能夠拿到所有負載均衡節點的信息。
grpc負載均衡優缺點
優點
grpc負載均衡是上述兩種負載均衡機制的結合體,通過添加一個額外的load balancer server來實現,它基本上避免了兩種負載均衡機制的缺點。
- 負載均衡節點健康度檢查和機器負載通過這個load balancer server來實現,並且復雜的負載均衡算法都由其來實現,避免了客戶端過於復雜的缺點,客戶端只是實現一些簡單的負載均衡算法。
- 服務網絡連接依然采用直連,繞過load balancer,解決了網絡吞吐量的問題。
缺點
- 客戶端仍然是需要受信任的
gobalan
為什么要實現一個負載均衡器,因為目前為止沒有找到滿足作者要求的負載均衡器。市面上負載均衡器大多是proxy負載均衡器,像LVS,Haproxy,上行流量會成為它們的瓶頸。grpc的負載均衡只是做了設計,並沒有實現,並且grpc負載均衡設計的初衷是per-call的,設計的目標應該是針對微服務中的API調用,並且感覺grpc負載均衡設計還有改進的空間。
gobalan有一下特點:
- gobalan是per-connection的,也就是一次TCP連接請求做一次負載均衡。
- gobalan所有負載均衡邏輯均在負載均衡器中實現,包括服務健康檢查,機器負載信息收集,負載均衡算法的實現。
- 客戶端只需要實現服務節點的請求和返回值解析兩個邏輯就能使用gobalan,我們需要的是超薄客戶端。
- 客戶端和服務節點采用直連,避免了proxy負載均衡的網絡帶寬瓶頸。
整個系統的交互流程是下面這個樣子:
關於gobalan的更加詳細的設計原理和使用方法,參考項目地址