HTTP请求
介绍 HTTP 之前,我们需要了解一些前置知识。
IP 协议(Internet Protocol)
IP 协议是 TCP/IP 协议族中的核心协议,它定义了计算机之间如何通信以及数据如何在网络中传输。IP 协议负责将数据从源地址传送到目的地址。
IP 协议的主要功能有:
- 寻址:IP 协议采用 32 位地址,每个 IP 地址都对应唯一的网络设备。
- 路由:IP 协议使用路由表来决定数据包的路径。
- 转发:当数据包到达目的地址时,IP 协议会检查目的地址是否在本地网络,如果在本地网络,则直接传送,否则需要通过路由表来选择下一跳路由器,并将数据包传送到下一跳路由器。
- 分片:当数据包的长度超过网络传输的最大包长时,IP 协议会将数据包分割成多个小包,并通过 IP 头部的分片字段来标识。
- 错误检测:IP 协议提供检错机制,检测数据包是否被篡改。
TCP 协议(Transmission Control Protocol)
TCP 协议是一种面向连接的、可靠的、基于字节流的传输层协议。它负责建立连接、数据传输、保证数据完整性、保证数据顺序、处理丢包重传等。
TCP 协议的主要功能有:
- 建立连接:TCP 协议采用三次握手建立连接,即客户端发送 SYN 报文,服务器收到后返回 SYN/ACK 报文,客户端再次发送 ACK 报文,连接建立。
- 数据传输:TCP 协议采用可靠的字节流传输,即 TCP 协议会将数据分割成 TCP 包,并通过序号和确认号来保证数据传输的完整性。
- 保证数据顺序:TCP 协议保证数据包按顺序到达目的地址。
DNS 协议(Domain Name System)
DNS 协议是用于域名解析的协议,它将域名转换成 IP 地址。
DNS 协议的主要功能有:
- 域名解析:DNS 协议将域名转换成 IP 地址,使得用户可以方便地访问互联网资源。
- 负载均衡:DNS 协议可以将域名请求转发到多个服务器,实现负载均衡。
DNS 的优先级:
- 本地 DNS 服务器:如果本地 DNS 服务器中有域名的解析记录,则直接返回解析结果。
- 主 DNS 服务器:如果本地 DNS 服务器中没有域名的解析记录,则向主 DNS 服务器请求解析结果。
- 缓存 DNS 服务器:如果主 DNS 服务器也没有域名的解析记录,则向缓存 DNS 服务器请求解析结果。
- 根 DNS 服务器:如果缓存 DNS 服务器也没有域名的解析记录,则向根 DNS 服务器请求解析结果。
前置知识介绍完毕,下面我们来看一下 HTTP 协议。
HTTP 协议(Hypertext Transfer Protocol)
HTTP 协议是用于从 Web 服务器传输超文本到本地浏览器的协议。它是一个基于请求-响应模型的协议,由请求消息和响应消息构成。
HTTP 协议的主要功能有:
- 客户机-服务器模型:HTTP 协议是客户机-服务器模型的基础协议。
- 无状态:HTTP 协议是无状态协议,即服务器不会保存关于客户的任何信息。
HTTP 请求分为三大部分:
- 请求行:包括方法、URL、HTTP 版本。
GET baidu.com/index.html HTTP/1.1
- 请求头
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/58.0.3029.110 Safari/537.36
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8
Accept-Encoding: gzip, deflate, sdch, br
Accept-Language: zh-CN,zh;q=0.8
- 请求体
search=hello
响应也是差不多的格式,但是响应头会包含状态码、服务器信息等。
HTTP/1.1 200 OK
Server: nginx/1.10.1
那么发起 HTTP 后,只有一个域名是怎么知道目标服务器的地址呢,这就要用到上述的 IP 协议了。
但是 IP 是数字,如何把域名转换成 IP 呢?这就要用到 DNS 了, DNS 协议将域名转换成 IP 地址,使得用户可以方便地访问目标服务器。
HTTP 协议的请求流程:
- 客户端向 DNS 服务器请求域名对应的 IP 地址。
- DNS 服务器解析域名,返回 IP 地址和端口号。
- 客户端向目标服务器发起 TCP 三次握手建立连接。
- 客户端和服务器传输数据。
- 四次挥手断开 TCP 连接。
在 HTTP/1.1 及更高版本中,可以通过 Keep-Alive 复用连接,减少 TCP 连接的建立和断开。
HTTP2
在 HTTP 1.1 中,虽然支持 Keep-Alive 复用 TCP,但是每个域名有 6 个 TCP 的限制,所以并发需要比较多的 hack 操作,比如申请多个不同的域名以支持开启更多的 TCP 链接,然后通过服务端的反向代理这些域名到真正的服务器;之后 HTTP2 解决了 HTTP1 的单个 TCP 只能同时处理一个HTTP 请求的问题,HTTP2 使用二进制帧的概念,多个 Frame 组合成 Stream,Stream是TCP上的逻辑传输单元,能做到一个 TCP 多路复用,减少 TCP 的连接,并且支持头部压缩,相比之下做了不小的优化。
但是 HTTP2 也有 TCP 的致命缺点,假设第一个 Stream 上丢失了 Frame,后面 N 个 Stream 即使到达了服务器,也是不能被处理的,TCP 需要等待前面发出的包有回应才能处理后序的包,所以这个是 TCP 本身的头部阻塞问题,没有办法根本解决,并且在弱网环境下,HTTP2 性能比 HTTP1 还要低。
移动时代,如果用户的 IP 时刻变化,就需要频繁的进行 TCP 连接和反复握手。
HTTP3
我们先来了解一下 TCP 的拥塞控制:
- 慢启动: 发送方像接收方发送一个单位的数据, 收到确认后发送2个单位, 然后是4个, 8个依次指数增长, 这个过程中不断试探网络的拥塞程度.
- 避免拥塞: 指数增长到某个限制之后, 指数增长变为线性增长。
- 快速重传: 发送方每一次发送都会设置一个超时计时器, 超时后认为丢失, 需要重发。
- 快速恢复: 在上面快速重传的基础上, 发送方重新发送数据时, 也会启动一个超时定时器, 如果收到确认消息则进入拥塞避免阶段, 如果仍然超时, 则回到慢启动阶段。
HTTP3 做了相当多的根本升级:
- 放弃了 TCP,使用自己内部开发的 QUIC 协议,底层是 UDP
- QIUCK通过递增的 Packet Number,精准计算 RTT(Round Trip Time)
- QUIC 不需要像 TCP 那样,每个三个数据包就要返回ACK,QUIC 最多可以带 256 个 ACK Block,减少数据包重传问题
- 通过 connectId 来保持连接,即使用户切换了 IP,也能继续复用连接