转载自 | 小米运维(公众号 ID:MI-SRE)html
HTTP/2 是现行 HTTP 协议(HTTP/1.x)的替代,但它不是重写,HTTP 方法 / 状态码 / 语义都与 HTTP/1.x 同样。不过,HTTP/2 修改了数据格式化(分帧)以及在客户端与服务器间传输的方式。HTTP/2 基于 SPDY3,专一于性能,最大的一个目标是在用户和网站间只用一个链接。前端
HTTP/2 经过支持完整的请求与响应复用来减小延迟,经过有效压缩 HTTP 报头字段将协议开销降至最低,同时增长对请求优先级和服务器推送的支持。java
HTTP/2 协议由如下两个 RFC 组成:nginx
影响一个 HTTP 网络请求的因素主要有两个:带宽和延迟。在当今的网络状况下,带宽通常再也不是瓶颈,因此咱们主要讨论下延迟。延迟通常由下面几个因素所形成:git
链接没法复用:
链接没法复用会致使每次请求都经历三次握手和慢启动。三次握手在高延迟的场景下影响较明显,慢启动则对文件类大请求影响较大。github
线头阻塞(Head-Of-Line Blocking):
致使带宽没法被充分利用,以及后续健康请求被阻塞。HOLB 是指在 HTTP/1.x 中,因为服务器必须按接受请求的顺序发送响应的规则限制,那么假设浏览器在一个(tcp)链接上发送了两个请求,那么服务器必须等第一个请求响应完毕才能发送第二个响应——HOLB。虽然如今浏览器容许每一个 origin 创建 6 个 connection,但大量网页动辄几十个或上百个资源,HOLB 依然是主要问题。
协议开销大:
HTTP/1.x 中 header 内容过大(每次请求 header 基本不怎么变化),增长了传输的成本。
安全因素:
在 HTTP 中传输的内容都是明文,客户端和服务端双方没法验证身份。web
链接复用:
在用户和网站之间只用一个链接,避免后续创建链接过程当中的几个往返和慢启动,同时减小了服务器的资源消耗。算法
没有线头阻塞:
采用新的二进制分帧层的机制,组成消息的帧能够乱序发送,帧到达对端从新组装,不须要等待前面的帧到达后再发送。chrome
报头压缩:
HTTP/2 协议中采用 HPACK 来压缩请求头和响应头,下降协议开销。数据库
更加安全:
当前主流浏览器,都只支持基于 HTTPS 部署的 HTTP/2。
HTTP 2.0 性能加强的核心,全在于新增的二进制分帧层,它定义了如何封装 HTTP 消息并在客户端和服务器之间传输,和 HTTP/1.x 对好比下图:
这里所谓的 “层”,指的是位于套接字接口与应用可见的高级 HTTP API 之间一个通过优化的新编码机制:HTTP 的语义(包括各类动词、方法、标头)都不受影响,不一样的是传输期间对它们的编码方式变了。HTTP/1.x 协议以换行符做为纯文本的分隔符,而 HTTP/2 将全部传输的信息分割为更小的消息和帧,并采用二进制格式对它们编码。
这样一来,客户端和服务器为了相互理解,都必须使用新的二进制编码机制:HTTP/1.x 客户端没法理解只支持 HTTP/2 的服务器,反之亦然。不过没关系,现有的应用没必要担忧这些变化,由于客户端和服务器会替咱们完成必要的分帧工做。
新的二进制分帧机制改变了客户端与服务器之间交换数据的方式。 为了说明这个过程,咱们须要了解 HTTP/2 的三个概念:
这些概念的关系总结以下:
帧是最小的通讯单位,承载着特定类型的数据,例如 HTTP 标头、消息负载等等。 来自不一样 数据流的帧能够交错发送,而后再根据每一个帧头的数据流标识符从新组装,以下图:
简言之,HTTP/2 将 HTTP 协议通讯分解为二进制编码帧的交换,这些帧对应着特定数据流中的消息。全部这些都在一个 TCP 链接内复用。这是 HTTP/2 协议全部其余功能和性能优化的基础。
在 HTTP/1.x 中,若是客户端要想发起多个并行请求以提高性能,则必须使用多个 TCP 链接。这是 HTTP/1.x 交付模型的直接结果,该模型能够保证每一个链接每次只交付一个响应(响应排队)。更糟糕的是,这种模型也会致使队首阻塞,从而形成底层 TCP 链接的效率低下。
HTTP/2 中新的二进制分帧层突破了这些限制,实现了完整的请求和响应复用:客户端和服务器能够将 HTTP 消息分解为互不依赖的帧,而后交错发送,最后再在另外一端把它们从新组装起来。
上图捕捉了同一个链接内并行的多个数据流。客户端正在向服务器传输一个 DATA 帧(数据流 5),与此同时,服务器正向客户端交错发送数据流 1 和数据流 3 的一系列帧。所以,一个链接上同时有三个并行数据流。
将 HTTP 消息分解为独立的帧,交错发送,而后在另外一端从新组装是 HTTP 2 最重要的一项加强。事实上,这个机制会在整个网络技术栈中引起一系列连锁反应,从而带来巨大的性能提高,让咱们能够:
HTTP/2 中的新二进制分帧层解决了 HTTP/1.x 中存在的队首阻塞问题,也消除了并行处理和发送请求及响应时对多个链接的依赖。结果,应用速度更快、开发更简单、部署成本更低。
HTTP 1.1 的有一个缺点是:当一个含有确切值的 Content-Length 的 HTTP 消息被送出以后,你就很难中断它了。固然,一般你能够断开整个 TCP 链接(但也不老是能够这样),但这样致使的代价就是须要经过三次握手来从新创建一个新的 TCP 链接。
一个更好的方案是只终止当前传输的消息并从新发送一个新的。在 HTTP/2 里面,咱们能够经过发送 RST_STREAM 帧来实现这种需求,从而避免浪费带宽和中断已有的链接。
将 HTTP 消息分解为不少独立的帧以后,咱们就能够复用多个数据流中的帧,客户端和服务器交错发送和传输这些帧的顺序就成为关键的性能决定因素。为了作到这一点,HTTP/2 标准容许每一个数据流都有一个关联的权重和依赖关系:
数据流依赖关系和权重的组合让客户端能够构建和传递 “优先级树”,代表它倾向于如何接收响应。反过来,服务器可使用此信息经过控制 CPU、内存和其余资源的分配设定数据流处理的优先级,在资源数据可用以后,带宽分配能够确保将高优先级响应以最优方式传输至客户端。
如上图,HTTP/2 内的数据流依赖关系经过将另外一个数据流的惟一标识符做为父项引用进行声明;若是忽略标识符,相应数据流将依赖于 “根数据流”。声明数据流依赖关系指出,应尽量先向父数据流分配资源,而后再向其依赖项分配资源。换句话说,“请先处理和传输响应 D,而后再处理和传输响应 C”。
共享相同父项的数据流(即,同级数据流)应按其权重比例分配资源。 例如,若是数据流 A 的权重为 12,其同级数据流 B 的权重为 4,那么要肯定每一个数据流应接收的资源比例,请执行如下操做:
将全部权重求和:4 + 12 = 16
将每一个数据流权重除以总权重:A = 12/16, B = 4/16 所以,数据流 A 应得到四分之三的可用资源,数据流 B 应得到四分之一的可用资源;数据流 B 得到的资源是数据流 A 所获资源的三分之一。 咱们来看一下上图中的其余几个动手示例:顺序为从左到右:
数据流 A 和数据流 B 都没有指定父依赖项,依赖于显式 “根数据流”;A 的权重为 12,B 的权重为 4。所以,根据比例权重:数据流 B 得到的资源是 A 所获资源的三分之一。 数据流 D 依赖于根数据流;C 依赖于 D。所以,D 应先于 C 得到完整资源分配。权重不重要,由于 C 的依赖关系拥有更高的优先级。 数据流 D 应先于 C 得到完整资源分配;C 应先于 A 和 B 得到完整资源分配;数据流 B 得到的资源是 A 所获资源的三分之一。 数据流 D 应先于 E 和 C 得到完整资源分配;E 和 C 应先于 A 和 B 得到相同的资源分配;A 和 B 应基于其权重得到比例分配。
如上面的示例所示,数据流依赖关系和权重的组合明确表达了资源优先级,这是一种用于提高浏览性能的关键功能,网络中拥有多种资源类型,它们的依赖关系和权重各不相同。不只如此,HTTP/2 协议还容许客户端随时更新这些优先级,进一步优化了浏览器性能。换句话说,咱们能够根据用户互动和其余信号更改依赖关系和从新分配权重。
注:数据流依赖关系和权重表示传输优先级,而不是要求,所以不能保证特定的处理或传输顺序。即,客户端没法强制服务器经过数据流优先级以特定顺序处理数据流。 尽管这看起来违反直觉,但倒是一种必要行为。 咱们不但愿在优先级较高的资源受到阻止时,还阻止服务器处理优先级较低的资源。
有了新的分帧机制后,HTTP/2 再也不依赖多个 TCP 链接去并行复用数据流;每一个数据流都拆分红不少帧,而这些帧能够交错,还能够分别设定优先级。所以,全部 HTTP/2 链接都是永久的,并且仅须要每一个来源一个链接,随之带来诸多性能优点。
大多数 HTTP 传输都是短暂且急促的,而 TCP 则针对长时间的批量数据传输进行了优化。 经过重用相同的链接,HTTP/2 既能够更有效地利用每一个 TCP 链接,也能够显著下降总体协议开销。不只如此,使用更少的链接还能够减小占用的内存和处理空间,也能够缩短完整链接路径(即,客户端、可信中介和源服务器之间的路径)这下降了总体运行成本并提升了网络利用率和容量。 所以,迁移到 HTTP/2 不只能够减小网络延迟,还有助于提升通量和下降运行成本。
在 HTTP/2 RFC 文档中建议实现时客户端不该该在给定的目的地上打开多个 HTTP/2 链接,目的地是由给定的 URI 肯定的 IP 地址及 TCP 端口,或者配置的代理 IP 和端口。固然客户端可使用不相同的服务端名称标识值或者提供不同的 ssl 证书对相同的 IP 地址及 TCP 端口打开多个链接,但应该避免对相同的配置上建立多个链接。
注:链接数量减小对提高 HTTPS 部署的性能来讲是一项特别重要的功能:能够减小开销较大的 TLS 链接数、提高会话重用率,以及从总体上减小所需的客户端和服务器资源。
流量控制是一种阻止发送方向接收方发送大量数据的机制,以避免超出后者的需求或处理能力:发送方可能很是繁忙、处于较高的负载之下,也可能仅仅但愿为特定数据流分配固定量的资源。例如,客户端可能请求了一个具备较高优先级的大型视频流,可是用户已经暂停视频,客户端如今但愿暂停或限制从服务器的传输,以避免提取和缓冲没必要要的数据。再好比,一个代理服务器可能具备较快的下游链接和较慢的上游链接,而且也但愿调节下游链接传输数据的速度以匹配上游链接的速度来控制其资源利用率;等等。
不过,因为 HTTP/2 数据流在一个 TCP 链接内复用,TCP 流控制既不够精细,也没法提供必要的应用级 API 来调节各个数据流的传输。为了解决这一问题,HTTP/2 提供了一组简单的构建块,这些构建块容许客户端和服务器实现其本身的数据流和链接级流量控制:
HTTP/2 未指定任何特定算法来实现流量控制。不过,它提供了简单的构建块并推迟了客户端和服务器实现,能够实现自定义策略来调节资源使用和分配,以及实现新传输能力,同时提高网络应用的实际性能和感知性能。
例如,应用层流量控制容许浏览器仅提取一部分特定资源,经过将数据流流控制窗口减少为零来暂停提取,稍后再行恢复。换句话说,它容许浏览器提取图像预览或首次扫描结果,进行显示并容许其余高优先级提取继续,而后在更关键的资源完成加载后恢复提取。
HTTP/2 新增的另外一个强大的新功能是,服务器能够对一个客户端请求发送多个响应。 换句话说,除了对最初请求的响应外,服务器还能够向客户端推送额外资源(以下图),而无需客户端明确地请求。
注:HTTP/2 打破了严格的请求 - 响应语义,支持一对多和服务器发起的推送工做流,在浏览器内外开启了全新的互动可能性。这是一项使能功能,对咱们思考协议、协议用途和使用方式具备重要的长期影响。
为何在浏览器中须要一种此类机制呢?一个典型的网络应用包含多种资源,客户端须要检查服务器提供的文档才能逐个找到它们。那为何不让服务器提早推送这些资源,从而减小额外的延迟时间呢?服务器已经知道客户端下一步要请求什么资源,这时候服务器推送便可派上用场。
事实上,若是在网页中内联过 CSS、JavaScript,或者经过数据 URI 内联过其余资产,那么就已经亲身体验过服务器推送了。对于将资源手动内联到文档中的过程,咱们其实是在将资源推送给客户端,而不是等待客户端请求。使用 HTTP/2,咱们不只能够实现相同结果,还会得到其余性能优点。 推送资源能够进行如下处理:
全部服务器推送数据流都由 PUSH_PROMISE 帧发起,代表了服务器向客户端推送所述资源的意图,而且须要先于请求推送资源的响应数据传输。这种传输顺序很是重要:客户端须要了解服务器打算推送哪些资源,以避免为这些资源建立重复请求。知足此要求的最简单策略是先于父响应(即,DATA 帧)发送全部 PUSH_PROMISE 帧,其中包含所承诺资源的 HTTP 标头。
在客户端接收到 PUSH_PROMISE 帧后,它能够根据自身状况选择拒绝数据流(经过 RST_STREAM 帧)。 (若是资源已经位于缓存中,可能会发生这种状况。) 这是一个相对于 HTTP/1.x 的重要提高。 相比之下,使用资源内联(一种受欢迎的 HTTP/1.x“优化”)等同于 “强制推送”:客户端没法选择拒绝、取消或单独处理内联的资源。
使用 HTTP/2,客户端仍然彻底掌控服务器推送的使用方式。客户端能够限制并行推送的数据流数量;调整初始的流控制窗口以控制在数据流首次打开时推送的数据量;或彻底停用服务器推送。这些优先级在 HTTP/2 链接开始时经过 SETTINGS 帧传输,可能随时更新。
推送的每一个资源都是一个数据流,与内嵌资源不一样,客户端能够对推送的资源逐一复用、设定优先级和处理。 浏览器强制执行的惟一安全限制是,推送的资源必须符合原点相同这一政策:服务器对所提供内容必须具备权威性。
每一个 HTTP 传输都承载一组报头,这些报头说明了传输的资源及其属性。 在 HTTP/1.x 中,此元数据始终以纯文本形式,一般会给每一个传输增长 500–800 字节的开销。若是使用 HTTP Cookie,增长的开销有时会达到上千字节。为了减小此开销和提高性能, HTTP/2 使用 HPACK 压缩格式压缩请求和响应标头元数据,这种格式采用两种简单可是强大的技术:
利用 Huffman 编码,能够在传输时对各个值进行压缩,而利用以前传输值的索引列表,咱们能够经过传输索引值的方式对重复值进行编码,索引值可用于有效查询和重构完整的标头键值对。
做为一种进一步优化方式,HPACK 压缩上下文包含一个静态表和一个动态表:静态表在规范中定义,并提供了一个包含全部链接均可能使用的经常使用 HTTP 标头字段(例如,有效标头名称)的列表;动态表最初为空,将根据在特定链接内交换的值进行更新。所以,为以前未见过的值采用静态 Huffman 编码,并替换每一侧静态表或动态表中已存在值的索引,能够减少每一个请求的大小。
注:在 HTTP/2 中,请求和响应标头字段的定义保持不变,仅有一些微小的差别:全部标头字段名称均为小写,请求行如今拆分红各个 :method、:scheme、:authority 和 :path 伪标头字段。
至于 HPACK 压缩的详细介绍,请点击这里:HTTP/2 头部压缩技术介绍或者官方 RFC。
为了测试 HTTP/2 对 web 访问的性能提高,本人借助 bbs 产品线的 miui 官方网站,开启了 tengine 的 HTTP/2 的支持,取一周的访问数据与 HTTPS、HTTP 访问数据进行对比分析,详细结果以下:
响应类型分布
请求类别 | http | https | http2 |
---|---|---|---|
2xx | 945144 | 927482 | 505702 |
3xx | 243075 | 258331 | 681997 |
4xx | 2372 | 4750 | 2813 |
5xx | 9 | 37 | 88 |
sum | 1190600 | 1190600 | 1190600 |
2xx 请求各个响应时间段占比(基于 nginx log 的 request_time 数据)
时间 | http | https | http2 |
---|---|---|---|
<50ms | 79.75% | 78.89% | 82.60% |
<100ms | 87.24% | 87.47% | 89.86% |
<150ms | 91.12% | 91.90% | 93.19% |
<200ms | 92.72% | 93.82% | 94.54% |
<2s | 98.99% | 99.71% | 99.48% |
2xx 请求响应时间大于 7 秒的数量 (基于 nginx log 的 request_time 数据)
时间 | http | https | http2 |
---|---|---|---|
>7s | 1960(0.207%) | 603(0.065%) | 950(0.187%) |
>10s | 1519(0.160%) | 420(0.045%) | 638(0.126%) |
>30s | 594(0.062%) | 165(0.017%) | 190(0.037%) |
>60s | 259(0.027%) | 104(0.011%) | 97(0.019%) |
2xx 请求后端响应时间超过 7 秒的数量(基于 nginx log 的 upstream_response_time)
时间 | http | https | http2 |
---|---|---|---|
>7s | 68(0.007%) | 88(0.017%) | 58(0.006%) |
301 请求响应大小(基于 nginx 的 request_length 和 bytes_sent 数据)
/static/image/common/miui9.jpg | 请求数 | 总大小(byte) | avg(byte) | 请求总大小(byte) | 请求avg(byte) |
---|---|---|---|---|---|
http | 2722 | 1460146 | 536 | 3194589 | 1173 |
https | 4695 | 2618278 | 415 | 8019924 | 1708 |
http2 | 16239 | 6751609 | 557 | 1209570 | 74 |
200 请求响应大小(基于 nginx log 的 request_length 和 bytes_sent 数据)
/favicon.ico | 请求数 | 响应总大小(byte) | 响应avg(byte) | 请求总大小(byte) | 请求avg(byte) |
---|---|---|---|---|---|
http | 17658 | 23552229 | 1413 | 15300656 | 866 |
https | 117178 | 165623779 | 1413 | 122356406 | 1044 |
http2 | 80856 | 105496656 | 1304 | 10015908 | 123 |
客户端分析(基于 nginx log 的 user_agent 数据)
协议 | chrome | MSIE | safari | FireFox | Crawlers | others | unknown | |
---|---|---|---|---|---|---|---|---|
http | 23.53% | 4.26% | 3.56% | 0.67% | 4.01% | 15.07% | 48.22% | |
https | 79.24% | 5.93% | 3.67% | 1.54% | 7.87% | 1.42% | 0.1% | |
http2 | 88.57% | 4.93% | 1.91% | 1.57% | 0% | 2.9% | 0.03% |
平台分析(基于 nginx log 的 user_agent 数据)
协议 | Android | Windows | Linux | IOS | Darwin | unknown | |
---|---|---|---|---|---|---|---|
http | 28.4% | 16.07% | 0.29% | 2.46% | 0.12% | 51.86% | |
https | 64.85% | 24.65% | 0.62% | 0.54% | 0.29% | 9.05% | |
http2 | 40.06% | 57.62% | 1.49% | 0.44% | 0% | 0.02% |
实现 HTTP/2 很简单,不过,HTTP/2 并非万能的银弹,它只对某些 Web 应用有用,对另一些则没那么有用。
若是你使用 SSL/TLS(之后简称 TLS),那么 HTTP/2 能够提高网站性能。若是你没有,那在使用 HTTP/2 以前要先支持 TLS。这时候,使用 TLS 的性能损耗大体能够被使用 HTTP/2 的性能提高抵销。不过仍是建议你在实际应用以前先测试一下。
HTTP/2 有五大优点:
相应地,HTTP/2 也有五个不足之处。
总之,一切要看性能。这方面,有好消息也有坏消息。
好消息是 nginx 官方团队在内部对 NGINX 作过测试,结果从理论上可以获得印证:对于要经过典型网络延迟请求的混合内容网页,HTTP/2 的性能好于 HTTP/1.x 和 HTTPS。基于链接的 RTT,结果能够分三种状况。
这张图显示了首次渲染的时间,也就是用户第一次在本身屏幕上看到网页内容的时间。这个时间通常认为关系到用户对网站响应速度的感知。
然而,每一个网页都不相同,实际上每一个用户的会话也不同。若是你托管流媒体或提供大文件下载,那你的决定可能不同,甚至相反。
终止协议意味着客户端使用指望的协议链接代理服务器,好比 TLS 或 HTTP/2,而后代理服务器再去链接应用服务器、数据库服务器等,但不须要使用相同的协议,以下图所示。
使用独立的服务器终止协议意味着使用多服务器架构。多服务器多是多个物理服务器、多个虚拟服务器,或者 AWS 这样的云环境中的多个虚拟服务器实例。多服务器就比单服务器复杂,或者比应用服务器 / 数据库服务器的组合复杂。不过,多服务器架构有不少好处,并且不少流量大的网站也必须用这种架构。
配置了服务器或者虚拟服务器以后,不少事情都成为可能。新服务器能够分担其余服务器的负载,可用于负载平衡、静态文件缓存和其余用途。另外,也可让添加和替换应用服务器或其余服务器更容易。
NGINX 和 NGINX Plus 常常被用来终止 TLS 和 HTTP/2 协议、负载平衡。已有环境没必要改动,除非要把 NGINX 服务器挪到前端。
在决定采用 HTTP/2 以前,首先得知道你的代码有哪些是针对 HTTP/1.x 优化过的。大概有四方面的优化。
后面三种优化都涉及把小文件塞进一个较大的文件里,目的是减小新建链接的初始化和握手,这些操做对 TLS 而言很是费时间。
第一种优化即分域存储偏偏相反,强制打开多个链接,目的是并行地从不一样的域获取文件。这两种看似矛盾的技术对于 HTTP/1.x 下的站点却十分有效。然而,要用好这两种技术,必须投入大量时间、精力和资源,用于实现、管理和运维。
在采用 HTTP/2 以前,须要找出应用了这些优化的代码,分析一下它们会不会影响你的应用设计和工做流程。这样在迁移到 HTTP/2 以后,就能够着手改造它们,甚至撤销某些优化。
事实上,部署 HTTP/2 并不难。若是使用 NGINX,只要在配置文件中启动相应的协议就能够了。浏览器和服务器会协商采用什么协议,若是浏览器支持 HTTP/2(并且也在使用 TLS),就会使用 HTTP/2。
配置完服务器后,使用支持 HTTP/2 浏览器的用户就会基于 HTTP/2 运行你的应用,而使用旧版本浏览器的用户则会继续使用 HTTP/1.x 运行你的应用,以下图所示。若是你的网站流量很是大,那么应该监测改变先后的性能,对于性能下降的状况,可能就得撤销更改。
注意:使用 HTTP/2 及其单链接以后,NGINX 某些配置的重要性会很明显,特别要注意的是 output_buffers、proxy_buffers 和 ssl_buffer_size 等指令,多测试一下。参见 general configuration notes,特定的 SSL 建议,以及 NGINX 关于 SSL 性能的白皮书。
注意:使用 HTTP/2 传输密文要格外注意。HTTP/2 的 RFC 中有一个长长的列表,列出了要避免的加密套件。建议你本身也搞一个表格,启用 ssl_buffer_size,而后在全部经常使用的浏览器版本下测试你想用的加密套件。
你说奇怪不,撤销和修改针对 HTTP/1.x 优化的代码竟然是实现 HTTP/2 最有创意的部分。这里面有几个问题要注意,由于不少事怎么作都是能够的。
在开始运做以前,必须考虑旧版本浏览器用户是否好过。以后,能够采起三个策略撤销和修改 HTTP/1.x 的优化。
缓存仍是普适的。理论上,缓存操做很是适合小文件特别多的状况。可是,小文件多也意味着文件 I/O 多。所以一些相近文件的合并仍是必要的,一方面要考虑工做流程,另外一方面要考虑应用性能。建议多关注一下其余人在过渡到 HTTP/2 过程当中的一些经验。
分域存储多是最极端但也最成功的 HTTP/1.x 优化策略。它可以提高 HTTP/1.x 下的应用性能,但在 HTTP/2 之下,其性能提高能够忽略不讲(由于只有一个链接。)
对 HTTP/2 友好的分域,要保证如下两点:
有了这些保障,分域还会继续对 HTTP/1.x 有效,即域名仍然能够触发浏览器建立更多链接,但对 HTTP/2 则无效,由于这些域名会被当作同一个域,一个链接就能够访问全部域名了。
若是业务提供的是 web 形式的内容,经过浏览器进行访问,因为当前大部分的浏览器都已经支持 HTTP/2 了,因此基本不需进行任何操做,如下为支持 HTTP/2 的浏览器列表:
浏览器 | 支持HTTP/2 | 基于的内核 | 备注 | |
---|---|---|---|---|
Chrome(49) | 支持 | 从49版本开始支持 | ||
IE 11 | 不支持 | win10系统上的IE11支持h2 | ||
Edge(14) | 支持 | 从14版本开始支持 | ||
Safari(10.1) | 支持 | 从10.1版本开始支持,但都须要OSX10.11+以上系统版本 | ||
Firefox(52) | 支持 | 从52版本开始支持 | ||
Opera(47.0.2631.55) | 支持 | 从46版本开始支持 | ||
搜狗浏览器(7.1.5.25209) | 支持 | |||
猎豹浏览器(6.0.114.15532) | 支持 | |||
2345加速浏览器(8.7.0.16013) | 支持 | |||
百度浏览器(8.7.5000.4962) | 不支持 | chrome 47 | ||
QQ浏览器(9.6.4) | 支持 | chrome 53 | ||
360浏览器(9.1.0.346) | 支持 | chrome 55 | ||
360极速浏览器(8.7.0.306) | 支持 |
安卓 app 基本采用 JAVA 开发,因为各个应用采用的与服务端通讯的 http 库各不相同,有的是采用 jdk 自带的 httpurlconnection 库和 httpclient 库,有的用的是安卓系统自带的 webview 或者 volley(volley 的 HTTP/2 支持依赖于所使用的 httpstack,默认使用 httpurlconection,但如今也有不少开发者使用第三方的 okhttp 做为 volley 的 httpstack),而有的开发者直接使用的是第三方库相似于 okhttp,netty 等,这些 http 库对 http2.0 的支持状况各不相同。
基于 java 开发的 http 库对 HTTP/2 的支持状况以下:
Golang 的 net/http 库从 Go1.6 版本开始支持 http2,并默认开启
名称 | 支持的版本 | 支持的协商机制 | |
---|---|---|---|
Apache HTTP Server 2.4.17+ | h2,h2c | ALPN,Upgrade,direct | |
Apache Tomcat 8.5+ | h2,h2c | ALPN,Upgrade,direct | |
Nginx | h2,h2c | ALPN,NPN,direct | |
Tengine 2.1.2+ | h2 | ALPN | |
Twisted | h2 | NPN,ALPN | |
Netty | h2,h2c | ALPN,NPN,Upgrade,direct |
在 HTTP/2 的 github 中维护了一份 HTTP/2 协议的实现列表,更加详细,可供参考。
因为现有的 URI 结构正在被 HTTP 1.x 使用而不能被更换,因此 HTTP/2 也必须沿用该结构。所以不得不找到一种方式将使用的协议升级至 HTTP/2,好比能够要求服务器让它做响应时使用 HTTP/2 来替代旧的协议。
HTTP 1.1 自己就制定过 “升级” 的方案:提供一个首部字段,表示容许服务器在收到旧协议请求的同时,能够向客户端发送新协议的响应。但这一方案每每须要花费一次额外的往返通讯来做为升级的代价。
而这一代价是 SPDY 团队不想接受的。由于他们只实现了基于 TLS 的 SPDY,因此他们开发了一个 TLS 的扩展去简化协议的协商。这个扩展被称做 NPN(Next Protocol Negotiation),借助于此,服务器会通知客户端全部它支持的协议,让客户端从中选择一个合适的来进行通信。
IETF 将这个非正式标准 --NPN 进行规范化,从而演变成了 ALPN(Application Layer Protocol Negotiation)。ALPN 会随着 HTTP/2 的应用被推广,而 SPDY 的客户端与服务器则会继续使用 NPN。
因为 NPN 先于 ALPN 诞生,而 ALPN 又经历了一些标准化过程,因此许多早期的 HTTP/2 客户端和服务器在协商 HTTP/2 时会将这二者同时实现。与此同时,考虑到 SPDY 会使用 NPN,而许多服务器又会同时提供 SPDY 以及 HTTP/2,因此在这些服务器上同时支持 ALPN 以及 NPN 显然会成为最理所固然的选择。
ALPN 和 NPN 的主要区别在于:谁来决定通讯协议。在 ALPN 的描述中,是让客户端先发送一个协议优先级列表给服务器,由服务器最终选择一个合适的。而 NPN 则正好相反,客户端有着最终的决定权。
ALPN 扩展的具体资料,能够参考 Jerry Qu 写的这篇博客:谈谈 HTTP/2 的协议协商机制
QUIC (Quick UDP Internet Connection,快速 UDP 互联网链接) 是一个新的基于 UDP 的多路复用且安全的传输协议,它从头开始设计,且为 HTTP/2 语义作了优化。尽管以 HTTP/2 做为主要的应用协议而构建,然而 QUIC 的构建是基于传输和安全领域数十年的经验的,且实现了使它成为有吸引力的现代通用传输协议的机制。QUIC 提供了等价于
HTTP/2 的多路复用和流控,等价于 TLS 的安全机制,及等价于 TCP 的链接语义、可靠性和拥塞控制。
QUIC 彻底运行于用户空间,它当前做为 Chromium 浏览器的一部分发布给用户,以便于快速的部署和实验。做为基于 UDP 的用户空间传输协议,QUIC 能够作一些因为遗留的客户端和中间设备,或旷日持久的操做系统开发和部署周期的阻碍,而被证实很难在现有的协议中部署的创新。
QUIC 的一个重要目标是经过快速的实验得到更好的传输设计相关的知识。
基于早期的部署的 QUIC 标准化建议为 [draft-hamilton-quic-transport-protocol],[draft-shade-quic-http2-mapping],[draft-iyengar-quic-loss-recovery],和 [draft-thomson-quic-tls]。
更加详细的资料请参考这里:中文文档; Chromium 的 QUIC 主页。