gRPC客户端创建和调用原理解析(2)

ClientCallImpl的主要构造参数是MethodDescriptor和CallOptions,其中MethodDescriptor存放了需要调用RPC服务的接口名、方法名、服务调用的方式(例如UNARY类型)以及请求和响应的序列化和反序列化实现类。CallOptions则存放了RPC调用的其它附加信息,例如超时时间、鉴权信息、消息长度限制和执行客户端调用的线程池等。

设置压缩和解压缩的注册类(CompressorRegistry和DecompressorRegistry),以便可以按照指定的压缩算法对HTTP/2消息做压缩和解压缩。

ClientCallImpl实例创建完成之后,就可以调用ClientTransport,创建HTTP/2 Client,向gRPC服务端发起远程服务调用。

1.3.4. 基于Netty的HTTP/2 Client创建流程

gRPC客户端底层基于Netty4.1的HTTP/2协议栈框架构建,以便可以使用HTTP/2协议来承载RPC消息,在满足标准化规范的前提下,提升通信性能。

gRPC HTTP/2协议栈(客户端)的关键实现是NettyClientTransport和NettyClientHandler,客户端初始化流程如下所示:

(点击放大图像)

gRPC客户端创建和调用原理解析

图1-5 HTTP/2 Client创建流程

流程关键技术点解读:

1.NettyClientHandler的创建:级联创建Netty的Http2FrameReader、Http2FrameWriter和Http2Connection,用于构建基于Netty的gRPC HTTP/2客户端协议栈。

2.HTTP/2 Client启动:仍然基于Netty的Bootstrap来初始化并启动客户端,但是有两个细节需要注意:

NettyClientHandler(实际被包装成ProtocolNegotiator.Handler,用于HTTP/2的握手协商)创建之后,不是由传统的ChannelInitializer在初始化Channel时将NettyClientHandler加入到pipeline中,而是直接通过Bootstrap的handler方法直接加入到pipeline中,以便可以立即接收发送任务。

客户端使用的work线程组并非通常意义的EventLoopGroup,而是一个EventLoop:即HTTP/2客户端使用的work线程并非一组线程(默认线程数为CPU内核 * 2),而是一个EventLoop线程。这个其实也很容易理解,一个NioEventLoop线程可以同时处理多个HTTP/2客户端连接,它是多路复用的,对于单个HTTP/2客户端,如果默认独占一个work线程组,将造成极大的资源浪费,同时也可能会导致句柄溢出(并发启动大量HTTP/2客户端)。

3. WriteQueue创建:Netty的NioSocketChannel初始化并向Selector注册之后(发起HTTP连接之前),立即由NettyClientHandler创建WriteQueue,用于接收并处理gRPC内部的各种Command,例如链路关闭指令、发送Frame指令、发送Ping指令等。

HTTP/2 Client创建完成之后,即可由客户端根据协商策略发起HTTP/2连接。如果连接创建成功,后续即可复用该HTTP/2连接,进行RPC调用。

1.3.5. HTTP/2连接创建流程

HTTP/2在TCP连接之初通过协商的方式进行通信,只有协商成功,才能进行后续的业务层数据发送和接收。

HTTP/2的版本标识分为两类:

基于TLS之上构架的HTTP/2, 即HTTPS,使用h2表示(ALPN):0x68与0x32

直接在TCP之上构建的HTTP/2,即HTTP,使用h2c表示

HTTP/2连接创建,分为两种:通过协商升级协议方式和直接连接方式。

假如不知道服务端是否支持HTTP/2,可以先使用HTTP/1.1进行协商,客户端发送协商请求消息(只含消息头),报文示例如下:

GET / HTTP/1.1 Host: 127.0.0.1 Connection: Upgrade, HTTP2-Settings Upgrade: h2c HTTP2-Settings: <base64url encoding of HTTP/2 SETTINGS payload>

服务端接收到协商请求之后,如果不支持HTTP/2,则直接按照HTTP/1.1响应返回,双方通过HTTP/1.1进行通信,报文示例如下:

HTTP/1.1 200 OK Content-Length: 28 Content-Type: text/css body...

如果服务端支持HTTP/2,则协商成功,返回101结果码,通知客户端一起升级到HTTP/2进行通信,示例报文如下:

HTTP/1.1 101 Switching Protocols Connection: Upgrade Upgrade: h2c [ HTTP/2 connection...

101响应之后,服务需要发送SETTINGS帧作为连接序言,客户端接收到101响应之后,也必须发送一个序言作为回应,示例如下:

PRI * HTTP/2.0\r\n\r\nSM\r\n\r\n SETTINGS帧

客户端序言发送完成之后,可以不需要等待服务端的SETTINGS帧,而直接发送业务请求Frame。

假如客户端和服务端已经约定使用HTTP/2,则可以免去101协商和切换流程,直接发起HTTP/2连接,具体流程如下所示:

(点击放大图像)

gRPC客户端创建和调用原理解析

图1-6 HTTP/2 直接连接过程

几个关键点:

内容版权声明:除非注明,否则皆为本站原创文章。

转载注明出处:https://www.heiqu.com/13469.html