netty系列之:netty对http2消息的封装
简介
无论是什么协议,如果要真正被使用的话,需要将该协议转换成为对应的语言才好真正的进行应用,本文将从http2消息的结构出发,探讨一下netty对http2消息的封装,带大家领略一下真正的框架应该做到什么程度。
http2消息的结构
http2和http1.1不同的是它使用了新的二进制分帧,通过客户端和服务器端建立数据流steam来进行客户端和服务器端之间消息的交互。其中数据流是一个双向字节流,用来发送一条或者多条消息。
消息是客户端和服务端发送的一个逻辑上完整的数据。根据数据大小的不同,可以将消息划分为不同的帧Frame。也就是说message是由不同的frame组成的。
frame就是http2中进行通信的最小单位,根据上一节的介绍,我们知道frame有这样几种:
- DATA frame
- HEADERS frame
- PRIORITY frame
- RST_STREAM frame
- SETTINGS acknowledgment frame
- SETTINGS frame
- PING frame
- PING acknowledgment
- PUSH_PROMISE frame
- GO_AWAY frame
- WINDOW_UPDATE frame
- Unknown Frame
我们看一下http2中stream和frame的一个大体的结构:

在http2中,一个TCP连接,可以承载多个数据流stream,多个stream中的不同frame可以交错发送。
每个frame通过stream id来标记其所属的stream。
有了上面的http2的基本概念,我们接下来就看下netty对http2的封装了。
netty对http2的封装
Http2Stream
作为一个TCP连接下面的最大的单位stream,netty中提供了接口Http2Stream。注意,Http2Stream是一个接口,它有两个实现类,分别是DefaultStream和ConnectionStream。
Http2Stream中有两个非常重要的属性,分别是id和state。
id前面已经介绍了,是stream的唯一标记。这里要注意由客户端建立的 Stream ID 必须是奇数,而由服务端建立的 Stream ID 必须是偶数。另外Stream ID 为 0 的流有特殊的作用,它是CONNECTION_STREAM_ID,1 表示HTTP_UPGRADE_STREAM_ID。
state表示stream的状态,具体而言,stream有下面几个状态:
IDLE(false, false),
RESERVED_LOCAL(false, false),
RESERVED_REMOTE(false, false),
OPEN(true, true),
HALF_CLOSED_LOCAL(false, true),
HALF_CLOSED_REMOTE(true, false),
CLOSED(false, false);
为什么状态需要区分local和remote呢?这是因为stream连接的两端,所以有两端的状态。
和stream状态相对应的就是http2的生命周期了。netty提供了Http2LifecycleManager来表示对http2生命周期的管理:
void closeStreamLocal(Http2Stream stream, ChannelFuture future);
void closeStreamRemote(Http2Stream stream, ChannelFuture future);
void closeStream(Http2Stream stream, ChannelFuture future);
ChannelFuture resetStream(ChannelHandlerContext ctx, int streamId, long errorCode,
ChannelPromise promise);
ChannelFuture goAway(ChannelHandlerContext ctx, int lastStreamId, long errorCode,
ByteBuf debugData, ChannelPromise promise);
void onError(ChannelHandlerContext ctx, boolean outbound, Throwable cause);
分别是关闭stream,重置stream,拒绝新建stream:goAway,和处理出错状态这几种。
Http2Frame
stream之后,就是真实承载http2消息的Http2Frame了。在netty中,Http2Frame是一个接口,它有很多具体的实现。
Http2Frame的直接子类包括HTTP2GoAwayFrame、HTTPPingFrame、Http2SettingsFrame和HTTP2SettingsAckFrame。
其中goAway表示不接受新的stream,ping用来进行心跳检测。SETTINGS用来修改连接或者 Stream 流的配置。
netty中专门有一个Http2Settings类和其对应。
在这个类中定义了一些特别的setting名字:
| SETTINGS 名字 | 含义 |
|---|---|
| SETTINGS_HEADER_TABLE_SIZE | 对端索引表的最大尺寸 |
| SETTINGS_ENABLE_PUSH | 是否启用服务器推送功能 |
| SETTINGS_MAX_CONCURRENT_STREAMS | 接收端允许的最大并发 Stream 数量 |
| SETTINGS_INITIAL_WINDOW_SIZE | 发送端的窗口大小,用于 Stream 级别流控 |
| SETTINGS_MAX_FRAME_SIZE | 设置帧的最大大小 |
| SETTINGS_MAX_HEADER_LIST_SIZE | 对端头部索引表的最大尺寸 |
除了上面讲的4个frame之外,其他的frame实现都继承自Http2StreamFrame,具体而言有PriorityFrame,ResetFrame,HeadersFrame,DataFrame,WindowUpdateFrame,PushPromiseFrame和UnknownFrame。
各个frame分别代表了不同的功能。这里最重要的就是Http2HeadersFrame和Http2DataFrame。
Http2HeadersFrame主要是客户端发送给服务器端的http2请求。
具体而言除了标准的http1.1的header之外,http2还支持下面的header:
METHOD(":method", true),
SCHEME(":scheme", true),
AUTHORITY(":authority", true),
PATH(":path", true),
STATUS(":status", false),
PROTOCOL(":protocol", true);
对于Http2DataFrame来说,他本身是一个ByteBufHolder,用来传递具体的数据信息。data frame的Payload直接存储在ByteBuf中。
总结
以上就是netty对http2消息的封装了。
本文的例子可以参考:learn-netty4
本文已收录于 http://www.flydean.com/28-netty-wrap-http2/
最通俗的解读,最深刻的干货,最简洁的教程,众多你不知道的小技巧等你来发现!
欢迎关注我的公众号:「程序那些事」,懂技术,更懂你!
netty系列之:netty对http2消息的封装的更多相关文章
- 【读后感】Netty 系列之 Netty 高性能之道 - 相比 Mina 怎样 ?
[读后感]Netty 系列之 Netty 高性能之道 - 相比 Mina 怎样 ? 太阳火神的漂亮人生 (http://blog.csdn.net/opengl_es) 本文遵循"署名-非商 ...
- Netty 系列之 Netty 高性能之道 高性能的三个主题 Netty使得开发者能够轻松地接受大量打开的套接字 Java 序列化
Netty系列之Netty高性能之道 https://www.infoq.cn/article/netty-high-performance 李林锋 2014 年 5 月 29 日 话题:性能调优语言 ...
- netty系列之:netty实现http2中的流控制
目录 简介 http2中的流控制 netty对http2流控制的封装 Http2FlowController Http2LocalFlowController Http2RemoteFlowContr ...
- Netty系列之Netty线程模型
Reference: http://www.infoq.com/cn/articles/netty-threading-model 1. 背景 1.1. Java线程模型的演进 1.1.1. 单线程 ...
- netty系列之:netty初探
目录 简介 netty介绍 netty的第一个服务器 netty的第一个客户端 运行服务器和客户端 总结 简介 我们常用浏览器来访问web页面得到相关的信息,通常来说使用的都是HTTP或者HTTPS协 ...
- netty系列之:netty架构概述
目录 简介 netty架构图 丰富的Buffer数据机构 零拷贝 统一的API 事件驱动 其他优秀的特性 总结 简介 Netty为什么这么优秀,它在JDK本身的NIO基础上又做了什么改进呢?它的架构和 ...
- Netty 系列之 Netty 高性能之道
1. 背景 1.1. 惊人的性能数据 最近一个圈内朋友通过私信告诉我,通过使用 Netty4 + Thrift 压缩二进制编解码技术,他们实现了 10 W TPS(1 K 的复杂 POJO 对象)的跨 ...
- Netty系列之Netty高性能之道
转载自http://www.infoq.com/cn/articles/netty-high-performance 1. 背景 1.1. 惊人的性能数据 最近一个圈内朋友通过私信告诉我,通过使用Ne ...
- 转:Netty系列之Netty高性能之道
1. 背景 1.1. 惊人的性能数据 最近一个圈内朋友通过私信告诉我,通过使用Netty4 + Thrift压缩二进制编解码技术,他们实现了10W TPS(1K的复杂POJO对象)的跨节点远程服务调用 ...
随机推荐
- Spring Cloud Eureka 实践(二)
接上一篇的内容,Eureka服务已经启动成功后,可以尝试开发服务的提供者与消费者,并注册到Eureka来实现服务的发现与调用. 首先,在父工程中继续创建服务提供者的Module,最新的目录结构如下图所 ...
- 装配Bean的三种方式
一.装配Bean就是在xml写一个Bean标签:装配完Bean,还需要读取xml配置文件创建Spring容器来创建对象: 1.new 实现类方式 正常的三种创建Bean容器的方法都可以根据装配的Bea ...
- Vue指令及自定义指令的使用
导航列表: 一.vue指令 二.自定义指令 一.vue指令 回到顶部 1. v-text v-text主要用来更新textContent,可以等同于JS的text属性,不会解析标签,会把标签解析 ...
- 有关类朋友圈设计(3) -- 数据库设计&现有技术&流程设计
在写之前,先说说当前的系统架构吧 spring cloud + zuul + eureka + oauth2 + redis + rabbitMq 这个系统是由我搭建的,当时采用的springClou ...
- Mysql实现无插入有更新(不知主键的情况下)
网上很多资料说有两种方式 (必须现有唯一键) 1.INSERT 中ON DUPLICATE KEY UPDATE的使用 2.REPLACE的使用 通过可以得出结果: 如果a和b字段 能决定唯一 例子: ...
- Jmeter系列(3)- 常用断言之响应断言
断言的作用 确定请求是有效还是无效的 添加断言 面板模块介绍 Apply to 作用:指定断言作用范围 Main sample and sub-sample:作用于主main sample和子sub- ...
- 博客主题——element v2
主题预览 主题下载 gshang.element-v2.rar
- javascript wchar_t 宽字符 转化为 ascii字符码数组
String.prototype.charCodeAt String.fromCharCode() String.prototype.toUtfArray = function() { return ...
- P3649-[APIO2014]回文串【PAM】
正题 题目链接:https://www.luogu.com.cn/problem/P3649 题目大意 一个字符串,求最大的回文串长度×出现次数 解题思路 构建出\(\text{PAM}\)然后统计一 ...
- JSP页面属性
一.JSP指令 <%@指令名属性名=属性值 %> page指令: 定义页面是如何解析 include指令: 静态包含 taglib指令: 在页面引入标签呢库. 1.page指令属性 imp ...