在上图中 DATA 帧主要承载了响应结果的数据集,图中的 gRPC Server 就是我们 RPC 方法的响应结果。
在上图中 HEADERS 帧主要承载了 gRPC 状态 和 gRPC 状态消息,图中的 grpc-status 和 grpc-message 就是我们的 gRPC 调用状态的结果。
其它步骤WINDOW_UPDATE
主要作用是管理和流的窗口控制。通常情况下打开一个连接后,服务器和客户端会立即交换 SETTINGS 帧来确定流控制窗口的大小。默认情况下,该大小设置为约 65 KB,但可通过发出一个 WINDOW_UPDATE 帧为流控制设置不同的大小。
PING/PONG
主要作用是判断当前连接是否仍然可用,也常用于计算往返时间。其实也就是 PING/PONG,大家对此应该很熟。
小结
在建立连接之前,客户端/服务端都会发送连接前言(Magic+SETTINGS),确立协议和配置项。
在传输数据时,是会涉及滑动窗口(WINDOW_UPDATE)等流控策略的。
传播 gRPC 附加信息时,是基于 HEADERS 帧进行传播和设置;而具体的请求/响应数据是存储的 DATA 帧中的。
请求/响应结果会分为 HTTP 和 gRPC 状态响应两种类型。
客户端发起 PING,服务端就会回应 PONG,反之亦可。
这块 gRPC 的基础使用,你可以看看我另外的 《gRPC 入门系列》,相信对你一定有帮助。
浅谈理解 服务端为什么四行代码,就能够起一个 gRPC Server,内部做了什么逻辑。你有想过吗?接下来我们一步步剖析,看看里面到底是何方神圣。
一、初始化 // grpc.NewServer() func NewServer(opt ...ServerOption) *Server { opts := defaultServerOptions for _, o := range opt { o(&opts) } s := &Server{ lis: make(map[net.Listener]bool), opts: opts, conns: make(map[io.Closer]bool), m: make(map[string]*service), quit: make(chan struct{}), done: make(chan struct{}), czData: new(channelzData), } s.cv = sync.NewCond(&s.mu) ... return s }这块比较简单,主要是实例 grpc.Server 并进行初始化动作。涉及如下:
lis:监听地址列表。
opts:服务选项,这块包含 Credentials、Interceptor 以及一些基础配置。
conns:客户端连接句柄列表。
m:服务信息映射。
quit:退出信号。
done:完成信号。
czData:用于存储 ClientConn,addrConn 和 Server 的 channelz 相关数据。
cv:当优雅退出时,会等待这个信号量,直到所有 RPC 请求都处理并断开才会继续处理。
二、注册 pb.RegisterSearchServiceServer(server, &SearchService{})