syntax = "proto3"; package servers; // The greeter service definition. service Greeter { // Sends a greeting rpc SayHello (HelloRequest) returns (HelloReply) {} } // The request message containing the user's name. message HelloRequest { string name = 1; } // The response message containing the greetings message HelloReply { string message = 1; }
conn, err := grpc.Dial("localhost:8080", grpc.WithInsecure())
建立一個 ClientConn
並將傳入的 DialOption
應用到 ClientConn
的 dopts (dialOptions)
字段上。 設置默認的編解碼類 protoCodec
, backoff配置,負載均衡策略(roundRobin
)。服務器
從負載均衡器中拿到地址列表,啓動goroutine鏈接各個地址(看下面的<鏈接address>),主協程設置超時時間(根據 dopts.timeout)
),在超時時間內等待鏈接完成。負載均衡
若是有地址列表監控Watcher
(當負載均衡設置了naming.Resolver
時會有),異步監控地址列表的變更(變更時更新 ClientConn
的鏈接列表 conns
)。異步
若是 dopts.insecure
爲false,檢查證書相關信息。編碼
將建立的 addrConn
放入到 ClientConn
的 conns
map中,並銷燬被替換的 addrConn
。code
重置 Transport
:server
鏈接地址,一旦出錯,重試,重試間隔時間由 dopts.bs
指定。協程
若是沒出錯則調用負載均衡的Up方法(標記一下這個地址已經鏈接了而已)。rpc
監控 Transport
: 若是有錯誤發生就重置 Transport
(關閉以前的,從新鏈接一個)。源碼
c := servers.NewGreeterClient(conn) reply, err := c.SayHello(context.Background(), &servers.HelloRequest{"person"})
建立Client沒有什麼東西。string
調用 SayHello
時主要代碼就下面這句:
grpc.Invoke(ctx, "/servers.Greeter/SayHello", in, out, c.cc, opts...)
從 ClientConn
中獲取 Transport
。
利用獲取到的transport
建立一個 Stream
, Stream
的id每次遞增2,將 Stream
保存在transport的activeStreams
中。設置各類 header 字段。將 header 按照 frame 發送給服務端以開啓一個stream,frame最大16KB。
將 HelloRequest
編碼寫到 stream
中。
等待讀取服務器的相應到 HelloReply
。
最後關閉 stream
。
默認是沒有指定 naming.Resolver
的,因此 Start
只是將地址放入到 addrs
字段中。
若是指定了 naming.Resolver
, 會調用它返回一個 Watcher
,而後啓動 goroutine
,循環從 Watcher
中獲取地址變更的信息(增長或刪除地址),一旦地址列表變更了,就將新的地址列表發給 addrCh
這個channel。
標記地址是已經鏈接的了。
獲取上一次調用時拿到的地址的下一個地址。
若是獲取不到地址,就建立 waitCh
而後等待有人關閉這個 waitCh
。Up
和 Close
方法都會檢測並關閉 waitCh
。