HTTP 2.0协议面世


Http2协议的草案已经出来了,http2尽可能的兼容http1.1,改进了http1.1协议的不足,基本协议单位为帧。HTTP/2使用HTTP/1相同的API,开发者不需要改变应用程序代码就能更新库支持HTTP/2。

---------------------------------------------------
HTTP发展历史
HTTP 0.9
只有一个GET方法
没有header等描述数据信息
服务器发送完毕,就关闭TCP连接
HTTP 1.0
增加了很多方法,例如POST,PUT,DELETE等
增加了status code和header
增加了多字符集的支持, 多部分发送,权限,缓存等;1996年5月发布,引入请求头和响应头
HTTP 1.1
持久连接/长连接
Pipeline 客户端可以在同一个连接中发送多个请求, 服务端按顺序返回(串行)
增加host头,有了host之后可以实现一台web服务可以接收/处理多个域名的请求
增加了其他更多的方法;1997年1月发布。支持长连接;添加Content-Length字段;分块传输编码等
HTTP 2.0
2.0所有的数据以二进制进行传输(帧),在1.1大部分是以字符串的形式传输
得益于基于帧的传输, 可以实现在同一个连接里面发送多个请求不再需要按顺序来返回(并行)
头信息压缩, 1.1的header头以字符串的形式进行传输,占用了大量带宽
推送,1.1之前只支持客户端主动向服务端发起请求,服务端被动向客户端响应请求; 2.0之后服务可以主动向客户端发送数据(例子:客户端在发起请求访问服务端页面时, 先请求html页面, 当客户端收到服务端发来的html数据之后,客户端浏览器进行解析并渲染, 在其中,发现了引用到了其他文件,如css、js文件,均以url链接形式引用,此时浏览器会按顺序再次对新的资源发起请求; 2.0中的此场景下, 客户端在请求了html页面后,服务端可以实现主动将css,js数据推送到客户端,从而解决了1.1串行请求资源的性能低下问题。并且服务端主动推送资源到客户端,也可以解决客户端因各种原因,请求不到指定资源的情况)
2.0 以提高效率为主要目标对1.1进行了大量改进。
SPDY
2012年Google发布。HTTP2.0就是基于SPDY设计的,其目前已经无人使用。添加多路复用(Multiplexing);header压缩(DEFLATE算法);服务端推送等
HTTP2.0
2015年发布。本文主要讲解内容,后文详细讨论
HTTP3.0
2018年发布。尚未学习,最大的特点可能是基于UDP协议,不在本文讨论范围
通过对HTTP/2的Wiki介绍,可以看下定义和发展历史。RFC 7540 定义了 HTTP/2 的协议规范和细节, RFC 7541定义了头部压缩。
http 1.0和http 1.1的缺点:
1.http1.0只允许在一个连接上建立当前未完成的请求。
2.http1.1管道只部分处理了请求并发和包头堵塞问题,客户端多建立TCP连接,减少延迟。
3.报头字段经常重复和冗长,数据包变大,容易造成初始TCP端口的堵塞,多建立几个TCP连接。
http 2x协议解决之道:
1.优化基础连接的语义映射,例如同一个连接上建立交错的请求和响应,使用高效率编码的报头字段。
2.允许请求的优先级,让更多重要的请求先完成。
http2协议的特点:
1.http2中最基本的协议单位是帧。每个帧都有不同的类型和用途。例如,报头(HEADERS)和数据(DATA)帧组成了基本的http请求和响应,帧包含的HTTP报头字段是压缩的。HTTP请求有可能是高度冗余的,因此压缩能显著减少请求和响应的大小。
2.请求多路复用:一个流上分配多个HTTP请求响应交换,流在很大程度上是相互独立的,因为一个请求上的阻塞和终止不会影响其他请求的处理。
3.流量控制和优先级确保正确使用复用流,流量控制有助于确保只传播接受需要的数据,优先级确保有限的资源能被重要的请求使用。
4.添加了一种新的交互模式,即服务器能推送消息给客户端。服务器推送允许服务端预测客户端需要来发送。
数据给客户端,交换网络使用以阻塞潜在的延迟增长。服务器通过复用一个以PUSH_PROMISE帧发送的请求来实现推送,然后服务端可以在一个单独的流里面发送响应给这个合成的请求。
------------------------------
HTTP/2 规格制定完成
IETF HTTP工作者的负责人Mark Nottingham在其博客上宣布HTTP/2规格制定完成,接下来将是分配RFC编号和正式发表。HTTP是Web的核心技术之一,相比HTTP/1,HTTP/2的改进之处包括更快的页面加载;更长久的连接;服务器推送,允许服务器主动向客户端推送消息;减少加密连接开销,改进性能;多路复用功能允许同时发送许多个请求。
HTTP/2使用HTTP/1相同的API,开发者不需要改变应用程序代码就能更新库支持HTTP/2。
---------------------------------------------------
HTTP/2 正式通过 IETF 组织批准发布
超过两年的讨论,超过 200 个设计问题, 17 个草案 和 30 个实现, HTTP/2 和 HPACK 规范终于通过了 IETF 组织的批准并作为可跟踪的 RFC 标准。HTTP/2 将帮助实现更快的用户浏览体验,降低带宽要求,同时更容易实现安全的通讯连接。
在 2012 年 HTTP Working Group 开始在 Google 的 SPDY 协议的基础上研究 HTTP/2 标准,通过 6 次组织内的会议以及来自社区的讨论完成了最初版本的确定。
协议被设计为可以在 HTTP/1 和 HTTP/2 中无缝切换,以最小化对应用和 API 的变化要求,同时提升性能以及更好的使用网络资源。Web 用户只需要沿用老的习惯就可以享用 HTTP/2 带来的提升。
协议开发过程中的关键点是协议的更新、实现和测试过程中的迭代。工作组会对一些特定版本进行标注以便于浏览器进行实现和测试,内部的会议主要是密集讨论这些问题。
HTTP/2 的工作具体体现了 IETF 的价值宗旨 —— 大致共识并运行代码。
---------------------------------------------------
HTTP/2 没有强制要求 TLS
HTTP/2规格已经制定完成,即将成为正式标准。在规格中,HTTP/2协议没有强制要求使用TLS, 主要原因是许多机构都想要检查HTTP流量,或网络环境需要缓存,或认为TLS会增加额外的负担,以及认为安全证书太昂贵,等等。虽然规格没有强迫使用 TLS实现HTTP/2支持,目前浏览器开发商在实现HTTP/2支持时都是经过TLS, Firefox 和Chrome开发团队的成员明确表示他们只实现使用TLS的HTTP/2,而IE的团队成员一开始表示他们不使用TLS,但Windows 10技术预览版上第一个支持HTTP/2的测试版本也是只使用TLS。
---------------------------------------------------
HTTP/2 规格正式发布,RFC 编号为 7540
2015年05月15日,互联网工程任务组正式发布了HTTP/2 规格,RFC编号为7540。HTTP/2的改进之处包括更快的页面加载、更长久的连接、服务器推送、允许服务器主动向客户端推送消息、减少加密连接开销改进性能、多路复用功能允许同时发送许多个请求。
HTTP协议演进
HTTP协议经过4个版本的演进,不断解决Web发展的问题,比如WEB2.0的复杂页面和移动互联网时代的手机浏览器页面,本文简单对比这些演进版本的。

