netty 系列之: 使用 netty 实现支持 http2 的服务器
简介上一篇文章中,我们提到了如何在 netty 中配置 TLS,让他支持 HTTP2。事实上 TLS 并不是 https 的一个必须要求,它只是建议的标准。那么除了 TLS 之外,还需要如何设置才能让 netty 支持 http2 呢?一起来看看吧。
基本流程 netty 支持 http2 有两种情况,第一种情况是使用 tls,在这种情况下需要添加一个 ProtocolNegotiationHandler 来对握手之后的协议进行协商,在协商之后,需要决定到底使用哪一种协议。
上一篇文章,我们已经介绍 TLS 支持 http2 的细节了,这里不再赘述,感兴趣的朋友可以查看我之前的文章。
如果不使用 tls,那么有两种情况,一种是直接使用 http1.1 了,我们需要为 http1.1 添加一个 ChannelInboundHandler 即可。
另一种情况就是使用 clear text 从 HTTP1.1 升级到 HTTP2。
HTTP/2 ClearText 也叫做 h2c,我们看一个简单的升级请求,首先是客户端请求:
GET /index HTTP/1.1Host: server.flydean.comConnection: Upgrade, HTTP2-SettingsUpgrade: h2cHTTP2-Settings: (SETTINGS payload)然后是服务器端的响应,如果服务器端不支持升级,则返回:
HTTP/1.1 200 OKContent-length: 100Content-type: text/html
(... HTTP/1.1 response ...)如果服务器支持升级,则返回:
HTTP/1.1 101 Switching ProtocolsConnection: UpgradeUpgrade: h2c
(... HTTP/2 response ...)CleartextHttp2ServerUpgradeHandler 有了上面的基本流程,我们只需要在 netty 中提供对应的 handler 类就可以解决 netty 对 http2 的支持了。
不过上面的升级流程看起来比较复杂,所以 netty 为我们提供了一个封装好的类:CleartextHttp2ServerUpgradeHandler 来实现 h2c 的功能。
这个类需要传入 3 个参数,分别是 HttpServerCodec、HttpServerUpgradeHandler 和 ChannelHandler。
HttpServerCodec 就是处理 http server 的编码类,一般我们使用 HttpServerCodec。
HttpServerUpgradeHandler 是从 http1.1 升级到 http2 的处理类。
netty 也提供了一个现成的类:HttpServerUpgradeHandler,来处理升级的编码。
HttpServerUpgradeHandler 需要两个参数,一个是 sourceCodec,也就是 http 原始的编码类 HttpServerCodec,一个是用来返回 UpgradeCodec 的工厂类,返回 netty 自带的 Http2ServerUpgradeCodec。
ChannelHandler 是真正处理 HTTP2 的 handler,我们可以根据需要对这个 handler 进行自定义。
有了 UpgradeHandler,将其加入 ChannelPipeline 即可。
Http2ConnectionHandler 不管是 HttpServerUpgradeHandler,还是 CleartextHttp2ServerUpgradeHandler,都需要传入一个真正能够处理 http2 的 handler。这个 handler 就是 Http2ConnectionHandler。
Http2ConnectionHandler 是一个实现类,它已经实现了处理各种 inbound frame events 的事件,然后将这些事件委托给 Http2FrameListener。
所以 Http2ConnectionHandler 需要跟 Http2FrameListener 配合使用。
这里要详细讲解一下 Http2FrameListener,它主要处理 HTTP2 frame 的各种事件。
先来看下 http2FrameListener 中提供的 event trigger 方法:
从上图可以看到,主要是各种 frame 的事件触发方法,其中 http2 中有这样几种 frame:
DATA frameHEADERS framePRIORITY frameRST_STREAM frameSETTINGS acknowledgment frameSETTINGS framePING framePING acknowledgmentPUSH_PROMISE frameGO_AWAY frameWINDOW_UPDATE frameUnknown Frame 这几种 frame 基本上列举了 http2 frame 中所有的类型。
我们要做的就是自定义一个 handler 类,继承 Http2ConnectionHandler,然后实现 Http2FrameListener 接口即可。
在使用 clear text 从 HTTP1.1 升级到 HTTP2 的过程中,我们需要处理两个事情,第一个事情就是处理 http1.1 使用 http 头升级到 http2,可以重写继承自 Http2ConnectionHandler 的 userEventTriggered 方法,通过判断 event 的类型是否是 UpgradeEvent,来触发对应的 Http2FrameListener 接口中的方法,比如这里的 onHeadersRead:
upgradeToHttp2Headers 方法将传入的 FullHttpRequest,转换成为 Http2Headers:
还有一个要实现的方法,就是 sendResponse 方法,将数据写回给客户端,回写需要包含 headers 和 data 两部分,如下所示:
总结到此,一个处理 clear text 从 HTTP1.1 升级到 HTTP2 的 handler 就做好了。加上之前讲解的 TLS 扩展协议的支持,就构成了一个完整的支持 http2 的 netty 服务器。
本文的例子可以参考:learn-netty4
本文已收录于 http://www.flydean.com/27-netty-http2/
最通俗的解读,最深刻的干货,最简洁的教程,众多你不知道的小技巧等你来发现!
欢迎关注我的公众号:「程序那些事」,懂技术,更懂你!
版权声明: 本文为 InfoQ 作者【程序那些事】的原创文章。
原文链接:【http://xie.infoq.cn/article/ba8dde5499fcafe2a2bd3936a】。文章转载请联系作者。
评论