1. 程式人生 > >grpc的dial正常執行流程

grpc的dial正常執行流程

以下基於預設配置情況下(還有其它沒有提到的配置都取預設值):

  1. 設定了balancer(etcd等)
  2. 沒有設定WithBlock,即dialOptions.block = false
  3. 沒有設定FailOnNonTempDialError,即dialOptions.copts.FailOnNonTempDialError = false

grpc.Dial 正常的執行流程,第一次進入的時候的有些邏輯是走不到或者不太重要的都捨去不表

A. grpc.Dial()  返回一個*ClientConn

  1. 從balancer(etcd等)返回一批地址,但是這批地址暫時還是不能用的,需要等待A225

  2. A2,
    對於每一個地址依次建立連線,迴圈呼叫cc.resetAddrConn, 即
  3. A3,單獨goroutine監控balancer(etcd等)的變化(cc.lbWatcher())實時更新服務叢集地址,即
  4. 單獨goroutine監控監控ServiceConfig的變化(cc.scWatcher),可以在服務啟動後動態更新呼叫服務的配置

A2cc.resetAddrConn針對一個地址建立連線,建立一個addrConn加入到ClientConn.conns中去,主流程分為:

  1.  如果這個地址已經存在連線了,先關閉掉ac.teardown
  2. A22,ac.resetTransport,建立一個底層連線(http2),這一步預設是goroutine出去的,不會阻塞,除非呼叫WithBlock;
  3. A23,單獨goroutine監控底層連線的狀態變化(ac.transportMonitor),進行重連或者放棄

A22, ac.resetTransport裡面是一個大迴圈,重試建立連線直到成功,除非某些條件下返回(預設情況下只有被ac.teardown了,即在balance中刪除),每個迴圈裡面:

  1. 如果ac.state == Shutdown ,直接返回
  2. 將狀態改為正在連線中~~  ac.state == Connecting

  3. 計算sleepTime,這裡是根據重試的超時策略,返回兩次重試的間隔時間;即如果這次重連還是失敗,會等待sleepTime才會進入下一次迴圈
  4. A224,建立一個底層的http2連線(transport.NewClientTransport);如果是臨時錯誤, 將狀態改為短暫的失敗,ac.state = TransientFailure
    ,等待sleepTime;如果是非臨時錯誤,直接返回,預設情況下可以認為都是臨時錯誤;
  5. 將狀態改為readyac.state = Ready ,通知balancer(etcd等)這個地址連線ok了(up);這樣下次就能從balancer 中讀取到這個地址了

A224, 建立一個底層的http2連線(newHTTP2Client)

  1. dial一個tcp連線,失敗的話,預設返回一個臨時錯誤
  2. 單獨goroutine,迴圈的讀取所有的幀,並且分發到相應的流中去,如果有錯誤了,會有通知到A233
  3. 初始化http2 相關的操作(傳送setting幀等)

A23,transportMonitor 是一個單獨的goroutine,裡面是一個迴圈,會監控這個連線以下幾種情況:

  1. 如果這個連線被ac.teardown了,直接退出,不需要維護了
  2. 如果收到http2的goaway幀,再重新cc.resetAddrConn,即A2,然後當前直接退出;相當於用一個新的連線來替換
  3. 如果這個連接出錯了,置為臨時失敗ac.state = TransientFailure ,暫時不讓用,然後重試連線ac.resetTransport,即A22

A3,cc.lbWatcher監控balancer(etcd等)的變化 , 實時更新叢集服務地址

  1. balancer.Notify() 是一個channel,每當有更新的時候,從這裡讀取到所有的地址(全量而非增量)
  2. 判斷有哪些地址是新增的,哪些地址是刪除掉的

  3. 對於新增的地址執行cc.resetAddrConn,即A2

  4. 對於刪掉的地址直接ac.tearDown,通知balancer(etcd等)這個地址down了, 這樣可能會影響到A231A221

對於ac.tearDown,裡面會關閉底層的連線,修改狀態為ac.state == Shutdown,然後通知balancer(etcd等)這個地址down了,在下次輪詢的時候,就不會有這個地址了;

如果這個balancer(etcd等)收到這個地址的UP的通知,表示這個地址又OK了