HTTP1.0和HTTP1.1的一些区别
HTTP1.0最早在网页中使用是在1996年,那时候只是使用在一些较为简单的网页和网络请求上,而HTTP1.1则在1999年才开始广泛应用于现在的各大浏览器网页中,同时HTTP1.1也是当前使用最为广泛的HTTP协议。 主要区别体现在:
缓存处理,在HTTP1.0中主要使用header里的If-Modified-Since,Expires来做为缓存判断的标准,HTTP1.1则引入了更多的缓存控制策略例如Entity tag,If-Unmodified-Since, If-Match, If-None-Match等更多可供选择的缓存头来控制缓存策略。
带宽优化及网络连接的使用,HTTP1.0中,存在一些浪费带宽的现象,例如客户端只是需要某个对象的一部分,而服务器却将整个对象送过来了,并且不支持断点续传功能,HTTP1.1则在请求头引入了range头域,它允许只请求资源的某个部分,即返回码是206 Partial Content,这样就方便了开发者自由的选择以便于充分利用带宽和连接。
错误通知的管理,在HTTP1.1中新增了24个错误状态响应码,如409 Conflict表示请求的资源与资源的当前状态发生冲突;410 Gone表示服务器上的某个资源被永久性的删除。
Host头处理,在HTTP1.0中认为每台服务器都绑定一个唯一的IP地址,因此,请求消息中的URL并没有传递主机名hostname。但随着虚拟主机技术的发展,在一台物理服务器上可以存在多个虚拟主机Multi-homed Web Servers,并且它们共享一个IP地址。HTTP1.1的请求消息和响应消息都应支持Host头域,且请求消息中如果没有Host头域会报告一个错误400 Bad Request。
长连接,HTTP 1.1支持长连接PersistentConnection和请求的流水线Pipelining处理,在一个TCP连接上可以传送多个HTTP请求和响应,减少了建立和关闭连接的消耗和延迟,在HTTP1.1中默认开启Connection:keep-alive,一定程度上弥补了HTTP1.0每次请求都要创建连接的缺点。
HTTP 1.0和1.1现存的一些问题
上面提到过的,HTTP1.x在传输数据时,每次都需要重新建立连接,无疑增加了大量的延迟时间,特别是在移动端更为突出。
HTTP1.x在传输数据时,所有传输的内容都是明文,客户端和服务器端都无法验证对方的身份,这在一定程度上无法保证数据的安全性。
HTTP1.x在使用时,header里携带的内容过大,在一定程度上增加了传输的成本,并且每次请求header基本不怎么变化,尤其在移动端增加用户流量。
虽然HTTP1.x支持了keep-alive,来弥补多次创建连接产生的延迟,但是keep-alive使用多了同样会给服务端带来大量的性能压力,并且对于单个文件被不断请求的服务(例如图片存放网站),keep-alive可能会极大的影响性能,因为它在文件被请求之后还保持了不必要的连接很长时间。
HTTP2.0新特性
新的二进制格式Binary Format,HTTP1.x的解析是基于文本。基于文本协议的格式解析存在天然缺陷,文本的表现形式有多样性,要做到健壮性考虑的场景必然很多,二进制则不同,只认0和1的组合。基于这种考虑HTTP2.0的协议解析决定采用二进制格式,实现方便且健壮。
多路复用MultiPlexing,即每一个request都是连接共享机制。一个request对应一个id,这样一个连接上可以有多个request,每个连接的request可以随机的混杂在一起,接收方可以根据request的 id将request再归属到各自不同的服务端请求里面。多路复用原理图:

