NettyClientHandler继承自Netty的Http2ConnectionHandler,是gRPC接收和发送HTTP/2消息的关键实现类,也是gRPC和Netty的交互桥梁,它的主要功能如下所示:
发送各种协议消息给gRPC服务端
接收gRPC服务端返回的应答消息头、消息体和其它协议消息
处理HTTP/2协议相关的指令,例如StreamError、ConnectionError等。
协议消息的发送:无论是业务请求消息,还是协议指令消息,都统一封装成QueuedCommand,由NettyClientHandler拦截并处理,相关代码如下所示:
(点击放大图像)
协议消息的接收:NettyClientHandler通过向Http2ConnectionDecoder注册FrameListener来监听RPC响应消息和协议指令消息,相关接口如下:
(点击放大图像)
FrameListener回调NettyClientHandler的相关方法,实现协议消息的接收和处理:
(点击放大图像)
需要指出的是,NettyClientHandler并没有实现所有的回调接口,对于需要特殊处理的几个方法进行了重载,例如onDataRead和onHeadersRead。
2.3. ProtocolNegotiator功能和源码分析ProtocolNegotiator用于HTTP/2连接创建的协商,gRPC支持三种策略并有三个实现子类:
(点击放大图像)
gRPC的ProtocolNegotiator实现类完全遵循HTTP/2相关规范,以PlaintextUpgradeNegotiator为例,通过设置Http2ClientUpgradeCodec,用于101协商和协议升级,相关代码如下所示:
(点击放大图像)
2.4. LoadBalancer功能和源码分析LoadBalancer负责客户端负载均衡,它是个抽象类,gRPC框架的使用者可以通过继承的方式进行扩展。
gRPC当前已经支持PickFirstBalancer和RoundRobinLoadBalancer两种负载均衡策略,未来不排除会提供更多的策略。
以RoundRobinLoadBalancer为例,它的工作原理如下:根据PickSubchannelArgs来选择一个Subchannel:
(点击放大图像)
再看下Subchannel的选择算法:
(点击放大图像)
即通过顺序的方式从服务端列表中获取一个Subchannel。
如果用户需要定制负载均衡策略,则可以在RPC调用时,使用如下代码:
(点击放大图像)
2.5. ClientCalls功能和源码分析ClientCalls提供了各种RPC调用方式,包括同步、异步、Streaming和Unary方式等,相关方法如下所示:
(点击放大图像)
下面一起看下RPC请求消息的发送和应答接收相关代码。
2.5.1. RPC请求调用源码分析请求调用主要有两步:请求Frame构造和Frame发送,请求Frame构造代码如下所示:
(点击放大图像)
使用PB对请求消息做序列化,生成InputStream,构造请求Frame:
(点击放大图像)
Frame发送代码如下所示:
(点击放大图像)
NettyClientHandler接收到发送事件之后,调用Http2ConnectionEncoder将Frame写入Netty HTTP/2协议栈:
(点击放大图像)