HTTP(超文本传输协议) 是基于 C/S 架构的应用层协议。用于浏览器和服务器之间进行通信。我们从方法和特点的角度,看看 http 从 0.9 到 3.x 的进化史。
HTTP 0.9
方法:GET
特点:
- 版本简单,只有一个 GET 方法,用于向服务器请求 HTML 页面。服务器只能回应 HTML 格式字符串,不能回应别的格式。(缺点:只能显示纯文本)
- 没有状态码(缺点:即使访问的页面不存在,也不会返回任何错误码)
- 不支持头信息(缺点:只支持纯文本)
- 客户端获取到 HTML 之后就会断开连接(缺点:无状态,效率低)
HTTP 1.0
方法:GET , POST , HEAD
特点:
-
支持请求头和响应头(解决HTTP0.9中只显示纯文本问题,可以指定资源类型,支持图像、音频等)
-
可以通过 POST 方法向服务端提交数据
-
无连接,每个请求响应都要建立新的TCP连接(缺点:无法复用连接,效率低,除此之外还存在队头阻塞问题,只有一个请求响应完了,才继续响应后边请求)
-
缓存机制(减轻服务器压力,速度快)
通过Expires,来设置缓存过期时间。Expires会生成绝对时间,比如 "Expires : Wed,14 May 2015 14:30:32 GMT" 表示缓存在2015年5月14日14:30:32 过期,这是我们常说的 强缓存。
对于协商缓存,HTTP 1.0 使用 If-Modified-Since 和 Last-Modified 来控制。
HTTP 1.1
方法:GET , POST , HEAD, OPTIONS , PUT ,DELETE ,TRACE , CONNECT
特点:
-
默认带流水线的持久性连接(解决HTTP1.0中连接无法复用的问题)
HTTP 1.1 提供了一个保持长连接的方式,需要在请求头中添加 “Connection : keep-alive" 来支持持久连接。服务端收到后,会在响应头中添加相同的头信息,表示这是一个持久连接。
客户端通过发送Connection: false,明确要求服务器关闭TCP连接。
-
优化缓存机制
强缓存使用 Cache-Control 缓存头,生成相对时间。协商缓存使用 E-tag,避免因为缓存文件被打开过导致 Last-Modified 被改变的问题。
-
管道连接
客户端依据域名来向服务器建立连接,一般PC端浏览器会针对单个域名的服务器同时建立6
8个连接,手机端一般控制在46个。比如说一个HTML上边有10个img,允许浏览器同时建立6-8个TCP连接,同时请求6-8个img。
允许同时发送多个请求,提高效率。但是服务器时按照请求顺序来进行处理的,服务器处理完前一个才会处理下一个,所以本质上还是存在阻塞问题。
如果上一组为请求结果未返回,也不能发送下一组请求结果。
还拿上边例子来说,如果你想请求余下两个img,需要等前边8个结果返回之后在同时建立两个TCP,发送两个请求
HTTP 2.x
方法:HTTP1.1之后新增PATCH 方法
此方法与PUT方法类似,都用于资源的更新,但是差别在于:
- PATCH主要用于资源的部分更新,而PUT主要用于整体资源的更新
- 当资源不存在时, PATCH 会创建一个新的资源,而PUT只会已在资源进行更新。
特点:
-
通信单位为二进制帧
在应用层和传输层之间增加一个二进制分帧层。在不改动 HTTP/1.x 的语义、方法、状态码、URI 以及首部字段的情况下, 解决了HTTP1.1 的性能限制,改进传输性能,实现低延迟和高吞吐量。在二进制分帧层中,HTTP 2.x 会将所有传输的信息分割为更小的帧(frame),并对它们采用二进制格式的编码,其中 HTTP1.x 的首部信息会被封装到 HEADER frame,而相应的 Request Body 则封装到 DATA frame 里面。
-
数据流模式(无序,编号+ID+(优先权))
HTTP 2 的数据包是不按顺序发送的,同一个连接里面连续的数据包,可能属于不同的回应。
将每个请求或回应的所有数据包,称为一个数据流。每个数据流都有一个独一无二的编号。数据包发送的时候,都必须标记数据流ID,用来区分它属于哪个数据流。客户端发出的数据流,ID一律为奇数,服务器发出的,ID为偶数。
客户端还可以指定数据流的优先级。优先级越高,服务器就会越早回应
-
多路复用
流的概念是为了实现多路复用,在单个连接上实现同时进行多个业务单元数据的传输,多路复用就是利用流来实现会话的串行传输。
在一个连接里,客户端和浏览器都可以同时发送多个请求或回应,而且不用按照顺序一一对应,避免堵塞。
-
首部压缩(节省带宽)
-
服务器推送
服务器可以对客户端的一个请求发送多个响应,比如你请求一个HTML,服务端可以将里边包含的图片等资源发送给你,不必再去请求。另一个好处是可以缓存。
-
支持加密
互联网上通常所能见到的HTTP/2都是使用"https”协议名,跑在TLS上面。HTTP/2协议定义了两个字符串标识符:“h2"表示加密的HTTP/2,“h2c”表示明文的HTTP/2。
HTTP2.0解决了之前版本的很多问题,但是还存在着一些问题,主要是传输层TCP协议引起的:
-
TCP或TCP+TLS建立连接 产生的延时
TCP三次握手需要1.5个RTT(浏览器发出请求到收到响应的时间),如果是HTTPS的话还会建立TLS连接,也存在握手的过程,不同版本的TLS建立连接花费时间不同大致上是1-2个RTT,总体来讲就是3-4个RTT。
-
TCP的队头阻塞并没有彻底解决
HTTP2.0多个请求是跑在一个TCP管道中的。但当出现了丢包时,HTTP/2 的表现反倒不如 HTTP/1 了。因为TCP为了保证可靠传输,存在重传机制,丢失的包必须要等待重新传输确认,HTTP/2出现丢包时,整个 TCP 都要开始等待计时器超时进行重传,那么就会阻塞该TCP连接中的所有请求。而对于 HTTP/1.1 来说,可以开启多个 TCP 连接,出现这种情况反到只会影响其中一个连接,剩余的 TCP 连接还可以正常传输数据。
HTTP 3.x
我们知道HTTP2.0在应用层和传输层之间添加二进制分帧层对数据进行分割编码,提高效率降低延时。而HTTP3.0在HTTP2.0 的基础上,彻底的将传输层协议由 TCP变成了UDP,为确保数据的可靠传输,在二进制分帧层和传输层之间添加QUIC协议。
QUIC协议:
-
实现了类似TCP的流量控制、传输可靠性的功能。
既然UDP是不可靠的,那为保证数据传输的可靠性,QUIC代替UDP去完成了TCP的数据重传、拥塞控制、可靠数据传输等功能。
-
实现了快速握手功能。
QUIC是基于UDP的,所以QUIC可以实现使用0-RTT或者1-RTT来建立连接,这意味着QUIC可以用最快的速度来发送和接收数据,这样可以大大提升首次打开页面的速度。0RTT 建连可以说是 QUIC 相比 HTTP2 最大的性能优势
-
多路复用,不存在队头阻塞问题
QUIC实现了在同一物理连接上可以有多个独立的逻辑数据流
队头阻塞
队头阻塞是指当顺序发送的请求序列中的一个请求因为某种原因被阻塞时,在后面排队的所有请求也一并被阻塞,会导致客户端迟迟收不到数据。
HTTP1.0和HTTP1.1都存在这个问题。在HTTP2.0和3.0中逐步得到解决。
以上总结如有问题,欢迎留言指正。
叮叮叮!!!欢迎关注微信搜索“前端笔迹”或者扫码关注微信公众号,我们共同进步。