HTTP/2 Inside: multiplexing
header压缩,如上文中所言,前面提到过HTTP 1.x的header带有大量信息,而且每次都要重复发送,HTTP2.0使用encoder来减少需要传输的header大小,通讯双方各自cache一份header fields表,既避免了重复header的传输,又减小了需要传输的大小。
服务端推送server push,例如我的网页有一个style.css的请求,在客户端收到style.css数据的同时,服务端会将style.js的文件推送给客户端,当客户端再次尝试获取style.js时就可以直接从缓存中获取到,不用再发请求了。
---------------------------------------------------
经典五层模型
应用层 -> HTTP/FTP
传输层 -> TCP/UDP
网络层: 数据在节点之间传输创建逻辑链路
数据链路层: 在通信的实体间建立数据链路连接(0101)
物理层: 定义物理设备如何传输数据
传输层
向用户提供可靠的端到端的服务, 传输层向高层屏蔽了下层数据通信的细节
应用层
为应用软件提供服务, 构建在传输层协议之上, 屏蔽网络通信细节
HTTP(TCP)的三次握手
三次握手是TCP连接中的概念, HTTP不存在连接的概念, HTTP只有请求和响应的概念
每个HTTP的请求与响应都是需要基于一个TCP的连接的
User http requests -- TCP connection -- Server http response
在HTTP 1.0 版本中, 客户端发起一个HTTP请求, 此时, 会创建一条TCP连接通道, 在服务端处理完毕, 响应给客户端之后, 这条TCP连接就会被断掉
在HTTP 1.1版本中, 通过声明特殊的属性, 可以实现一个TCP连接上, 可以发送多个HTTP请求(长连接/Keepalive)
在HTTP 2.0 版本中,可以实现,同一个客户端请求同一个服务端,只需要一个TCP连接即可,因为2.0版本支持并行发送请求,和并行接收请求,不需要再额外创建更多的TCP连接
---------------------------------------------------
HTTP/2 常见问题回答
为什么修订HTTP?
HTTP/1.1已经很好的服务Web超过15个年头,但它的劣势开始显现。
载入一个Web页面比之前占用更多的资源(详情可见HTTP压缩页大小统计),有效的载入这些资源很难,因为HTTP实际上对每个TCP连接,只允许一个优先的请求。
在过去,对于并发请求,浏览器使用多个TCP连接。然而,这也是有局限的;如果使用了过多的连接,这既是一种计数上的高产(TCP阻塞控制是被有效否定的,导致阻塞事件影响性能和网络),也基本上是不公平的(因为浏览器承受的资源大于它们享有的网络资源)。
同时,大量的请求意味着“线上”有很多重复的数据。
HTTP/1.1耗费大量的开销是与这两个因素有关。如果发生过多的请求,会影响性能。
这些导致了相关行业成为了像雪碧、数据内联、域共享和级联的最佳练习场地。这些问题被认为是底层协议自身的问题,并导致在使用它们时产生了一系列的问题。
谁正在做这件事?
IETF的HTTPbis工作组正在开发HTTP/2,他们负责维护HTTP协议。是由若干HTTP实现者、用户、网络运营商和HTTP专家组成。
注意虽然工作组的邮件列表是托管在W3C网站上,不过却不是W3C的功劳。但是, Tim Berners-Lee 和 W3C TAG与WG的进程保持了一致。
大量的人对相关工作作出了共享,不过大部分活跃参与者是来自像Firefox、Chrome、Twitter、Microsoft的HTTP栈、Curl和Akamai这样大项目的工程师,以及若干Python、Ruby和NodeJS的HTTP实现者。
要了解更多IETF参与者,请看IETF之道。你也可以在Github的贡献者图表中了解到哪些人正在对规范做贡献,在我们的实现者列表了解哪些人正在参与实施。
和SPDY是怎样的关系?
HTTP/2 第一次出现并被讨论的时候, SPDY 正得到厂商 (像 Mozilla 和 nginx)的青睐和支持, 并被看成是HTTP/1.x 基础上的重大改善.
经过建议和投票之后, SPDY/2 被列为HTTP/2 的基础.从那时起, 根据工作组的讨论和厂商的反馈,它已经有了很多变化。
在整个过程中,SPDY 的核心开发成员都参与了HTTP/2 的发展, 其中也包括 Mike Belshe 和 Roberto Peon. 事实上,已经发布的 SPDY/4 revision 正是基于 HTTP/2的 ,因为SPDY社区现在发现它是作为一种进一步实验反馈到 HTTP/x的工具, 而不是竞争对手.
是 HTTP/2.0 还是 HTTP/2?
工作组决定去掉小版本 (“.0”) 因为这在HTTP/1.x中导致了很多困惑.
也就是说, HTTP 的版本仅代表它的兼容性,不表示它的特性和 “亮点”
和HTTP/1.x的关键区别是什么?
在高版本 HTTP/2中:
是二进制的,代替原有的文本
是多路复用的, 代替原来的序列和阻塞机制
所以可以在一个连接中并行处理
压缩头部信息减小开销
允许服务器主动推送应答到客户端的缓存中
HTTP/2为什么是二进制的?
比起像HTTP/1.x这样的文本协议,二进制协议解析起来更高效、“线上”更紧凑,更重要的是错误更少。因为它们对如空白字符的处理、大小写、行尾、空链接等的处理很有帮助。例如,HTTP/1.1定义了四个不同的方法来解析一条消息;在HTTP/2中,仅需一个代码路径即可。
HTTP/2在telnet中将不可用,但是我们有一些工作提供支持,比如Wireshark plugin。
为什么 HTTP/2 需要多路传输?
HTTP/1.x 有个问题叫线端阻塞(head-of-line blocking), 它是指一个连接(connection)一次只提交一个请求的效率比较高, 多了就会变慢.
HTTP/1.1 试过用流水线(pipelining)来解决这个问题, 但是效果并不理想(数据量较大或者速度较慢的响应, 会阻碍排在他后面的请求). 此外, 由于网络媒介(intermediary )和服务器不能很好的支持流水线, 导致部署起来困难重重.
客户端使用一些启发式的方法(基本靠猜) 来决定通过哪些连接提交哪些请求; 由于一个页面加载的数据量, 往往比可用连接能处理的数据量的10倍还多, 对性能产生极大的负面影响, 结果经常引起瀑布式阻塞(waterfall of blocked requests).
而多路传输(Multiplexing)能很好的解决这些问题, 因为它能同时处理多个消息的请求和响应; 甚至可以在传输过程中将一个消息跟另外一个掺杂在一起.
所以客户端只需要一个连接就能加载一个页面。
为什么只要一个 TCP 连接?
目前的浏览器, 每个点 (origin) 打开 4 到 8 个连接(Connection). 而很多网站都支持多点传输(multiple origins), 也就是说, 光加载一个网页, 打开的连接数量就超过 30 个.
一个应用同时打开这么多连接, 已经远远超出了当初设计 TCP 时的预期; 每一个连接接收过多的数据, 又存在网络缓存溢出的风险, 结果导致网络堵塞和数据重传.
此外, 使用这么多连接还会强占许多网络资源. 这些资源都是从别人那 “偷” 来的. 你说这些应用够遵纪守法吧? (VoIP 就是个很好的例子).
服务器推送的好处是什么?
当浏览器请求一个网页时,服务器将会发回HTML,在服务器开始发送JavaScript、图片和CSS前,服务器需要等待浏览器解析HTML和发送所有内嵌资源的请求。
服务器推送服务通过“推送”那些它认为客户端将会需要的内容到客户端的缓存中,以此来避免往返的延迟。
消息头为什么需要压缩?
来自Mozilla的Patrick McManus通过计算消息头对平均页面负载的印象,对此进行了形象且充分的说明.
假定一个页面有80个资源需要加载(这个数量对于今天的Web而言还是挺保守的), 而每一次请求都有1400字节的消息头(着同样也并不少见,因为Cookie和引用等东西的存在), 至少要7到8个来回去“在线”获得这些消息头。这还不包括响应时间——那只是从客户端那里获取到它们所花的时间而已。
这全都由于TCP的慢启动机制,它会基于对已知有多少个包,来确定还要来回去获取哪些包 – 这很明显的限制了最初的几个来回可以发送的数据包的数量.
相比之下,即使是头部轻微的压缩也可以是让那些请求只需一个来回就能搞定——有时候甚至一个包就可以了。
这种开销是可以被节省下来的,特别是当你考虑移动客户端应用的时候,即使是良好条件下,一般也会看到几百毫秒的来回延迟。
为什么是 HPACK?
SPDY/2 提出在每一方都使用一个单独的GZIP上下文用于消息头压缩,者实现起来很容易,也很高效.
从那时候开始,就有了一个被证明能针对算法中使用流压缩(如GZIP)的重要攻击方式 CRIME.
CRIME 让那些能向加密流中诸如数据的攻击者获得了“探测”原文并进行还原的可能性。因为是Web,JavaScript使其成为了可能,而且已经有了使用针对受到TLS保护的HTTP资源的CRIME恢复cookie和认证令牌信息的证明。因此,我们不应该使用GZIP。由于找不到其它适合使用在这种用例下的安全有效的算法,我们创造了一种新的,特别针对消息头的压缩方案,它能进行粗粒度的操作;因为HTTP消息头并不常常需要改变,我们仍然可以得到很好的压缩效率,而且更加的安全.
HTTP/2 能让cookie(以及其他的消息头)更好么?
这一尝试被许可在网络协议的一个修订版本上运行 – 例如,HTTP消息头、方法等等如何才能在不改变HTTP语义的前提下放到"网络上“.
这是因为HTTP的使用是如此广泛。如果我们使用了这个版本的HTTP,引入了一种新的状态机制(例如之前讨论过的例子)或者改变的核心方法(幸好,这还没有发生过), 这可能就意味着新的协议将不会同现有的Web兼容.
具体地,我们是想要能够从HTTP/1转移到HTTP/2,并且不会有信息的丢失. 如果我们开始”清理”消息头(大多数人会认同,HTTP消息头现在简直是一团糟), 我们就不得不要去面对现有Web的诸多问题.
那样做只会为采用新协议的过程中制造麻烦.
总而言之,工作组会对所有的HTTP负责,而不仅仅只是HTTP/2. 因此,我们才可以在版本独立的新机制下运作,同时它们也能向后同现有的网络兼容。
非浏览器用户的HTTP会是什么情况呢?
人们期望非浏览器应用程序也能够用上HTTP/2,如果它们曾今使用过HTTP的话。
早起收到针对HTTP的“API”,HTTP/2具有性能好等特点这样的反馈,是因为API的设计中不需要考虑像请求开销这样一些事情。
之前说过,我们所要考虑的主要的提升重点是在典型的浏览器用例下, 因为这是协议主要的使用场景。
我们的章程里面是这样说的:
正在组织的规范能满足现在已经普遍部署了的HTTP的功能要求;
具体的,(桌面端和移动端的)Web浏览,(“HTTP API”形式的)非浏览器, (大范围的)Web服务,
还有各种(借助代理,企业防火墙,反向代理以及内容分发网络实现的)中介。
同样的,对HTTP/1.x当前和未来的语义扩展 (例如,消息头,方法,状态码,缓存指令) 都应该在新的协议中支持。
注意,这里没有涵盖将HTTP用于非特定行为所依赖的(例如超时,连接状态以及拦截代理)场景中;这些使用可能不会被最终的产品启用。
HTTP/2 需要加密吗?
不需要。在广泛的讨论后,工作组没有就新协议是否使用加密(如TLS)而达成共识。
不过,有些实现者说,只有HTTP/2使用加密链接他们才提供支持。
HTTP/2为提高安全性做了什么?
目前,HTTP/2定义了TLS的轮廓,包括版本、密码套件和用到的扩展。
细节参见相关规范。其中也讨论了额外的机制,如对HTTP://URLs(所谓的“机会主义加密”)使用TLS;参见 issue #315。
现在可以用HTTP/2吗?
HTTP/2暂时在主流浏览器中还不可用,不过还是有一些体验版的可以用,或许在“每夜(nightly)”频道可以找到。
还是有几个服务器可用的(包括 Akamai 和 Twitter主流网站提供了测试服务器),以及几个开源版的,你可以用来部署和测试。
HTTP/2会代替HTTP/1.x
工作组的目的是让那些使用HTTP/1.x也可以使用HTTP/2,并能感受到HTTP/2所带来的好处。工作组说过,由于人们部署代理和服务器的方式的原因,我们不能强迫整个世界进行迁移,所以HTTP/1.x很可能仍要使用了一段时间。
HTTP/3 会出现么?
如果通过HTTP/2引入的沟通协作机制运行良好, 那就有可能比过去更加容易的支持新版本的HTTP。
实现中的问题
为什么规则会围绕消息头帧的数据接续?
数据接续的存在是由于一个值(例如cookie)可以超过 16kb, 这意味着它不可能全部装进一个帧里面. 所以就决定以最不容易出错的方式让所有的消息头数据以一个接一个帧的方式传递, 这样就使得对消息头的解码和缓冲区的管理更加的容易。
HPACK状态的最小和最大尺寸是多少 ?
接收一方总是会控制HPACK中内存的使用量, 并且最小能设置到0,最大则要看SETTING帧中能表示的最大整型数是多少,目前是 2^32 - 1.
我怎样才能避免保持 HPACK 状态?
发送一个 SETTINGS 帧将状态尺寸 (SETTINGS_HEADER_TABLE_SIZE) 设置到0, 然后 RST 所有的流,知道一个带有ACT设置位的 SETTINGS 帧发送了过来。
为什么会有一个单独的压缩/流控制上下文?
简洁.
原来的提案里面流分组这个概念,它可以共享上下文,流控制等等. 那样有利于代理 (也有利于经过它们的用户的体验), 而这样做相应也会增加一点复杂度. 所以我们就决定先以一个简单的东西开头,看看它会有多糟糕的问题,并且在未来的协议版本中解决这些问题(如果有的话).
在HPACK中为什么会有EOS符号?
由于CPU效率和安全的原因,HPACK的霍夫曼编码填充了霍夫曼编码字符串的下一个字节边界。因此对于任何特定的字符串可能需要0-7个比特的填充。
如果单独考虑霍夫曼解码,任何比所需要的填充长的符号都可以正常工作。但是,HPACK的设计允许按字节对比霍夫曼编码的字符串。通过填充EOS符号需要的比特,我们确保用户在做霍夫曼编码字符串字节级比较时是相等的。反之,许多 headers 可以在不需要霍夫曼解码的情况下被解析。
实现 HTTP/2 的时候我可以不用去实现 HTTP/1.1 么?
可以,完全可以。
对于运行在 TLS (h2) 之上的 HTTP/2 而言, 如果你没有实现 http1.1 的 ALPN 标识, 那你就就准备不需要支持任何 HTTP/1.1 特性的.
对于运行在 TCP (h2c) 之上的HTTP/2 而言, 你需要实现最原始的升级(Upgrade)请求.
只支持h2c的客户将需要生成一个请求 OPTIONS 的请求,因为 “*” 或者一个针对“/”的 HEAD 请求已经相当安全,并且也很容易构建. 寻求实现 HTTP/2 的客户将只需要把没有带上101状态码的HTTP/1.1响应看做一个错误就行了.
只支持h2c的服务器可以使用一个固定的101响应来接收一个包含升级(Upgrade)消息头字段的请求 . 没有h2c的Upgrade令牌的请求可以使用一个包含了Upgrade消息头字段的505(HTTP版本不支持)状态码来拒绝. 那些不希望处理 HTTP/1.1 响应的服务器应该在发送了带有鼓励用户在升级了的HTTP/2连接上重试的连接序言之后立即用带有 REFUSED_STREAM 错误码拒绝该请求的第一份数据流.
怎么调试加密过的 HTTP/2 ?
存取应用程序数据的方法很多,最简单的方法是使用 NSS keylogging 加 Wireshark 插件 (包含在最新开发版中),这种方式对 Firefox 和 Chrome 都适用。

