HTTP1.0、HTTP1.1、HTTP2.0 和 HTTP3.0
作者:Seiya
时间:2019年09月01日
前言
早在 HTTP 建立之初,主要就是为了将超文本标记语言(HTML)文档从Web服务器传送到客户端的浏览器。也是说对于前端来说,我们所写的 HTML 页面将要放在我们的 web 服务器上,用户端通过浏览器访问 url 地址来获取网页的显示内容。
但是到了 WEB2.0 以来,我们的页面变得复杂,不仅仅单纯的是一些简单的文字和图片,同时我们的 HTML 页面有了 CSS,Javascript,来丰富我们的页面展示,当 ajax 的出现,我们又多了一种向服务器端获取数据的方法,这些其实都是基于 HTTP 协议的。
同样到了移动互联网时代,我们页面可以跑在手机端浏览器里面,但是和 PC 相比,手机端的网络情况更加复杂,这使得我们开始了不得不对 HTTP 进行深入理解并不断优化过程中。
HTTP 基本优化
影响一个 HTTP 网络请求的因素主要有两个:带宽和延迟。
带宽
如果说我们还停留在拨号上网的阶段,带宽可能会成为一个比较严重影响请求的问题,但是现在网络基础建设已经使得带宽得到极大的提升,我们不再会担心由带宽而影响网速;
延迟
浏览器阻塞(HOL blocking)
浏览器会因为一些原因阻塞请求。浏览器对于同一个域名,同时只能有 4 个连接(这个根据浏览器内核不同可能会有所差异),超过浏览器最大连接数限制,后续请求就会被阻塞。
DNS 查询(DNS Lookup)
浏览器需要知道目标服务器的 IP 才能建立连接。将域名解析为 IP 的这个系统就是 DNS。这个通常可以利用 DNS 缓存结果来达到减少这个时间的目的。
建立连接(Initial connection)
HTTP 是基于 TCP 协议的,浏览器最快也要在第三次握手时才能捎带 HTTP 请求报文,达到真正的建立连接,但是这些连接无法复用会导致每次请求都经历三次握手和慢启动。三次握手在高延迟的场景下影响较明显,慢启动则对文件类大请求影响较大。
HTTP/1.0 和 HTTP/1.1
HTTP/1.0 最早在网页中使用是在 1996 年,那个时候只是使用一些较为简单的网页上和网络请求上,这是第一个在通讯中指定版本号的 HTTP 协议版本,至今仍被广泛采用,特别是在代理服务器中。
而 HTTP/1.1 则在 1999 年才开始广泛应用于现在的各大浏览器网络请求中,同时 HTTP/1.1 也是当前使用最为广泛的 HTTP 协议。
HTTP/1.0 和 HTTP/1.1 的主要区别
缓存处理
在 HTTP1.0 中主要使用 header 里的 If-Modified-Since,Expires 来做为缓存判断的标准,HTTP1.1 则引入了更多的缓存控制策略例如 Entity tag,If-Unmodified-Since, If-Match, If-None-Match 等更多可供选择的缓存头来控制缓存策略。
带宽优化及网络连接的使用
HTTP/1.0 中,存在一些浪费带宽的现象,例如客户端只是需要某个对象的一部分,而服务器却将整个对象送过来了,并且不支持断点续传功能,HTTP/1.1 则在请求头引入了 range 头域,它允许只请求资源的某个部分,即返回码是 206(Partial Content),这样就方便了开发者自由的选择以便于充分利用带宽和连接。
错误通知的管理
在 HTTP/1.1 中新增了 24 个错误状态响应码,如 409(Conflict)表示请求的资源与资源的当前状态发生冲突;410(Gone)表示服务器上的某个资源被永久性的删除。
Host 头处理
在 HTTP/1.0 中认为每台服务器都绑定一个唯一的 IP 地址,因此,请求消息中的 URL 并没有传递主机名(hostname)。但随着虚拟主机技术的发展,在一台物理服务器上可以存在多个虚拟主机(Multi-homed Web Servers),并且它们共享一个 IP 地址。
HTTP/1.1 的请求消息和响应消息都应支持 Host 头域,且请求消息中如果没有 Host 头域会报告一个错误(400 Bad Request)。
长连接
HTTP/1.1 支持长连接(PersistentConnection)和请求的流水线(Pipelining)处理,在一个 TCP 连接上可以传送多个 HTTP 请求和响应,减少了建立和关闭连接的消耗和延迟,在 HTT/P1.1 中默认开启 Connection: keep-alive,一定程度上弥补了 HTTP/1.0 每次请求都要创建连接的缺点。
HTTP/1.0 和 HTTP/1.1 现存的问题
HTTP1.x 在传输数据时,每次都需要重新建立连接,无疑增加了大量的延迟时间,特别是在移动端更为突出。
HTTP1.x 在传输数据时,所有传输的内容都是明文,客户端和服务器端都无法验证对方的身份,这在一定程度上无法保证数据的安全性。
HTTP1.x 在使用时,header 里携带的内容过大,在一定程度上增加了传输的成本,并且每次请求 header 基本不怎么变化,尤其在移动端增加用户流量。
虽然 HTTP1.x 支持了 keep-alive,来弥补多次创建连接产生的延迟,但是 keep-alive 使用多了同样会给服务端带来大量的性能压力,并且对于单个文件被不断请求的服务 (例如图片存放网站),keep-alive 可能会极大的影响性能,因为它在文件被请求之后还保持了不必要的连接很长时间。
HTTP 与 HTTPS
为了 HTTP/1.0 和 HTTP/1.1 存在的问题,网景在 1994 年创建了 HTTPS,并应用在网景导航者浏览器中。
最初,HTTPS 是与 SSL 一起使用的;在 SSL 逐渐演变到 TLS 时(其实两个是一个东西,只是名字不同而已),最新的 HTTPS 也由在 2000 年五月公布的 RFC 2818 正式确定下来。
简单来说,HTTPS 就是安全版的 HTTP,并且由于当今时代对安全性要求更高,chrome 和 firefox 都大力支持网站使用 HTTPS,苹果也在 ios 10 系统中强制 app 使用 HTTPS 来传输数据。
HTTPS 与 HTTP 的一些区别
HTTPS协议需要到CA申请证书,一般免费证书很少,需要交费。
HTTP协议运行在 TCP 之上,所有传输的内容都是明文,HTTPS 运行在 SSL/TLS之上,SSL/TLS运行在TCP之上,所有传输的内容都经过加密的。
HTTP 和 HTTPS 使用的是完全不同的连接方式,用的端口也不一样,前者是80,后者是443。
HTTPS 可以有效的防止运营商劫持,解决了防劫持的一个大问题。
HTTPS 改造
如果一个网站要全站由 HTTP 替换成 HTTPS,可能需要关注以下几点:
安装 CA 证书,一般的证书都是需要收费的,这边推荐一个比较好的购买证书网站:1)Let's Encrypt,免费,快捷,支持多域名(不是通配符),三条命令即时签署+导出证书。缺点是暂时只有三个月有效期,到期需续签。2Comodo PositiveSSL,收费,但是比较稳定。
在购买证书之后,在证书提供的网站上配置自己的域名,将证书下载下来之后,配置自己的 web 服务器,同时进行代码改造。
HTTPS 降低用户访问速度。SSL 握手,HTTPS 对速度会有一定程度的降低,但是只要经过合理优化和部署,HTTPS 对速度的影响完全可以接受。在很多场景下,HTTPS 速度完全不逊于 HTTP,如果使用
SPDY
,HTTPS 的速度甚至还要比 HTTP 快。相对于 HTTPS 降低访问速度,其实更需要关心的是服务器端的 CPU 压力,HTTPS 中大量的密钥算法计算,会消耗大量的 CPU 资源,只有足够的优化,HTTPS 的机器成本才不会明显增加。
SPDY
SPDY 是 Google 开发的基于 TCP 的会话层协议,用以最小化网络延迟,提升网络速度,优化用户的网络使用体验。SPDY 并不是一种用于替代 HTTP 的协议,而是对 HTTP 协议的增强。 新协议的功能包括数据流的多路复用、请求优先级以及 HTTP 报头压缩。
SPDY 可以说是综合了 HTTPS 和 HTTP 两者有点于一体的传输协议,主要解决:
降低延迟
针对 HTTP 高延迟的问题,SPDY 优雅的采取了多路复用(multiplexing)。多路复用通过多个请求 stream 共享一个 tcp 连接的方式,解决了 HOL blocking 的问题,降低了延迟同时提高了带宽的利用率。
请求优先级
多路复用带来一个新的问题是,在连接共享的基础之上有可能会导致关键请求被阻塞。SPDY 允许给每个 request 设置优先级,这样重要的请求就会优先得到响应。比如浏览器加载首页,首页的 html 内容应该优先展示,之后才是各种静态资源文件,脚本文件等加载,这样可以保证用户能第一时间看到网页内容。
header 压缩
前面提到 HTTP1.x 的 header 很多时候都是重复多余的。选择合适的压缩算法可以减小包的大小和数量。
基于 HTTPS 的加密协议传输
基于 HTTPS 的加密协议传输,大大提高了传输数据的可靠性。
服务端推送
采用了 SPDY 的网页,例如我的网页有一个 sytle.css 的请求,在客户端收到 sytle.css 数据的同时,服务端会将 sytle.js 的文件推送给客户端,当客户端再次尝试获取 sytle.js 时就可以直接从缓存中获取到,不用再发请求了。
tips
SPDY 位于 HTTP 之下,TCP 和 SSL 之上,这样可以轻松兼容老版本的 HTTP 协议 (将 HTTP1.x 的内容封装成一种新的 frame 格式),同时可以使用已有的 SSL 功能。
HTTP/2.0
HTTP/2 是 HTTP 协议自 1999 年 HTTP/1.1 发布后的首个更新,主要基于 SPDY 协议,可以说是 SPDY 的升级版(其实原本也是基于 SPDY 设计的),但是,HTTP/2.0 跟 SPDY 仍有不同的地方,主要是以下两点:
HTTP/2.0 支持明文 HTTP 传输,而 SPDY 强制使用 HTTPS;
HTTP/2.0 消息头的压缩算法采用
HPACK
,而非 SPDY 采用的DEFLATE
;
HTTP/2.0 的新特性
新的二进制格式
HTTP/2 中所有加强性能的核心点在于此。HTTP/1.x 的解析是基于文本。基于文本协议的格式解析存在天然缺陷,文本的表现形式有多样性,要做到健壮性考虑的场景必然很多,二进制则不同,只认 0 和 1 的组合。基于这种考虑 HTTP/2.0 的协议解析决定采用二进制格式,实现方便且健壮。
多路复用
在 HTTP/2 中,有两个非常重要的概念,分别是帧(frame)和流(stream)。帧代表着最小的数据单位,每个帧会标识出该帧属于哪个流,流也就是多个帧组成的数据流。
多路复用,就是在一个 TCP 连接中可以存在多条流。换句话说,也就是可以发送多个请求,对端可以通过帧中的标识知道属于哪个请求。通过这个技术,可以避免 HTTP 旧版本中的队头阻塞问题,极大的提高传输性能。
header 压缩
在 HTTP/1 中,我们使用文本的形式传输 header,在 header 携带 cookie 的情况下,可能每次都需要重复传输几百到几千的字节。
在 HTTP /2 中,使用了 HPACK 压缩格式对传输的 header 进行编码,减少了 header 的大小。并在两端维护了索引表,用于记录出现过的 header ,后面在传输过程中就可以传输已经记录过的 header 的键名,对端收到数据后就可以通过键名找到对应的值。
服务端 Push
在 HTTP/2 中,服务端可以在客户端某个请求后,主动推送其他资源。
可以想象以下情况,某些资源客户端是一定会请求的,这时就可以采取服务端 push 的技术,提前给客户端推送必要的资源,这样就可以相对减少一点延迟时间。当然在浏览器兼容的情况下你也可以使用 prefetch 。
HTTP/2.0 的升级改造
HTTP/2.0 其实可以支持非 HTTPS 的,但是现在主流的浏览器像 chrome,firefox 表示还是只支持基于 TLS 部署的 HTTP/2.0 协议,所以要想升级成 HTTP/2.0 还是先升级 HTTPS 为好。
当你的网站已经升级 HTTPS 之后,那么升级 HTTP/2.0 就简单很多,如果你使用 NGINX,只要在配置文件中启动相应的协议就可以了。
使用了 HTTP/2.0 那么,原本的 HTTP/1.x 怎么办,这个问题其实不用担心,HTTP/2.0 完全兼容 HTTP/1.x 的语义,对于不支持 HTTP/2.0 的浏览器,NGINX 会自动向下兼容的。
HTTP/3.0
虽然 HTTP/2 解决了很多之前旧版本的问题,但是它还是存在一个巨大的问题,虽然这个问题并不是它本身造成的,而是底层支撑的 TCP 协议的问题。因为 HTTP/2 使用了多路复用,一般来说同一域名下只需要使用一个 TCP 连接。当这个连接中出现了丢包的情况,那就会导致 HTTP/2 的表现情况反倒不如 HTTP/1 了。
因为在出现丢包的情况下,整个 TCP 都要开始等待重传,也就导致了后面的所有数据都被阻塞了。但是对于 HTTP/1 来说,可以开启多个 TCP 连接,出现这种情况反到只会影响其中一个连接,剩余的 TCP 连接还可以正常传输数据。
QUIC
基于这个原因,Google 就更起炉灶搞了一个基于 UDP 协议的 QUIC 协议,并且使用在了 HTTP/3 上,当然 HTTP/3 之前名为 HTTP-over-QUIC,从这个名字中我们也可以发现,HTTP/3 最大的改造就是使用了 QUIC。
QUIC 在 UDP 的基础上新增了很多功能,比如多路复用、0-RTT、使用 TLS1.3 加密、流量控制、有序交付、重传等等功能。
多路复用
虽然 HTTP/2 支持了多路复用,但是 TCP 协议终究是没有这个功能的。QUIC 原生就实现了这个功能,并且传输的单个数据流可以保证有序交付且不会影响其他的数据流,这样的技术就解决了之前 TCP 存在的问题。
并且 QUIC 在移动端的表现也会比 TCP 好。因为 TCP 是基于 IP 和端口去识别连接的,这种方式在多变的移动端网络环境下是很脆弱的。但是 QUIC 是通过 ID 的方式去识别一个连接,不管你网络环境如何变化,只要 ID 不变,就能迅速重连上。
0-RTT
通过使用类似 TCP 快速打开的技术,缓存当前会话的上下文,在下次恢复会话的时候,只需要将之前的缓存传递给服务端验证通过就可以进行传输了。
纠错机制
假如说这次我要发送三个包,那么协议会算出这三个包的异或值并单独发出一个校验包,也就是总共发出了四个包。当出现其中的非校验包丢包的情况时,可以通过另外三个包计算出丢失的数据包的内容。当然这种技术只能使用在丢失一个包的情况下,如果出现丢失多个包就不能使用纠错机制了,只能使用重传的方式了。
总结
HTTP/2 通过多路复用、二进制流、Header 压缩等等技术,极大地提高了性能,但是还是存在着问题的;
QUIC 基于 UDP 实现,是 HTTP/3 中的底层支撑协议,该协议基于 UDP,又取了 TCP 中的精华,实现了即快又可靠的协议;