gRPC源碼/transport/客戶端 服務端

綜述

http2Client實現自ClientTransport接口
http2Server實現自ServerTransport接口git

https://github.com/messixukej...
在liangzhiyang/annotate-grpc-go基礎上補充了部分註釋github

客戶端:http客戶端鏈接建立

原理(引自http2-spec/HTTP2中英對照版(06-29).md at master · fex-team/http2-spec · GitHub.md)):
Upon establishment of a TCP connection and determination that HTTP/2 will be used by both peers, each endpoint MUST send a connection preface as a final confirmation and to establish the initial SETTINGS parameters for the HTTP/2 connection.
在創建TCP鏈接而且檢測到HTTP/2會被各個對等端使用後,每一個端點必須發送一個鏈接序言最終確認並做爲創建HTTP/2鏈接的初始設置參數。緩存

The client connection preface starts with a sequence of 24 octets, which in hex notation are:
客戶端鏈接序言以24個字節的序列開始,以十六進制表示是:函數

0x505249202a20485454502f322e300d0a0d0a534d0d0a0d0a
(the string PRI * HTTP/2.0rnrnSMrnrn). This sequence is followed by a SETTINGS frame (Section 6.5). The SETTINGS frame MAY be empty.
(字符串PRI * HTTP/2.0rnrnSMrnrn)。這個序列後跟着一個設置幀,其可爲空幀。ui

The server connection preface consists of a potentially empty SETTINGS frame (Section 6.5) that MUST be the first frame the server sends in the HTTP/2 connection.
服務端鏈接序言包含一個有多是空的設置(SETTING)幀(章節6.5),它必須在HTTP/2鏈接中首個發送。code

To avoid unnecessary latency, clients are permitted to send additional frames to the server immediately after sending the client connection preface, without waiting to receive the server connection preface. It is important to note, however, that the server connection preface SETTINGS frame might include parameters that necessarily alter how a client is expected to communicate with the server. Upon receiving the SETTINGS frame, the client is expected to honor any parameters established.
爲了不沒必要要的延遲,容許客戶端在發送客戶端鏈接序言以後當即發送其餘額外的幀,不須要等待收到服務端鏈接序言。不過須要注意的是,服務端鏈接序言設置(SETTINGS)幀可能包含一些關於指望客戶端如何與服務端通訊的所必須修改的參數。在收到這些設置(SETTINGS)幀以後,客戶端應當遵照全部設置的參數。server

Clients and servers MUST terminate the TCP connection if either peer does not begin with a valid connection preface. A GOAWAY frame (Section 6.8) can be omitted if it is clear that the peer is not using HTTP/2.
若是任何一個端點沒有以一個有效的鏈接序言開頭,客戶端和服務端必須終止TCP鏈接。若是端點並無使用HTTP/2此時能夠省略超時(GOAWAY)幀(章節6.8)。接口

newHTTP2Client 
{
    conn=dial()
    t=基於conn創建http2Client
    framer 基於conn創建newFramer(conn),
    go t.reader() //循環讀取全部幀,並分發到對應流中
    t.conn.Write(clientPreface) //發送preface幀給服務端
    t.framer.writeSettings //發送setting幀。疑問:與writeWindowUpdate的關係。
    t.framer.writeWindowUpdate 
    go t.controller()//用於發送控制消息給服務端
}

客戶端writeWindowUpdate兩個時機,最終做用到server端對應的handleWindowUpdate:
一、newHTTP2Client->framer.writeWindowUpdate
二、io.ReadFull(s1, p)->http2Client.updateWindow->t.framer.writeWindowUpdate

客戶端:建立客戶端數據流

函數:NewStream
流程:
一、建立stream:newStream
二、fc inFlow用於接收流控
三、dec=recvBufferReader用於接收數據緩存
四、將新建立的stream加入到activeStreams字符串

客戶端:寫數據

函數:Write
流程:
一、從s.sendQuotaPool.acquire()、t.sendQuotaPool.acquire()獲取發送數據權限
二、從t.writableChan獲取寫權限。(writableChan用於控制write串行化。寫入表示釋放鎖,讀取表示獲取鎖。)
三、t.framer.writeData向服務端發送數據rpc

客戶端:讀數據

函數:reader
流程:
一、獲取setting幀
二、循環獲取全部幀,並分發給到相應的stream上。

服務端

與客戶端代碼基本相似再也不細講。主要差別是HandleStreams,該方法用於接收客戶端請求。

數據流處理:
一、handleData接收數據->數據經過Stream.write寫入Stream.buf

二、operateHeaders handle參數爲對應的數據接收處理策略。讀取Stream.buf 中寫入的數據進行相應處理。
其中server.go中實現是:
2.一、processUnaryRPC 處理流程: 接收消息p.recvMsg -> 處理md.Handler -> 發送響應s.sendResponse -> 回覆狀態t.WriteStatus
2.二、processStreamingRPC處理流程:創建serverStream -> sd.Handler -> t.WriteStatus

三、步驟2中的Handler是RegisterService注入的。

相關文章
相關標籤/搜索