---------------------------------------------------
HTTP发展历史
HTTP 0.9
只有一个GET方法
没有header等描述数据信息
服务器发送完毕,就关闭TCP连接
HTTP 1.0
增加了很多方法,例如POST,PUT,DELETE等
增加了status code和header
增加了多字符集的支持, 多部分发送,权限,缓存等;1996年5月发布,引入请求头和响应头
HTTP 1.1
持久连接/长连接
Pipeline 客户端可以在同一个连接中发送多个请求, 服务端按顺序返回(串行)
增加host头,有了host之后可以实现一台web服务可以接收/处理多个域名的请求
增加了其他更多的方法;1997年1月发布。支持长连接;添加Content-Length字段;分块传输编码等
HTTP 2.0
2.0所有的数据以二进制进行传输(帧),在1.1大部分是以字符串的形式传输
得益于基于帧的传输, 可以实现在同一个连接里面发送多个请求不再需要按顺序来返回(并行)
头信息压缩, 1.1的header头以字符串的形式进行传输,占用了大量带宽
推送,1.1之前只支持客户端主动向服务端发起请求,服务端被动向客户端响应请求; 2.0之后服务可以主动向客户端发送数据(例子:客户端在发起请求访问服务端页面时, 先请求html页面, 当客户端收到服务端发来的html数据之后,客户端浏览器进行解析并渲染, 在其中,发现了引用到了其他文件,如css、js文件,均以url链接形式引用,此时浏览器会按顺序再次对新的资源发起请求; 2.0中的此场景下, 客户端在请求了html页面后,服务端可以实现主动将css,js数据推送到客户端,从而解决了1.1串行请求资源的性能低下问题。并且服务端主动推送资源到客户端,也可以解决客户端因各种原因,请求不到指定资源的情况)
2.0 以提高效率为主要目标对1.1进行了大量改进。
SPDY
2012年Google发布。HTTP2.0就是基于SPDY设计的,其目前已经无人使用。添加多路复用(Multiplexing);header压缩(DEFLATE算法);服务端推送等
HTTP2.0
2015年发布。本文主要讲解内容,后文详细讨论
HTTP3.0
2018年发布。尚未学习,最大的特点可能是基于UDP协议,不在本文讨论范围
通过对HTTP/2的Wiki介绍,可以看下定义和发展历史。RFC 7540 定义了 HTTP/2 的协议规范和细节, RFC 7541定义了头部压缩。
http 1.0和http 1.1的缺点:
1.http1.0只允许在一个连接上建立当前未完成的请求。
2.http1.1管道只部分处理了请求并发和包头堵塞问题,客户端多建立TCP连接,减少延迟。
3.报头字段经常重复和冗长,数据包变大,容易造成初始TCP端口的堵塞,多建立几个TCP连接。
http 2x协议解决之道:
1.优化基础连接的语义映射,例如同一个连接上建立交错的请求和响应,使用高效率编码的报头字段。
2.允许请求的优先级,让更多重要的请求先完成。
http2协议的特点:
1.http2中最基本的协议单位是帧。每个帧都有不同的类型和用途。例如,报头(HEADERS)和数据(DATA)帧组成了基本的http请求和响应,帧包含的HTTP报头字段是压缩的。HTTP请求有可能是高度冗余的,因此压缩能显著减少请求和响应的大小。
2.请求多路复用:一个流上分配多个HTTP请求响应交换,流在很大程度上是相互独立的,因为一个请求上的阻塞和终止不会影响其他请求的处理。
3.流量控制和优先级确保正确使用复用流,流量控制有助于确保只传播接受需要的数据,优先级确保有限的资源能被重要的请求使用。
4.添加了一种新的交互模式,即服务器能推送消息给客户端。服务器推送允许服务端预测客户端需要来发送。
数据给客户端,交换网络使用以阻塞潜在的延迟增长。服务器通过复用一个以PUSH_PROMISE帧发送的请求来实现推送,然后服务端可以在一个单独的流里面发送响应给这个合成的请求。
------------------------------
HTTP/2 规格制定完成
IETF HTTP工作者的负责人Mark Nottingham在其博客上宣布HTTP/2规格制定完成,接下来将是分配RFC编号和正式发表。HTTP是Web的核心技术之一,相比HTTP/1,HTTP/2的改进之处包括更快的页面加载;更长久的连接;服务器推送,允许服务器主动向客户端推送消息;减少加密连接开销,改进性能;多路复用功能允许同时发送许多个请求。
HTTP/2使用HTTP/1相同的API,开发者不需要改变应用程序代码就能更新库支持HTTP/2。
---------------------------------------------------
HTTP/2 正式通过 IETF 组织批准发布
超过两年的讨论,超过 200 个设计问题, 17 个草案 和 30 个实现, HTTP/2 和 HPACK 规范终于通过了 IETF 组织的批准并作为可跟踪的 RFC 标准。HTTP/2 将帮助实现更快的用户浏览体验,降低带宽要求,同时更容易实现安全的通讯连接。
在 2012 年 HTTP Working Group 开始在 Google 的 SPDY 协议的基础上研究 HTTP/2 标准,通过 6 次组织内的会议以及来自社区的讨论完成了最初版本的确定。
协议被设计为可以在 HTTP/1 和 HTTP/2 中无缝切换,以最小化对应用和 API 的变化要求,同时提升性能以及更好的使用网络资源。Web 用户只需要沿用老的习惯就可以享用 HTTP/2 带来的提升。
协议开发过程中的关键点是协议的更新、实现和测试过程中的迭代。工作组会对一些特定版本进行标注以便于浏览器进行实现和测试,内部的会议主要是密集讨论这些问题。
HTTP/2 的工作具体体现了 IETF 的价值宗旨 —— 大致共识并运行代码。
---------------------------------------------------
HTTP/2 没有强制要求 TLS
HTTP/2规格已经制定完成,即将成为正式标准。在规格中,HTTP/2协议没有强制要求使用TLS, 主要原因是许多机构都想要检查HTTP流量,或网络环境需要缓存,或认为TLS会增加额外的负担,以及认为安全证书太昂贵,等等。虽然规格没有强迫使用 TLS实现HTTP/2支持,目前浏览器开发商在实现HTTP/2支持时都是经过TLS, Firefox 和Chrome开发团队的成员明确表示他们只实现使用TLS的HTTP/2,而IE的团队成员一开始表示他们不使用TLS,但Windows 10技术预览版上第一个支持HTTP/2的测试版本也是只使用TLS。
---------------------------------------------------
HTTP/2 规格正式发布,RFC 编号为 7540
2015年05月15日,互联网工程任务组正式发布了HTTP/2 规格,RFC编号为7540。HTTP/2的改进之处包括更快的页面加载、更长久的连接、服务器推送、允许服务器主动向客户端推送消息、减少加密连接开销改进性能、多路复用功能允许同时发送许多个请求。
HTTP协议演进
HTTP协议经过4个版本的演进,不断解决Web发展的问题,比如WEB2.0的复杂页面和移动互联网时代的手机浏览器页面,本文简单对比这些演进版本的。

