一、HTTP请求的准备
准备工作:
- 浏览器会将域名发送给 DNS 服务器,让它解析为 IP 地址
- HTTP 是基于 TCP 协议的,首先需要建立TCP连接
二、HTTP请求的构建
1. 概述
HTTP请求的组成:请求行、请求的首部、请求的正文实体
2. 请求行
结构:方法 sp URL sp 版本 cr if
方法:
- GET:获取资源
- POST:创建资源
- PUT:更新资源
- DELETE:删除资源
3. 首部字段
结构:key value,通过冒号分隔
例子:
- Accept-Charset:表示客户端可以接受的字符集
- Content-Type:指正文的格式
- Cache-control:用以控制缓存,若客户端发送的请求中包含max-age,则判断资源缓存的时间是否比max-age小,小于max-age则表示客户端可以接受资源,为0时则表示缓存层需要将请求转发给应用集群
- If-Modified-Since:如果服务器缓存没有更新,客户端请求时,返回“304 Not Modified”,客户端不用下载新的请求
三、HTTP 请求的发送
发送流程:
- HTTP基于TCP协议,通过stream二进制流的方式发送给对方,到了TCP层,会将二进制流转换一个个报文段。
- 发送每个报文段后,服务端会返回一个ACK,确保报文可靠到达对方,若超时或失败,则会重传
- TCP每发送一个报文段,都需要加上源地址和目标地址,并将这部分信息交给IP层处理
- IP层查看目标地址与源地址是否在同一局域网,若在同一局域网,则发送ARP协议请求目的地址对应的MAC地址,否则发送到网关,获取网关MAC地址。然后将源/目的MAC地址放入MAC头,发送出去
- 网关发现MAC地址与本地地址相符,获取目的IP地址,根据路由协议获取下一跳地址,将包转发给下一跳路由,直到到达目的服务器的局域网中
- 最后一跳路由器发现目的地址在自己的一个出口局域网中,于是在该局域网中发送ARP,获取目标地址的MAC地址,将包发送出去
- 目标机器发现MAC地址相符,收包,向上传递,发现IP地址相符,再根据IP头的协议项,知道传输层使用TCP协议,解析TCP头,获取序列号,判断序列号是否是请求的,若是则放入缓存,返回ACK,否则丢弃
- 目标机器根据端口号判断监听的进程,进程根据接收到的数据,返回相关信息
三、HTTP返回的构建
组成:状态行、首部、实体
状态行:200:成功;404:服务端无法响应这个请求
首部:
- Retry-After:客户端应该在多长时间以后再次尝试一下。“503 错误”是说“服务暂时不再和这个值配合使用”。
- Content-Type:表示返回的是 HTML,还是 JSON。
返回流程:
- 构造好的HTTP报文,传送到传输层,传输层中TCP将报文切分成一个个小的段,传送给IP层。IP层走之前的发送流程,将报文发送出去
- 客户端发现MAC头与本地MAC地址相符,IP地址相符,就交给TCP层,通过端口确定客户端进程(浏览器)
- 浏览器获取返回的报文,发现是200,则将正文从HTML中提取出来,渲染页面
四、HTTP2.0
HTTP1.0/HTTP1.1缺点:
- HTTP1.1在应用层使用纯文本传输,每次通信都要带完整的 HTTP 的头。
- 一个请求响应完毕后,下一个请求才能发送,如果请求阻塞了,后面的请求都会受影响。(不考虑pipeline);pipeline模式下, 一个请求发送完毕后,无需等待响应,便可发送下一个请求。但是服务端响应的时候只能按照客户端发送请求的顺序进行响应,如果第一个请求处理特别慢,后面的请求即使处理完毕,也要等着,这就是著名的线头阻塞问题。
- HTTP1.0每有一个请求建立一个TCP连接,三次握手耗时,TCP慢启动耗时,HTTP1.0的实时性可见一般。更别提并发性了。 HTTP1.1可以建立TCP长连接复用。实时性相比于HTTP1.0有所提高,但是仍然会出现前一个请求阻塞,后一个请求无法使用TCP连接的情况。
HTTP2.0改进:
- HTTP 2.0 会对 HTTP 的头进行一定的压缩,将原来每次都要携带的大量 key value 在两端建立一个索引表,对相同的头只发送索引表中的索引。
- HTTP 2.0 协议将一个 TCP 的连接中,切分成多个流,每个流都有自己的 ID,而且流可以是客户端发往服务端,也可以是服务端发往客户端。它其实只是一个虚拟的通道。流是有优先级的。
- HTTP 2.0 还将所有的传输信息分割为更小的消息和帧,并对它们采用二进制格式编码。常见的帧有 Header 帧,用于传输 Header 内容,并且会开启一个新的流。再就是 Data 帧,用来传输正文实体。多个 Data 帧属于同一个流。
- 通过两种机制,HTTP 2.0 的客户端可以将多个请求分到不同的流中,然后将请求内容拆成帧,进行二进制传输。这些帧可以打散乱序发送, 然后根据每个帧首部的流标识符重新组装,并且可以根据优先级,决定优先处理哪个流的数据。
- HTTP 2.0 其实是将三个请求变成三个流,将数据分成帧,乱序发送到一个 TCP 连接中。
HTTP2.0相对于HTTP1.x的优点:
HTTP 2.0 成功解决了 HTTP 1.1 的队首阻塞问题,同时,也不需要通过 HTTP 1.x 的 pipeline 机制用多条 TCP 连接来实现并行请求与响应;减少了 TCP 连接数对服务器性能的影响,同时将页面的多个数据 css、js、 jpg 等通过一个数据链接进行传输,能够加快页面组件的传输速度。
五、QUIC协议
HTTP2.0的缺点:TCP 协议在处理包时是有严格顺序的。当其中一个数据包遇到问题,TCP 连接需要等待这个包完成重传之后才能继续进行。
QUIC机制:
1. 自定义连接机制
- 一条TCP连接由源 IP、源端口、目的 IP、目的端口组成,一个元素发生变化时,就需要断开重连,再次进行三次握手。
- QUIC不再使用四元组标识,而是以一个 64 位的随机数作为 ID 来标识,而且 UDP 是无连接的,所以当 IP 或者端口变化的时候,只要 ID 不变,就不需要重新建立连接。
2. 自定义重传机制
- TCP 为了保证可靠性,通过使用序号和应答机制,来解决顺序问题和丢包问题。TCP超时时间是通过采样往返时间 RTT 不断调整的。
- QUIC有序列号和偏移(offset),序列号是递增的,可用于计算RTT;offset表征数据在这个数据流里面的偏移量
3. 无阻塞的多路复用
QUIC可以实现一个连接处理多个stream。由于QUIC基于UDP协议,各个流的帧之间不存在前后依赖,因此stream1的帧出现问题,不会影响stream2的帧的传输
4. 自定义流量控制
- TCP 的流量控制是通过滑动窗口协议。QUIC 的流量控制也是通过 window_update。但是 QUIC 的窗口是适应自己的多路复用机制的,不但在一个连接上控制窗口,还在一个连接中的每个 stream 控制窗口。
- 在 TCP 协议中,接收端的窗口的起始点是下一个要接收并且 ACK 的包,即便后来的包都到了,放在缓存里面,窗口也不能右移,因为 TCP 的 ACK 机制是基于序列号的累计应答,一旦 ACK 了一个序列号,就说明前面的都到了,所以只要前面的没到,后面的到了也不能 ACK,就会导致后面的到了,也有可能超时重传,浪费带宽
- QUIC 的 ACK 是基于 offset 的,每个 offset 的包来了,进了缓存,就可以应答,应答后就不会重发,中间的空档会等待到来或者重发即可,而窗口的起始位置为当前收到的最大 offset,从这个 offset 到当前的 stream 所能容纳的最大缓存,是真正的窗口大小。