当前位置: 首页 > 后端技术 > Java

Netty系列:Netty对http2报文的封装

时间:2023-04-01 21:22:10 Java

简介不管是什么协议,如果要使用,都需要转换成相应的语言才能真正应用。本文将从http2报文的结构入手,讨论netty对http2报文的封装,带你看看真正的框架到底应该走多远。http2的报文结构与http1.1的不同之处在于它使用了新的二进制帧,在客户端和服务器之间建立数据流steam来实现客户端和服务器之间的报文交换。数据流是用于发送一个或多个消息的双向字节流。消息是客户端和服务器端发送的一段逻辑上完整的数据。根据数据的大小,消息可以分为不同的帧Frame。也就是说,消息是由不同的帧组成的。Frame是http2中最小的通信单位。根据上一节的介绍,我们知道有几种类型的帧:DATAframeHEADERSframePRIORITYframeRST_STREAMframeSETTINGSacknowledgmentframeSETTINGSframePINGframePINGacknowledgmentPUSH_PROMISEframeGO_AWAYframeWINDOW_UPDATEframeUnknownframe我们来看一下其中一种httpf2UnknownFrame的一般结构:在http2中,一个TCP连接可以承载多个数据流,多个流中的不同帧可以交错发送。每个帧通过流ID标记它所属的流。有了上面http2的基本概念,我们再来看netty对http2的封装。Netty对http2的封装,Http2Stream,是一个TCP连接下的最大单元流,netty提供了接口Http2Stream。注意Http2Stream是一个接口,有两个实现类,DefaultStream和ConnectionStream。Http2Stream中有两个非常重要的属性,即id和state。id前面已经介绍过了,它是流的唯一标志。这里需要注意的是,client建立的StreamID必须是奇数,而server建立的StreamID必须是偶数。另外,StreamID为0的流有一个特殊的作用,它是CONNECTION_STREAM_ID,1表示HTTP_UPGRADE_STREAM_ID。state表示流的状态。具体来说,流具有以下状态:IDLE(false,false)、RESERVED_LOCAL(false,false)、RESERVED_REMOTE(false,false)、OPEN(true,true)、HALF_CLOSED_LOCAL(false,true)、HALF_CLOSED_REMOTE(true,false),关闭(假,假);为什么状态需要区分本地和远程?这是因为流的两端连接,所以有两端状态。流状态对应的是http2的生命周期。netty提供了Http2LifecycleManager来表示对http2生命周期的管理:voidcloseStreamLocal(Http2Streamstream,ChannelFuturefuture);voidcloseStreamRemote(Http2Stream流,ChannelFuture未来);voidcloseStream(Http2Stream流,ChannelFuture未来);ChannelFutureresetStream(ChannelHandlerContextctx,intstreamId,longerrorCode,ChannelPromisepromise);ChannelFuturegoAway(ChannelHandlerContextctx,intlastStreamId,longerrorCode,ByteBufdebugData,ChannelPromise承诺);voidonError(ChannelHandlerContextctx,booleanoutbound,Throwablecause);拒绝创建新流:goAway,并处理错误状态。在Http2Framestream之后,真正承载http2报文的是Http2Frame。在netty中,Http2Frame是一个接口,它有很多具体的实现。Http2Frame的直接子类包括HTTP2GoAwayFrame、HTTPPingFrame、Http2SettingsFrame和HTTP2SettingsAckFrame。其中goAway表示不接受新的流,ping用于心跳检测。SETTINGS用于修改连接或Stream配置。netty中有一个Http2Settings类及其对应类。该类中定义了一些特殊的设置名称:SETTINGS名称含义SETTINGS_HEADER_TABLE_SIZE对端索引表的最大大小SETTINGS_ENABLE_PUSH是否开启服务器推送功能SETTINGS_MAX_CONCURRENT_STREAMS接收端允许的最大并发数SETTINGS_MAX_FRAME_SIZE设置帧的最大大小SETTINGS_MAX_HEADER_LIST_SIZEpeerheaderindextable的最大大小除了上面提到的四种框架外,其他框架的实现都是继承自Http2StreamFrame,具体有PriorityFrame、ResetFrame、HeadersFrame、DataFrame、WindowUpdateFrame、PushPromiseFrame和UnknownFrame。每一帧代表不同的功能。这里最重要的是Http2HeadersFrame和Http2DataFrame。Http2HeadersFrame主要是客户端向服务端发送的http2请求。具体来说,除了标准的http1.1headers,http2还支持以下headers:METHOD(":method",true),SCHEME(":scheme",true),AUTHORITY(":authority",true),PATH(":path",true),STATUS(":status",false),PROTOCOL(":protocol",true);对于Http2DataFrame,它本身就是一个ByteBufHolder,用来传递具体的数据信息。数据帧的Payload直接存放在ByteBuf中。综上所述,以上就是netty对http2报文的封装。本文示例可参考:learn-netty4本文已收录于http://www.flydean.com/28-netty-wrap-http2/最流行的解读,最深刻的干货,最简洁的教程,很多你不知道的小技巧等你来发现!欢迎关注我的公众号:《程序那些事儿》,懂技术,更懂你!