vlambda博客
学习文章列表

golang grpc-源码-网络模型

golang 的grpc库是 https://github.com/grpc/grpc-go

grpc server端和服务端网络协议是在tcp基础上的 http2协议,http2协议负责grpc基础的数据传输、连接管理、流控等, 具体的业务层service 定义是基于 protobuf的

整个的网络过程和关键点如下图


说明:

  1. http2协议是支持在一个tcp连接上, client端同时发送多个request (不同request, streamid不同),不必等待server端响应第一个request后再发送第一个, 这是http2协议的应用层多路复用,这个特点,可以大大提高单个tcp连接的使用效率。更多http2协议的细节参考https://www.jianshu.com/p/e57ca4fec26f

  2. 在http2协议的支持下, client端可以多个协程同时发送request , 而server端收到请求后,首先会在单个协程内完成 http2 frame数据帧的解码工作, 如果是个业务请求(DataFrame), 会启动一个新的协程来处理单个请求(这样保证一个tcp连接处理请求的并发能力)。grpc下每个request开一个协程的关键代码如下

//google.golang.org/grpc/server.go func (s *Server) serveStreams(st transport.ServerTransport) { defer st.Close() var wg sync.WaitGroup // HandleStreams 是注册 grpc server处理 http2 stream 数据的处理函数 st.HandleStreams(func(stream *transport.Stream) {  wg.Add(1) //每次有新request时会调用这个方法, 这个方法就是开新的协程处理请求 go func() { defer wg.Done() s.handleStream(st, stream, s.traceInfo(st, stream)) }()  }, func(ctx context.Context, method string) context.Context { if !EnableTracing { return ctx }  tr := trace.New("grpc.Recv."+methodFamily(method), method) return trace.NewContext(ctx, tr) })  wg.Wait()}
  1. grpc连接池。如果单个连接的http2 编解码能力(这个是单协程内完成)成为你的瓶颈,可以考虑连接池功能。可以参考
    https://github.com/processout/grpc-go-pool
    https://github.com/rfyiamcool/grpc-client-pool/blob/master/client.go

  2. keepalive 特性
    tcp 系统层面可以设置keepalive。但是这不是grpc的keepalive原理, grpc的keepalive 是通过有规律的 ping pong 包维持的。详细的client 和server端代码参考grpc 的feature demo
    https://github.com/grpc/grpc-go/tree/master/examples/features/keepalive

TCP KeepAlive则是为了探测/保鲜(心跳检测,连接错误检测):用于探测对端的状态及网络情况(有可能客户端崩溃、强制关闭了应用、主机不可达等等),也有保鲜功能。比如如防止nat超时。TCP keepalive则是通过发送发送侦测包实现。在Linux中通过net.ipv4.tcp_keepalive_intvl,net.ipv4.tcp_keepalive_probes,net.ipv4.tcp_keepalive_time配置。比如gnet 网络框架中的实现https://github.com/panjf2000/gnet/blob/master/netpoll/netpoll_unix.go


  1. grpc 下http2 数据包查看
    运行client的时候加入 GODEBUG=http2debug=2 环境变量可以看到 http2数据frame的发送细节
    export GODEBUG=http2debug=2 && go run grpc_temp.go


测试代码参考: 

https://github.com/cclehui/study_golang/tree/master/grpc