HTTP1.0和HTTP1.1的一些区别
HTTP1.0最早在网页中使用是在1996年,那时候只是使用在一些较为简单的网页和网络请求上,而HTTP1.1则在1999年才开始广泛应用于现在的各大浏览器网页中,同时HTTP1.1也是当前使用最为广泛的HTTP协议。 主要区别体现在:
缓存处理,在HTTP1.0中主要使用header里的If-Modified-Since,Expires来做为缓存判断的标准,HTTP1.1则引入了更多的缓存控制策略例如Entity tag,If-Unmodified-Since, If-Match, If-None-Match等更多可供选择的缓存头来控制缓存策略。
带宽优化及网络连接的使用,HTTP1.0中,存在一些浪费带宽的现象,例如客户端只是需要某个对象的一部分,而服务器却将整个对象送过来了,并且不支持断点续传功能,HTTP1.1则在请求头引入了range头域,它允许只请求资源的某个部分,即返回码是206 Partial Content,这样就方便了开发者自由的选择以便于充分利用带宽和连接。
错误通知的管理,在HTTP1.1中新增了24个错误状态响应码,如409 Conflict表示请求的资源与资源的当前状态发生冲突;410 Gone表示服务器上的某个资源被永久性的删除。
Host头处理,在HTTP1.0中认为每台服务器都绑定一个唯一的IP地址,因此,请求消息中的URL并没有传递主机名hostname。但随着虚拟主机技术的发展,在一台物理服务器上可以存在多个虚拟主机Multi-homed Web Servers,并且它们共享一个IP地址。HTTP1.1的请求消息和响应消息都应支持Host头域,且请求消息中如果没有Host头域会报告一个错误400 Bad Request。
长连接,HTTP 1.1支持长连接PersistentConnection和请求的流水线Pipelining处理,在一个TCP连接上可以传送多个HTTP请求和响应,减少了建立和关闭连接的消耗和延迟,在HTTP1.1中默认开启Connection:keep-alive,一定程度上弥补了HTTP1.0每次请求都要创建连接的缺点。
HTTP 1.0和1.1现存的一些问题
上面提到过的,HTTP1.x在传输数据时,每次都需要重新建立连接,无疑增加了大量的延迟时间,特别是在移动端更为突出。
HTTP1.x在传输数据时,所有传输的内容都是明文,客户端和服务器端都无法验证对方的身份,这在一定程度上无法保证数据的安全性。
HTTP1.x在使用时,header里携带的内容过大,在一定程度上增加了传输的成本,并且每次请求header基本不怎么变化,尤其在移动端增加用户流量。
虽然HTTP1.x支持了keep-alive,来弥补多次创建连接产生的延迟,但是keep-alive使用多了同样会给服务端带来大量的性能压力,并且对于单个文件被不断请求的服务(例如图片存放网站),keep-alive可能会极大的影响性能,因为它在文件被请求之后还保持了不必要的连接很长时间。
HTTP2.0新特性
新的二进制格式Binary Format,HTTP1.x的解析是基于文本。基于文本协议的格式解析存在天然缺陷,文本的表现形式有多样性,要做到健壮性考虑的场景必然很多,二进制则不同,只认0和1的组合。基于这种考虑HTTP2.0的协议解析决定采用二进制格式,实现方便且健壮。
多路复用MultiPlexing,即每一个request都是连接共享机制。一个request对应一个id,这样一个连接上可以有多个request,每个连接的request可以随机的混杂在一起,接收方可以根据request的 id将request再归属到各自不同的服务端请求里面。多路复用原理图:

