【HTTP版本演变】
在浏览器中输入URL并按回车之后会发生什么
1. 输入URL并解析
输入URL后,浏览器会解析出协议、主机、端口、路径等信息,并构造一个HTTP请求(浏览器会根据请求头判断是否又HTTP缓存,并根据是否有缓存决定从服务器获取资源还是使用缓存资源)
2. DNS域名解析,将域名解析成对应的IP地址
DNS是一种用于将域名(www.baidu.com)转换成IP地址(220.181.111.188)的分布式系统。
3. 建立TCP三次握手
4. 浏览器发送HTTP/HTTPS请求到web服务器
5. 服务器处理HTTP请求并返回HTTP报文
服务器会接受请求并将其传递给请求处理程序并发送HTTP响应,一般响应报文包含:请求网页以及状态码,压缩类型,如何缓存的页面,设置cookie;
6. 浏览器渲染页面
7. TCP四次挥手断开连接
HTTP版本演变
HTTP/1.0
是HTTP协议的第一个正式版本,主要有以下特性:
- 引入了请求头和响应头,支持多种请求方法和状态码
- 不支持持久连接,每次请求都需要建立新的连接
HTTP/1.1
- 长连接
为了解决HTTP/1.0每次请求都需要建立新的连接的问题,HTTP/1.1提出了长连接(持久连接),只要客户端和服务器任意一端没有明确提出断开连接,则保持TCP连接状态
2. 管道网络传输
在同一个TCP连接里面,客户端可以发起多个请求,只要第一个请求发出去了,不必等其回来,就可以发送第二个请求,可以减少整体的响应时间。
客户端需要请求两个资源。以前的做法是,在同一个TCP连接里面,先发送A请求,然后等服务器做出回应,收到后再发出B请求。那么,管道机制则是允许浏览器同时发出A请求和B请求。
但是服务器必须按照接受请求的顺序发送对这些管道化请求的响应。
如果服务端在处理A请求时耗时比较长,那么后续的请求的处理都会被阻塞,这称为队头阻塞
HTTP/1.1管道解决了请求的对头阻塞,但没有解决响应的对头阻塞。
3.对头阻塞
当顺序发送的请求序列中的一个请求因为某种原因被阻塞时,在后面排队的所有请求也一同被阻塞了,会招致客户端一值请求不到数据,。
但是HTTP/1.1仍然存在很多问题:
- 头部冗余:每个请求你和响应都需要带有一定的头部信息,每次互相发送相同的头部造成的浪费较多;
- 服务器是按请求的顺序相应的,如果服务器响应慢,会导致客户端一直请求不到数据,也就是队头阻塞;
- 没有请求优先级控制
- 请求只能从客户端开始,服务器只能被动响应
HTTP/2
HTTP/2 协议是基于HTTPS的,所以HTTP/2的安全性也是有保障的
- 头部压缩:HTTP/2使用了HPACK压缩算法对请求头和响应头部进行压缩,减少了传输的头部数据量,降低了延迟
- 二进制帧:HTTP/2将数据分割成二进制帧进行传输,分为头信息帧和数据信息帧,增加了数据传输的效率
- 并发传输:引出Stream概念,多个Stream复用在一条TCP连接,针对不同的HTTP请求用独一无二的Stream ID来区分,接收端可以通过Stream ID 有序组装成HTTP消息,不同Stream的帧可以乱序重发送的,因此可以并发不同的Stream,也就是HTTP/2可以并行交错地发送请求和响应
- 服务器推送:在HTTP/2中,服务器可以对客户端的一个请求发送多个响应,即服务器可以额外的向客户端推送资源,而无需客户端明确的请求
但是HTTP/2仍然存在队头阻塞的问题,只不过在传输层
HTTP/2是基于TCP协议来传输数据的,TCP是字节流协议,TCP层必须保证收到的字节数据是完整且连续的,这样内核才会将缓冲区里的数据返回给HTTP应用,那么【当前1个字节数据】没有到达时,后收到的字节数据只能存放在内核缓冲区中,只有等到者1个字节的数据到达时,HTTP/2应用层才能从内核中拿数据,这就是HTTP/2的队头阻塞问题。
并发实现:
先来理解三个概念:Stream、Messager、frame
从图中可以看出
- 一个TCP连接包含一个或多个Stream,Stream时HTTP/2并发的关键技术
- Stream包含1个或多个Message,Message对应HTTP/1中的请求或响应,由HTTP头部和包体构成
- Message里面包含一条或多条frame,frame时HTTP/2最小单位,以二进制压缩格式存放HTTP/1中的内容
HTTP 消息可以由多个 Frame 构成
一个 Frame 可以由多个 TCP 报文构成
在 HTTP2 连接上,不同 Stream 的帧可以乱序发送(因此可以并发不同的 Stream),接收端可以通过 Stream ID 有序组装 HTTP 消息。
HTTP/2 通过 Stream 实现的并发,比 HTTP/1.1 通过 TCP 连接实现并发要牛逼的多,因为当 HTTP/2 实现 100 个并发 Stream 时,只需要建立一次 TCP 连接,而 HTTP/1.1 需要建立 100 个 TCP 连接,每个 TCP 连接都要经过 TCP 握手、慢启动以及 TLS 握手过程,这些都是很耗时的。
HTTP/2 还可以对每个 Stream 设置不同优先级,帧头中的「标志位」可以设置优先级,比如客户端访问 HTML/CSS 和图片资源时,希望服务器先传递 HTML/CSS,再传图片,那么就可以通过设置 Stream 的优先级来实现,以此提高用户体验。
HTTP/3
HTTP/3 基于 QUIC 协议,具有以下特点:
- 零 RTT 连接建立:QUIC 允许在首次连接时进行零往返时间(Zero Round Trip Time)连接建立,从而减少了连接延迟,加快了页面加载速度。
- 无队头阻塞:QUIC 使用 UDP 协议来传输数据。一个连接上的多个 stream 之间没有依赖,如果一个 stream 丢了一个 UDP 包,不会影响后面的 stream,不存在 TCP 队头阻塞
- 连接迁移:QUIC 允许在网络切换(如从 Wi - Fi 到移动网络)时,将连接迁移到新的 IP 地址,从而减少连接的中断时间。
- 向前纠错机制:每个数据包除了它本身的内容之外,还包括了部分其他数据包的数据,因此少量的丢包可以通过其他包的冗余数据直接组装而无需重传。向前纠错牺牲了每个数据包可以发送数据的上限,但是减少了因为丢包导致的数据重传。