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对象)的跨节点远程服务调用 ...
随机推荐
- 羽夏笔记——Win32(非WinAPI)
写在前面 本笔记是由本人独自整理出来的,图片来源于网络.本人非计算机专业,可能对本教程涉及的事物没有了解的足够深入,如有错误,欢迎批评指正. 如有好的建议,欢迎反馈.码字不易,如果本篇文章有帮助你 ...
- Linux常用命令 - nl命令详解
21篇测试必备的Linux常用命令,每天敲一篇,每次敲三遍,每月一循环,全都可记住!! https://www.cnblogs.com/poloyy/category/1672457.html 显示行 ...
- 《openssl编程》:第一章基础知识
第一章 基础知识 1.1 对称算法 对称算法使用一个密钥.给定一个明文和一个密钥,加密产生密文,其长度和明文大致相同.解密时,使用读密钥与加密密钥相同. 对称算法主要有四种加密模式: (1) 电子密码 ...
- TCP超时重传、序列号、滑动窗口简介
文章目录 12 TCP:传输控制协议(初步) 12.1 引言 12.1.1 ARQ和重传 12.1.2 分组窗口和滑动窗口 12.1.3 变量窗口:流量控制和拥塞控制 12.1.4 变量窗口:设置重传 ...
- MySQL(3)-日志
3. InnoDB日志 3.1 InnoDB架构 分为 内存区域架构 buffer pool log buffer 磁盘区域架构 redo log undo log 2.1.1 内存区域架构 1)Bu ...
- python类、对象
python类.对象 学习完本篇,你将会深入掌握 什么是类,对象 了解类和对象之间的关系 能独立创建一个People(人类),属性有姓名.性别.年龄.提供一个有参的构造方法,编写一个show方法,输出 ...
- 一起学习PHP中GD库的使用(二)
在日常的开发过程中,GD 库最常用的功能就是帮我们对图片进行一些处理,当然,除了处理已有的图片之外,它也可以直接来画图,就像我们最常见的图片验证码.今天的内容主要就是和画图有关,所以最后我们也会做一个 ...
- PHP的switch和ifelse谁更快?
对于多个if条件判断的情况下,我们使用switch来代替ifelse对于代码来说会更加的清晰明了,那么他们的效率对比呢?从PHP手册中发现有人已经对比过了,自己也用他的代码进行了实验: $s = ti ...
- jquery动态生成dom(比如append)导致js事件无效
如果无效用这个方法: on() 方法在被选元素及子元素上添加一个或多个事件处理程序. <div id="zkdiv"> <input type="bu ...
- mysql语句alter添加 字段
alter table ylh_coupon add is_reg int default 0 给数据表 ylh_coupon 添加一个字段 is_reg,,整型,默认值为0