Skip to content

HTTP版本差异

HTTP 1.0

1.0的HTTP是一个无连接、无状态的应用层协议。因此客户端每次请求服务器都需要建立一个TCP链接,服务器处理完TCP立即断开(无连接),服务器也不会记录每次的请求(无状态)。

无状态可以使用CookieSession来实现身份认证与状态记录(状态化)。

问题:

  • 无法实现连接复用

​ 每次发送请求后,都需要进行一次TCP连接,TCP的连接与释放过程消耗很多资源,这种无连接特性会导致网络复用率变低。

  • 队头阻塞

​ 由于HTTP 1.0规定下一个请求必须在前一个请求响应到达之前才能发送,假设前一个请求响应一直不到达,那么下一个请求将一直阻塞。

HTTP 1.1

长连接

HTTP 1.1解决了连接复用的问题。HTTP 1.1增加了Connection字段,通过设置Keep-Alive使得HTTP连接能够连接不断,避免客户端与服务器多次建立与释放TCP连接,提高了网络的复用率。

当客户端需要关闭连接的时候,可以在请求头的Connection设为false告知服务器关闭。

管道化

基于长连接实现,客户端能够发送多个请求,但是服务器必须按照请求的顺序依次回应相应的结果,即:让队列从客户端的请求队列迁移到了服务器的响应队列,但是仍然没有解决队头阻塞的问题。

HTTP 2.0

二进制分帧

HTTP 2.0通过在应用层与传输层之间增加了一个二进制分帧层,突破了HTTP 1.0的性能限制,改进了传输性能。

多路复用

  • :已建立连接上的双向自己流。
  • 消息:与逻辑消息对应的完整的一系列数据帧。
  • 帧(frame):HTTP 2.0通信的最小单位,每个帧包含头部,至少也会标识出当前所属的流(stream_id)

每个数据流以消息的形式发送,而消息由一个或者多个帧组成。帧可以乱序发送,然后依赖流标识符重新封装。

并且HTTP 2.0的数据流可以设置优先级依赖

头部压缩

在HTTP 1.X中,头部源数据都是以纯文本的形式发送的,会给每个请求头增加较多字节的负荷(Cookie),HTTP 2.0要求客户端与服务器都缓存一张Header_Files表,将Header进行编码压缩,避免了重复Header的传输,减小了传输的负荷。

服务器推送

即客户端发送一次请求,服务器会主动将所需要的资源一次性推送给客户端。eg: 客户端请求一个index.html资源,服务器将在一次请求内将所有所需的index.css, index.js等资源返回给客户。

这里的问题在于当用户误触到某个链接的时候,由于服务器推送机制,用户会一次性获取非常多不必要的资源,这种可能会造成DDoS攻击的实现。

HTTP 3.0

HTTP 2.0成功解决了头部阻塞的问题,但是这里解决的只是应用层的头部阻塞,在传输层的TCP中,出现丢包的情况整个TCP都要等待重传,即传输层的头部阻塞并没有被解决,而修改TCP协议是不可能的(TCP协议由操作系统负责)。

整合

HTTP 2.0默认使用TLS加密,那么除了TCP握手外,还需要建立TLS握手,这样需要消耗非常多的资源(即使TLS 1.3较TLS 1.2已做了优化)。在HTTP 3.0中,TCP握手与TLS握手整合到了一起。即0-RTT连接。

QUIC + UDP

QUIC基于UDP,一个连接上的多个流没有依赖,即使丢包只需要重新发送丢失的包即可,不需要重传整个连接,实现了多路复用

QUIC的帧中包含了Connection_Id字段,QUIC是通过该段识别连接的,而TCP是基于IP识别连接的,那么当网络环境变化的时候,Connection_Id并不会改变,能够迅速实现重连,能够提供更好的移动端表现

QUIC除了部分报文外,报文头部与报文BODY都经过加密,有效降低了安全风险

向前纠错,每个数据包除了它本身的内容之外还包括了其他数据包的数据,因此少量的丢包可以通过其他包的冗余数据直接组装而无需重传。

Released under the MIT License.