HTTP/2 Inside: multiplexing
header压缩,如上文中所言,前面提到过HTTP 1.x的header带有大量信息,而且每次都要重复发送,HTTP2.0使用encoder来减少需要传输的header大小,通讯双方各自cache一份header fields表,既避免了重复header的传输,又减小了需要传输的大小。
服务端推送server push,例如我的网页有一个style.css的请求,在客户端收到style.css数据的同时,服务端会将style.js的文件推送给客户端,当客户端再次尝试获取style.js时就可以直接从缓存中获取到,不用再发请求了。
---------------------------------------------------
经典五层模型
应用层 -> HTTP/FTP
传输层 -> TCP/UDP
网络层: 数据在节点之间传输创建逻辑链路
数据链路层: 在通信的实体间建立数据链路连接(0101)
物理层: 定义物理设备如何传输数据
传输层
向用户提供可靠的端到端的服务, 传输层向高层屏蔽了下层数据通信的细节
应用层
为应用软件提供服务, 构建在传输层协议之上, 屏蔽网络通信细节
HTTP(TCP)的三次握手
三次握手是TCP连接中的概念, HTTP不存在连接的概念, HTTP只有请求和响应的概念
每个HTTP的请求与响应都是需要基于一个TCP的连接的
User http requests -- TCP connection -- Server http response
在HTTP 1.0 版本中, 客户端发起一个HTTP请求, 此时, 会创建一条TCP连接通道, 在服务端处理完毕, 响应给客户端之后, 这条TCP连接就会被断掉
在HTTP 1.1版本中, 通过声明特殊的属性, 可以实现一个TCP连接上, 可以发送多个HTTP请求(长连接/Keepalive)
在HTTP 2.0 版本中,可以实现,同一个客户端请求同一个服务端,只需要一个TCP连接即可,因为2.0版本支持并行发送请求,和并行接收请求,不需要再额外创建更多的TCP连接
---------------------------------------------------
HTTP/2 常见问题回答
为什么修订HTTP?
HTTP/1.1已经很好的服务Web超过15个年头,但它的劣势开始显现。
载入一个Web页面比之前占用更多的资源(详情可见HTTP压缩页大小统计),有效的载入这些资源很难,因为HTTP实际上对每个TCP连接,只允许一个优先的请求。
在过去,对于并发请求,浏览器使用多个TCP连接。然而,这也是有局限的;如果使用了过多的连接,这既是一种计数上的高产(TCP阻塞控制是被有效否定的,导致阻塞事件影响性能和网络),也基本上是不公平的(因为浏览器承受的资源大于它们享有的网络资源)。
同时,大量的请求意味着“线上”有很多重复的数据。
HTTP/1.1耗费大量的开销是与这两个因素有关。如果发生过多的请求,会影响性能。
这些导致了相关行业成为了像雪碧、数据内联、域共享和级联的最佳练习场地。这些问题被认为是底层协议自身的问题,并导致在使用它们时产生了一系列的问题。
谁正在做这件事?
IETF的HTTPbis工作组正在开发HTTP/2,他们负责维护HTTP协议。是由若干HTTP实现者、用户、网络运营商和HTTP专家组成。
注意虽然工作组的邮件列表是托管在W3C网站上,不过却不是W3C的功劳。但是, Tim Berners-Lee 和 W3C TAG与WG的进程保持了一致。
大量的人对相关工作作出了共享,不过大部分活跃参与者是来自像Firefox、Chrome、Twitter、Microsoft的HTTP栈、Curl和Akamai这样大项目的工程师,以及若干Python、Ruby和NodeJS的HTTP实现者。
要了解更多IETF参与者,请看IETF之道。你也可以在Github的贡献者图表中了解到哪些人正在对规范做贡献,在我们的实现者列表了解哪些人正在参与实施。
和SPDY是怎样的关系?
HTTP/2 第一次出现并被讨论的时候, SPDY 正得到厂商 (像 Mozilla 和 nginx)的青睐和支持, 并被看成是HTTP/1.x 基础上的重大改善.
经过建议和投票之后, SPDY/2 被列为HTTP/2 的基础.从那时起, 根据工作组的讨论和厂商的反馈,它已经有了很多变化。
在整个过程中,SPDY 的核心开发成员都参与了HTTP/2 的发展, 其中也包括 Mike Belshe 和 Roberto Peon. 事实上,已经发布的 SPDY/4 revision 正是基于 HTTP/2的 ,因为SPDY社区现在发现它是作为一种进一步实验反馈到 HTTP/x的工具, 而不是竞争对手.
是 HTTP/2.0 还是 HTTP/2?
工作组决定去掉小版本 (“.0”) 因为这在HTTP/1.x中导致了很多困惑.
也就是说, HTTP 的版本仅代表它的兼容性,不表示它的特性和 “亮点”
和HTTP/1.x的关键区别是什么?
在高版本 HTTP/2中:
是二进制的,代替原有的文本
是多路复用的, 代替原来的序列和阻塞机制
所以可以在一个连接中并行处理
压缩头部信息减小开销
允许服务器主动推送应答到客户端的缓存中
HTTP/2为什么是二进制的?
比起像HTTP/1.x这样的文本协议,二进制协议解析起来更高效、“线上”更紧凑,更重要的是错误更少。因为它们对如空白字符的处理、大小写、行尾、空链接等的处理很有帮助。例如,HTTP/1.1定义了四个不同的方法来解析一条消息;在HTTP/2中,仅需一个代码路径即可。
HTTP/2在telnet中将不可用,但是我们有一些工作提供支持,比如Wireshark plugin。
为什么 HTTP/2 需要多路传输?
HTTP/1.x 有个问题叫线端阻塞(head-of-line blocking), 它是指一个连接(connection)一次只提交一个请求的效率比较高, 多了就会变慢.
HTTP/1.1 试过用流水线(pipelining)来解决这个问题, 但是效果并不理想(数据量较大或者速度较慢的响应, 会阻碍排在他后面的请求). 此外, 由于网络媒介(intermediary )和服务器不能很好的支持流水线, 导致部署起来困难重重.
客户端使用一些启发式的方法(基本靠猜) 来决定通过哪些连接提交哪些请求; 由于一个页面加载的数据量, 往往比可用连接能处理的数据量的10倍还多, 对性能产生极大的负面影响, 结果经常引起瀑布式阻塞(waterfall of blocked requests).
而多路传输(Multiplexing)能很好的解决这些问题, 因为它能同时处理多个消息的请求和响应; 甚至可以在传输过程中将一个消息跟另外一个掺杂在一起.
所以客户端只需要一个连接就能加载一个页面。
为什么只要一个 TCP 连接?
目前的浏览器, 每个点 (origin) 打开 4 到 8 个连接(Connection). 而很多网站都支持多点传输(multiple origins), 也就是说, 光加载一个网页, 打开的连接数量就超过 30 个.
一个应用同时打开这么多连接, 已经远远超出了当初设计 TCP 时的预期; 每一个连接接收过多的数据, 又存在网络缓存溢出的风险, 结果导致网络堵塞和数据重传.
此外, 使用这么多连接还会强占许多网络资源. 这些资源都是从别人那 “偷” 来的. 你说这些应用够遵纪守法吧? (VoIP 就是个很好的例子).
服务器推送的好处是什么?
当浏览器请求一个网页时,服务器将会发回HTML,在服务器开始发送JavaScript、图片和CSS前,服务器需要等待浏览器解析HTML和发送所有内嵌资源的请求。
服务器推送服务通过“推送”那些它认为客户端将会需要的内容到客户端的缓存中,以此来避免往返的延迟。
消息头为什么需要压缩?
来自Mozilla的Patrick McManus通过计算消息头对平均页面负载的印象,对此进行了形象且充分的说明.
假定一个页面有80个资源需要加载(这个数量对于今天的Web而言还是挺保守的), 而每一次请求都有1400字节的消息头(着同样也并不少见,因为Cookie和引用等东西的存在), 至少要7到8个来回去“在线”获得这些消息头。这还不包括响应时间——那只是从客户端那里获取到它们所花的时间而已。
这全都由于TCP的慢启动机制,它会基于对已知有多少个包,来确定还要来回去获取哪些包 – 这很明显的限制了最初的几个来回可以发送的数据包的数量.
相比之下,即使是头部轻微的压缩也可以是让那些请求只需一个来回就能搞定——有时候甚至一个包就可以了。
这种开销是可以被节省下来的,特别是当你考虑移动客户端应用的时候,即使是良好条件下,一般也会看到几百毫秒的来回延迟。
为什么是 HPACK?
SPDY/2 提出在每一方都使用一个单独的GZIP上下文用于消息头压缩,者实现起来很容易,也很高效.
从那时候开始,就有了一个被证明能针对算法中使用流压缩(如GZIP)的重要攻击方式 CRIME.
CRIME 让那些能向加密流中诸如数据的攻击者获得了“探测”原文并进行还原的可能性。因为是Web,JavaScript使其成为了可能,而且已经有了使用针对受到TLS保护的HTTP资源的CRIME恢复cookie和认证令牌信息的证明。因此,我们不应该使用GZIP。由于找不到其它适合使用在这种用例下的安全有效的算法,我们创造了一种新的,特别针对消息头的压缩方案,它能进行粗粒度的操作;因为HTTP消息头并不常常需要改变,我们仍然可以得到很好的压缩效率,而且更加的安全.
HTTP/2 能让cookie(以及其他的消息头)更好么?
这一尝试被许可在网络协议的一个修订版本上运行 – 例如,HTTP消息头、方法等等如何才能在不改变HTTP语义的前提下放到"网络上“.
这是因为HTTP的使用是如此广泛。如果我们使用了这个版本的HTTP,引入了一种新的状态机制(例如之前讨论过的例子)或者改变的核心方法(幸好,这还没有发生过), 这可能就意味着新的协议将不会同现有的Web兼容.
具体地,我们是想要能够从HTTP/1转移到HTTP/2,并且不会有信息的丢失. 如果我们开始”清理”消息头(大多数人会认同,HTTP消息头现在简直是一团糟), 我们就不得不要去面对现有Web的诸多问题.
那样做只会为采用新协议的过程中制造麻烦.
总而言之,工作组会对所有的HTTP负责,而不仅仅只是HTTP/2. 因此,我们才可以在版本独立的新机制下运作,同时它们也能向后同现有的网络兼容。
非浏览器用户的HTTP会是什么情况呢?
人们期望非浏览器应用程序也能够用上HTTP/2,如果它们曾今使用过HTTP的话。
早起收到针对HTTP的“API”,HTTP/2具有性能好等特点这样的反馈,是因为API的设计中不需要考虑像请求开销这样一些事情。
之前说过,我们所要考虑的主要的提升重点是在典型的浏览器用例下, 因为这是协议主要的使用场景。
我们的章程里面是这样说的:
正在组织的规范能满足现在已经普遍部署了的HTTP的功能要求;
具体的,(桌面端和移动端的)Web浏览,(“HTTP API”形式的)非浏览器, (大范围的)Web服务,
还有各种(借助代理,企业防火墙,反向代理以及内容分发网络实现的)中介。
同样的,对HTTP/1.x当前和未来的语义扩展 (例如,消息头,方法,状态码,缓存指令) 都应该在新的协议中支持。
注意,这里没有涵盖将HTTP用于非特定行为所依赖的(例如超时,连接状态以及拦截代理)场景中;这些使用可能不会被最终的产品启用。
HTTP/2 需要加密吗?
不需要。在广泛的讨论后,工作组没有就新协议是否使用加密(如TLS)而达成共识。
不过,有些实现者说,只有HTTP/2使用加密链接他们才提供支持。
HTTP/2为提高安全性做了什么?
目前,HTTP/2定义了TLS的轮廓,包括版本、密码套件和用到的扩展。
细节参见相关规范。其中也讨论了额外的机制,如对HTTP://URLs(所谓的“机会主义加密”)使用TLS;参见 issue #315。
现在可以用HTTP/2吗?
HTTP/2暂时在主流浏览器中还不可用,不过还是有一些体验版的可以用,或许在“每夜(nightly)”频道可以找到。
还是有几个服务器可用的(包括 Akamai 和 Twitter主流网站提供了测试服务器),以及几个开源版的,你可以用来部署和测试。
HTTP/2会代替HTTP/1.x
工作组的目的是让那些使用HTTP/1.x也可以使用HTTP/2,并能感受到HTTP/2所带来的好处。工作组说过,由于人们部署代理和服务器的方式的原因,我们不能强迫整个世界进行迁移,所以HTTP/1.x很可能仍要使用了一段时间。
HTTP/3 会出现么?
如果通过HTTP/2引入的沟通协作机制运行良好, 那就有可能比过去更加容易的支持新版本的HTTP。
实现中的问题
为什么规则会围绕消息头帧的数据接续?
数据接续的存在是由于一个值(例如cookie)可以超过 16kb, 这意味着它不可能全部装进一个帧里面. 所以就决定以最不容易出错的方式让所有的消息头数据以一个接一个帧的方式传递, 这样就使得对消息头的解码和缓冲区的管理更加的容易。
HPACK状态的最小和最大尺寸是多少 ?
接收一方总是会控制HPACK中内存的使用量, 并且最小能设置到0,最大则要看SETTING帧中能表示的最大整型数是多少,目前是 2^32 - 1.
我怎样才能避免保持 HPACK 状态?
发送一个 SETTINGS 帧将状态尺寸 (SETTINGS_HEADER_TABLE_SIZE) 设置到0, 然后 RST 所有的流,知道一个带有ACT设置位的 SETTINGS 帧发送了过来。
为什么会有一个单独的压缩/流控制上下文?
简洁.
原来的提案里面流分组这个概念,它可以共享上下文,流控制等等. 那样有利于代理 (也有利于经过它们的用户的体验), 而这样做相应也会增加一点复杂度. 所以我们就决定先以一个简单的东西开头,看看它会有多糟糕的问题,并且在未来的协议版本中解决这些问题(如果有的话).
在HPACK中为什么会有EOS符号?
由于CPU效率和安全的原因,HPACK的霍夫曼编码填充了霍夫曼编码字符串的下一个字节边界。因此对于任何特定的字符串可能需要0-7个比特的填充。
如果单独考虑霍夫曼解码,任何比所需要的填充长的符号都可以正常工作。但是,HPACK的设计允许按字节对比霍夫曼编码的字符串。通过填充EOS符号需要的比特,我们确保用户在做霍夫曼编码字符串字节级比较时是相等的。反之,许多 headers 可以在不需要霍夫曼解码的情况下被解析。
实现 HTTP/2 的时候我可以不用去实现 HTTP/1.1 么?
可以,完全可以。
对于运行在 TLS (h2) 之上的 HTTP/2 而言, 如果你没有实现 http1.1 的 ALPN 标识, 那你就就准备不需要支持任何 HTTP/1.1 特性的.
对于运行在 TCP (h2c) 之上的HTTP/2 而言, 你需要实现最原始的升级(Upgrade)请求.
只支持h2c的客户将需要生成一个请求 OPTIONS 的请求,因为 “*” 或者一个针对“/”的 HEAD 请求已经相当安全,并且也很容易构建. 寻求实现 HTTP/2 的客户将只需要把没有带上101状态码的HTTP/1.1响应看做一个错误就行了.
只支持h2c的服务器可以使用一个固定的101响应来接收一个包含升级(Upgrade)消息头字段的请求 . 没有h2c的Upgrade令牌的请求可以使用一个包含了Upgrade消息头字段的505(HTTP版本不支持)状态码来拒绝. 那些不希望处理 HTTP/1.1 响应的服务器应该在发送了带有鼓励用户在升级了的HTTP/2连接上重试的连接序言之后立即用带有 REFUSED_STREAM 错误码拒绝该请求的第一份数据流.
怎么调试加密过的 HTTP/2 ?
存取应用程序数据的方法很多,最简单的方法是使用 NSS keylogging 加 Wireshark 插件 (包含在最新开发版中),这种方式对 Firefox 和 Chrome 都适用。
该文章最后由 阿炯 于 2022-05-21 20:21:27 更新,目前是第 3 版。