先说一下 HTTP 的发展简史,以及 HTTP/2.0的优点在哪里。html
1991年发布的 HTTP/0.9 版本 是基于 TCP/IP 协议的应用层协议。它不涉及数据包的传输,只规定了客户端和服务器之间的通讯格式,默认使用80端口,该版本极其简单,只有一个命令 GET , 而且只支持文本传输。前端
请求过程: TCP 创建后,客户端向服务器请求 网页 如 index.html , 而且协议规定, 服务器只能回应 HTML 格式的字符串, 不能回应别的格式。 服务器发送完毕后, 就关闭链接。浏览器
1996年5月, HTTP/1.0 版本发布。缓存
首先: 加入了不少格式的内容均可以发送,这使得互联网不只能够传输文字,还能传输图像、视频、二进制文件。 经过此次的更新,为互联网的大发展奠基了基础。安全
其次: 除了GET命令,还加入了 POST 、HEAD 等命令, 丰富了浏览器与服务器的交互手段。服务器
最后: HTTP 请求和回应的格式也变了。 除了数据部分,每次通讯都必须包括头信息(HTTP header),用来描述一些元数据。微信
其余的新增功能还包括状态码、多字符集支持、多部分发送、权限、缓存、内容编码 等网络
相比 HTTP/0.9 有巨大的变化。微信公众平台
可是, HTTP/1.0 仍是存在一些缺点,其中主要缺点是,每一个TCP链接只能发送一个请求。发送数据完毕,链接就关闭,若是还要请求其余资源,就必须再新建一个链接。工具
TCP 新建链接的成本很高,由于须要客户端和服务器三次握手,而且开始时发送速率较慢,由于 TCP 经过慢开始启动。 因此,HTTP/1.0 版本的性能就比较差。 随着网页加载的外部资源愈来愈多,这个问题就愈发突出了。
解决每次都要从新创建链接的方法是: 在客户端和服务器端各自都加了一个 Connection: keep-alive 以便请求复用。可是,这个字段不是标准字段, 不一样实现的行为可能不一致, 所以不是根本的解决方法。
1997年1月, HTTP/1.1 版本发布, 只比 1.0 版本晚了半年。 它进一步完善了 HTTP 协议,一直用到了20年后的今天, 直到如今仍是最流行的版本。
加入了一些新的功能如:
持久链接
Connection: keep-alive , 即 TCP 链接时默认不关闭, 能够被多个请求复用,不用声明 Connection: keep-alive。
客户端和服务器发现对方一段时间没有活动,就能够主动关闭链接。规范的作法是,客户端在最后一个请求时,发送 Connection: close , 明确要求服务器关闭 TCP 链接。 Connection: close
目前,为了安全性,对于同一个域名,大多数浏览器容许同时创建6个持久链接。
管线化:即在同一个 TCP 链接里面,客户端能够同时发送多个请求, 这样就进一步改进了 HTTP 协议的效率。(虽然能够提升效率,可是支持的不多,用的也很少,确实会提高一些效率,可是而且也存在一些问题,后面HTTP/2.0再说)
Content-Length 字段
一个 TCP 链接同时能够传送多个回应,那么就须要有一种机制,区分数据包是属于哪个回应的。这就是 Content-Length 字段的做用, 声明本次回应的数据长度。
如: Content-Length: 3000
他告诉浏览器,本次回应的长度是 3000 字节, 后面的字节就属于下一个回应了。
在 HTTP/1.0 版本中, Content-Length 字段不是必须的,由于不涉及一次传多个回应,或者浏览器发现服务器关闭了 TCP链接,就代表收到的数据包已经全了。
分块传输编码
使用 Content-Length 字段的前提条件是, 服务器发送回应以前,必须知道响应的数据包长度。
对于一些很耗时的动态操做来讲,这意味着服务器须要等全部操做完成,才能发送数据,显然这样的效率不高。更好的处理方法是,产生一块数据,就发送一块,采用“流模式”(stream) 取代 “缓存模式”(buffer)。
所以,HTTP/1.1 版本规定能够不使用 Content-Length 字段,而使用 “分块传输编码”(chunked transfer encoding)。只要请求或回应的头信息有 Transfer-Encoding 字段, 就代表回应将由数量未定的数据块组成。
每一个非空的数据块以前,会有一个16进制的数值,表示这个块的长度。最后是一个大小为 0 的块, 就表示本次回应的数据发送完了。
其余功能
HTTP/1.1 版本还增长了不少动词方法如:PUT、PATCH、HEAD、OPTIONS、DELETE
另外,客户端请求的头信息新增了 Host 字段,用来指定服务器的域名。
有了Host字段,就能够将请求发往同一台服务器上的不一样网站,为虚拟主机的兴起打下了基础。
缺点
Spriting 是将众多个小图片整合成大图片,而后再拆分,坏处可想而知,每一个网页需不须要用到那么多图片,都须要发送。
内联(Inlining),简而言之就是把图片资源放在 CSS 文件里面的 URL 里面,这种缺点和 Spriting 相似。
拼接(Concatenation),若是 js 文件特别多的话,可使用工具把众多 js 文件整合成一个文件,这样浏览器就只须要下载一次就能够完成,而不是无数次请求去下载,可是若是 js 的某个代码被改动,那么也须要从新下载,这样会对调试和开发者形成极大的不变。
分片(Sharding),由于 HTTP/1.1 规范提到一个客户端最多能对同一主机创建有限个 TCP 链接。所以,Sharding 就是把服务分散在尽量多的服务器上面。这样用户就能够同时和多台主机创建不少 TCP 链接,从而下降载入时间。
线头阻塞
虽然加入了持久链接,管线化,可是同一个 TCP 链接里面,全部的数据通讯都是按次序进行的。服务器只有处理完一个回应,才会进行下一个回应。若是前面的回应特别慢,后面就会有不少请求排队等着。这称为“队头堵塞”(Head-line blocking)
为了不这个问题,有两种方法:一是减小请求数量,二是同时多开持久链接。这致使了不少的网页优化技巧,好比合并脚本和样式表,将图片嵌入 CSS 代码、域名分片等等。
为了解决此类问题的一些解决方法:
过多的可选项和太多的细节
而且 HTTP/1.1 包含了太多细节和可选的部分,这让它变得过于庞大。
过多的可选项,这就致使了在一些不经常使用的功能在后来的实现中不多会被支持,而有些最初实现了的功能,却又不多被使用。
随着时间的推移,这些当初看似被边缘化的功能逐渐被用上,客户端和服务器的互用性问题就暴露出来了。HTTP 管线化(HTTP pipelining) 就是一个很是好的例子。
未能被充分利用的 TCP
咱们能够经过更好的利用 TCP 来减小传输过程当中的暂停,并充分挖掘利用那些本能够用于发送/接收更多数据的时间。
传输大小和资源数量
近年来加载网站首页须要下载的数据量在逐渐增长,而且已经超过了 1.9MB。而且咱们更关心的是平均每一个页面为了完成显示与渲染所须要的资源已经超过100个了。
明显的延迟
HTTP/1.1 在网络延迟方面作的就不尽人意了。部分缘由是 HTTP 管线化(pipelining)还存在不少问题,因此对大部分用户来讲这项技术仍是默认被关闭的。虽然近几年,咱们的网络带宽从原来只有 几百KB ,如今通常的网络也能达到 数十MB ,可是 网络延迟也没有下降。好比在移动设备上,即便拥有高的链接速率,也很难得到优质快速的网络体验。
例如:能够将资源分布在不一样的主机上面来创建链接,得到更快的速度。
2009年,Google 公开了自行研发的 SPDY 协议, 主要解决 HTTP/1.1 效率不高的问题。
这个协议在 Chrome 浏览器上证实可行之后,就被当作 HTTP/2 的基础, 主要特性都在 HTTP/2 之中获得继承。
若是用 Chrome ,就会发现,在百度网站上就有用 SPDY 的例子:
2015年, HTTP/2 发布。它不叫 HTTP/2.0 ,是由于标准委员会不打算再发布自版本了,下一个新版本将是 HTTP/3。
改进
下降协议对延迟的敏感
修复 pipelining 和 head of line blocking 问题
防止主机须要更高的链接数量
保留全部现有的接口,内容,URI 格式和结构
HTTP/2 是一个二进制协议
咱们可使用 Wireshark 这样的 http/2 解析器来分析和调试协议。
http/2 会发送有着不一样类型的二进制帧,他们有一些公共字段,一共规范了10种不一样的帧,其中最基础的两种分别对应于 HTTP/1.1 的 DATA 和 HEADERS。
多路复用的流,实现双向的,实时的通讯,多工。
数据包具备优先级和依赖性,服务器能够优先处理
头部压缩,能够下降传输成本,可是有可能会存在安全问题。
支持 重置 ,就是若是要传输一个东西,可是须要传输好几回,而后传输了一半以后,接收方忽然不想要了,这个时候能够发送一个 RST_STREAM 帧来终止。而在 HTTP/1.1 时,则须要断开整个链接。
服务器主动推送,也能够称缓存推送
若是客户端请求一个资源,服务器能够推断出来客户端 请求完此资源后,会再请求的资源,这个时候服务器就能够主动准备好资源而且一并推送给客户端。若是客户端不须要,也能够发送一个RST_STREAM 帧来终止。
流量控制: HTTP/2 能够有本身公示的流量窗口,它能够限制一端发送数据。和 SSH 的工做原理相似。
其中包含了不少信息,其中有 Stream ID SEQ/ACK 等字段
下面这张图来讲明 HTTP/1.1 和 HTTP/2 在性能方面的差异。
文 / blank
编 / 陈皮爽,荧声
做者过往文章:
要点梳理:TCP 链接及常见攻击手法分析(微信公众平台连接)
本文已由做者受权发布,版权属于创宇前端。欢迎注明出处转载本文。本文连接:https://knownsec-fed.com/2018-09-25-guan-yu-http2-de-yan-jiu/
想要订阅更多来自知道创宇开发一线的分享,请搜索关注咱们的微信公众号:创宇前端(KnownsecFED)。欢迎留言讨论,咱们会尽量回复。
感谢您的阅读。