Skip to content

Commit ade136a

Browse files
committed
golang版 grpc源码浅析
1 parent 8de132a commit ade136a

File tree

1 file changed

+23
-4
lines changed

1 file changed

+23
-4
lines changed

protobuf/golang版 grpc源码浅析.md

+23-4
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,9 @@
22

33
首先,我最关心的是,他是怎么处理数据流的。GRPC框架采用了HTTP2作为通讯协议,而HTTP2是基于TCP协议(传输控制协议)。TCP协议传输数据是通过数据流的方式传输,所以grpc也绕不开数据流的处理。
44

5-
先看看发送数据函数:
5+
先看看发送数据函数:
6+
7+
stream.go
68

79
```go
810
func (cs *clientStream) SendMsg(m interface{}) (err error) {
@@ -62,6 +64,8 @@ func (cs *clientStream) SendMsg(m interface{}) (err error) {
6264

6365
prepareMsg函数如下:
6466

67+
stream.go
68+
6569
```go
6670
func prepareMsg(m interface{}, codec baseCodec, cp Compressor, comp encoding.Compressor) (hdr, payload, data []byte, err error) {
6771
if preparedMsg, ok := m.(*PreparedMsg); ok {
@@ -84,6 +88,8 @@ func prepareMsg(m interface{}, codec baseCodec, cp Compressor, comp encoding.Com
8488

8589
msgHeader函数如下:
8690

91+
rpc_util.go
92+
8793
```go
8894
func msgHeader(data, compData []byte) (hdr []byte, payload []byte) {
8995
hdr = make([]byte, headerLen)
@@ -106,6 +112,8 @@ func msgHeader(data, compData []byte) (hdr []byte, payload []byte) {
106112

107113
接收消息头部代码
108114

115+
rpc_util.go
116+
109117
```go
110118
func (p *parser) recvMsg(maxReceiveMessageSize int) (pf payloadFormat, msg []byte, err error) {
111119
if _, err := p.r.Read(p.header[:]); err != nil {
@@ -137,7 +145,7 @@ func (p *parser) recvMsg(maxReceiveMessageSize int) (pf payloadFormat, msg []byt
137145
}
138146
```
139147

140-
注意,接收单个数据包最大长度为maxReceiveMessageSize ,默认是 4194304(4M)。
148+
注意,接收单个数据包最大长度为maxReceiveMessageSize (clientconn.go) ,默认是 4194304(4M)。
141149

142150
首先读取消息头部(5字节)。然后解析出压缩标志和消息包长度(不含消息头部大小)。最后根据消息长度读取消息内容。
143151

@@ -149,6 +157,8 @@ func (p *parser) recvMsg(maxReceiveMessageSize int) (pf payloadFormat, msg []byt
149157

150158
ReadAtLeast这个函数会读取指定长度数据后再返回:
151159

160+
io/io.go
161+
152162
```go
153163
func ReadAtLeast(r Reader, buf []byte, min int) (n int, err error) {
154164
if len(buf) < min {
@@ -170,7 +180,9 @@ func ReadAtLeast(r Reader, buf []byte, min int) (n int, err error) {
170180

171181
这个函数的核心就是那个for循环啦,只要读取的数据没有达到最低要求,就不断尝试读取数据,直到读够数据为止。其实粘包就在这里悄悄的实现了。
172182

173-
readClient从接收数据channel里面取出数据:
183+
readClient从接收数据channel里面取出数据:
184+
185+
internal/transport/transport.go
174186

175187
```go
176188
func (r *recvBufferReader) readClient(p []byte) (n int, err error) {
@@ -192,4 +204,11 @@ GRPC框架采用HTTP2协议,而HTTP2是用过数据帧传输数据,当数据
192204

193205
readClient就可以从接收数据channel里面去数据啦。在传输数据较小(小于16K)的情况下,单个数据帧就能传输完毕。但是如果单个数据帧不能完成数据传输,就会用到上面提到的粘包功能了(这里也可以叫做粘帧,毕竟是通过数据帧传输数据的)。
194206

195-
相信通过以上分析,能对GRPC网络通信这块有一个大概的了解。这里面并没有提到HTTP2的Hpack思想,哈夫曼编码(Huffman Coding)等实现细节。有兴趣的朋友可以自己去了解下,这些仍然值得我们学习。
207+
相信通过以上分析,能对GRPC网络通信这块有一个大概的了解。这里面并没有提到HTTP2的HPACK思想,哈夫曼编码(Huffman Coding)等实现细节。有兴趣的朋友可以自己去了解下,这些仍然值得我们学习。
208+
209+
------
210+
211+
参考地址:
212+
213+
1. https://www.okcode.net/article/60025
214+
2. https://blog.fundebug.com/2019/03/07/understand-http2-and-http3

0 commit comments

Comments
 (0)