GRPC golang版源码分析之客户端(二)
生活随笔
收集整理的這篇文章主要介紹了
GRPC golang版源码分析之客户端(二)
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
Table of Contents
- 1. 前言
- 2. 負載均衡
- 3. 相關鏈接
1?前言
前面一篇文章分析了一個grpc call的大致調用流程,順著源碼走了一遍,但是grpc中有一些特性并沒有進行分析,這篇blog主要就是分析負載均衡這個特性。負載均衡可以讓你在使用grpc調用方法是連接不同的服務器。在啟動的時候,grpc client會建立對所有服務器的連接,然后通過輪詢算法拿不同的服務器。
2?負載均衡
負載均衡是在客戶端實現的,通過在初始化一個grpc客戶端傳入一個負載均衡器,默認是通過輪詢算法每次調用時切換調用的服務器,由于是在客戶端做的,所以只能讓服務器平攤壓力,并不能實時的根據服務器的狀態來進行負載均衡。比如某一刻所有的grpc客戶端都輪到了同一個服務器(這里只是舉例)。
//在clientconn.go的DialContext函數中 go func() {var addrs []Addressif cc.dopts.balancer == nil {// Connect to target directly if balancer is nil.//如果沒有設置負載均衡器,則直接連接addrs = append(addrs, Address{Addr: target})} else {var credsClone credentials.TransportCredentialsif creds != nil {credsClone = creds.Clone()}config := BalancerConfig{DialCreds: credsClone,}//啟動一個負載均衡器,start函數會啟動一個watch監聽地址的變化,而Notify返回一個通道,在每次服務器地址變化后的最新地址信息.if err := cc.dopts.balancer.Start(target, config); err != nil {waitC <- errreturn}ch := cc.dopts.balancer.Notify()if ch == nil {// There is no name resolver installed.addrs = append(addrs, Address{Addr: target})} else {addrs, ok = <-chif !ok || len(addrs) == 0 {waitC <- errNoAddrreturn}}}//對每一個地址進行連接, 因為這是客戶端啟動時,所以需要對所有地址操作.for _, a := range addrs {if err := cc.resetAddrConn(a, false, nil); err != nil {waitC <- errreturn}}close(waitC) }() .............. //省略一些代碼 if ok {//這里開啟一個監聽goroutine,主要是監聽服務器地址變化并對新的地址建立連接,對老的地址關閉連接go cc.lbWatcher() }上面的代碼大致是說明了一個負載均衡器是怎么使用的,下面看看負載均衡具體的結構:
type Balancer interface {//啟動一個負載均衡,內部會啟動一個名稱服務器的watcher,不斷監聽地址的變化Start(target string, config BalancerConfig) errorUp(addr Address) (down func(error))//得到下一次連接的地址Get(ctx context.Context, opts BalancerGetOptions) (addr Address, put func(), err error)//從服務器得到更新的地址,這個地址是更新后的所有地址Notify() <-chan []Address//關閉負載均衡器Close() error }負載均衡器有個默認實現在balancer.go中,使用的輪詢算法。這個實現中包含了一個名字服務器的服務,我們可以通過實現一個名字服務器的接口,然后封裝到這個負載均衡器中,這樣就不需要自己實現整個負載均衡器。名字服務器的接口如下:
type Update struct {// Op indicates the operation of the update.Op Operation// Addr is the updated address. It is empty string if there is no address update.Addr string// Metadata is the updated metadata. It is nil if there is no metadata update.// Metadata is not required for a custom naming implementation.Metadata interface{} } // Resolver creates a Watcher for a target to track its resolution changes. type Resolver interface {// Resolve creates a Watcher for target.//通過一個名字得到一個watcher,監聽服務器地址變化。Resolve(target string) (Watcher, error) } // Watcher watches for the updates on the specified target. type Watcher interface {// Next blocks until an update or error happens. It may return one or more// updates. The first call should get the full set of the results. It should// return an error if and only if Watcher cannot recover.// 得到下次更新的地址Next() ([]*Update, error)// Close closes the Watcher.Close() }負載均衡器的全貌大概就這些了,其中還有些細節我沒有看到,目前來說我也不希望過早深入這些細節。所以負載均衡就到這里啦。
3?相關鏈接
總結
以上是生活随笔為你收集整理的GRPC golang版源码分析之客户端(二)的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: GRPC golang版源码分析之客户端
- 下一篇: gRPC客户端创建和调用原理解析