做者最近用golang實現了一個TCP負載均衡器,靈感來自grpc。幾個主要的特性就是:git
項目開源地址github
先介紹幾種經常使用的負載均衡機制,如下幾種負載均衡方案介紹來自grpc服務發現&負載均衡golang
根據負載均衡實現所在的位置不一樣,一般可分爲如下四種解決方案:算法
在服務消費者和服務提供者之間有一個獨立的LB,一般是專門的硬件設備如 F5,或者基於軟件如 LVS,HAproxy等實現。LB上有全部服務的地址映射表,一般由運維配置註冊,當服務消費方調用某個目標服務時,它向LB發起請求,由LB以某種策略,好比輪詢(Round-Robin)作負載均衡後將請求轉發到目標服務。LB通常具有健康檢查能力,能自動摘除不健康的服務實例。 該方案主要問題:後端
單點問題,全部服務調用流量都通過LB,當服務數量和調用量大的時候,LB容易成爲瓶頸,且一旦LB發生故障影響整個系統;
服務消費方、提供方之間增長了一級,有必定性能開銷。瀏覽器
針對第一個方案的不足,此方案將LB的功能集成到服務消費方進程裏,也被稱爲軟負載或者客戶端負載方案。服務提供方啓動時,首先將服務地址註冊到服務註冊表,同時按期報心跳到服務註冊表以代表服務的存活狀態,至關於健康檢查,服務消費方要訪問某個服務時,它經過內置的LB組件向服務註冊表查詢,同時緩存並按期刷新目標服務地址列表,而後以某種負載均衡策略選擇一個目標服務地址,最後向目標服務發起請求。LB和服務發現能力被分散到每個服務消費者的進程內部,同時服務消費方和服務提供方之間是直接調用,沒有額外開銷,性能比較好。該方案主要問題:緩存
開發成本,該方案將服務調用方集成到客戶端的進程裏頭,若是有多種不一樣的語言棧,就要配合開發多種不一樣的客戶端,有必定的研發和維護成本;
另外生產環境中,後續若是要對客戶庫進行升級,勢必要求服務調用方修改代碼並從新發布,升級較複雜。服務器
該方案是針對第二種方案的不足而提出的一種折中方案,原理和第二種方案基本相似。
不一樣之處是將LB和服務發現功能從進程內移出來,變成主機上的一個獨立進程。主機上的一個或者多個服務要訪問目標服務時,他們都經過同一主機上的獨立LB進程作服務發現和負載均衡。該方案也是一種分佈式方案沒有單點問題,一個LB進程掛了隻影響該主機上的服務調用方,服務調用方和LB之間是進程內調用性能好,同時該方案還簡化了服務調用方,不須要爲不一樣語言開發客戶庫,LB的升級不須要服務調用方改代碼。
該方案主要問題:部署較複雜,環節多,出錯調試排查問題不方便。網絡
gRPC開源組件官方並未直接提供服務註冊與發現的功能實現,但其設計文檔已提供實現的思路,並在不一樣語言的gRPC代碼API中已提供了命名解析和負載均衡接口供擴展。併發
其基本實現原理:
服務啓動後gRPC客戶端向命名服務器發出名稱解析請求,名稱將解析爲一個或多個IP地址,每一個IP地址標示它是服務器地址仍是負載均衡器地址,以及標示要使用那個客戶端負載均衡策略或服務配置。
客戶端實例化負載均衡策略,若是解析返回的地址是負載均衡器地址,則客戶端將使用grpclb策略,不然客戶端使用服務配置請求的負載均衡策略。
負載均衡策略爲每一個服務器地址建立一個子通道(channel)。
當有rpc請求時,負載均衡策略決定那個子通道即grpc服務器將接收請求,當可用服務器爲空時客戶端的請求將被阻塞。
能夠看到第一種負載均衡是在server端進行負載均衡(也叫Proxy負載均衡),第二種和第三種負載均衡方案都是在客戶端進行的負載均衡,這兩類負載均衡各有優缺點
grpc負載均衡是上述兩種負載均衡機制的結合體,經過添加一個額外的load balancer server來實現,它基本上避免了兩種負載均衡機制的缺點。
爲何要實現一個負載均衡器,由於目前爲止沒有找到知足做者要求的負載均衡器。市面上負載均衡器大可能是proxy負載均衡器,像LVS,Haproxy,上行流量會成爲它們的瓶頸。grpc的負載均衡只是作了設計,並無實現,而且grpc負載均衡設計的初衷是per-call的,設計的目標應該是針對微服務中的API調用,而且感受grpc負載均衡設計還有改進的空間。
gobalan有一下特色:
整個系統的交互流程是下面這個樣子:
關於gobalan的更加詳細的設計原理和使用方法,參考項目地址