HTTP协议的迭代

97 阅读4分钟

前置知识

  • 浏览器针对同一个域名的网站最大的tcp链接数是根据浏览器规定的
  • 如果在一个tcp通道中如果某个http请求的响应因为某个原因没有及时返回,后面的响应会被阻塞,这就是队头阻塞。通过tcp并发连接解决,但会增大服务器的连接数,给服务器造成压力

HTTP/0.9

在当初,有了传输层的网络协议之后,增加HTTP协议,明确了网络通信下服务端和客户端传输和处理文本的规范(早期用于浏览器传输处理html文件,例如浏览器的请求只有GET/path而已,响应仅包含 HTML,一个 HTTP 请求就传递了一个完整的、自给自足的页面,不会异步请求其他资源)。

  • 只有客户端能下载数据
  • 没有长连接功能,不能复用底层的 TCP 连接,请求结束后会关闭连接,同一域名中有多少个http请求,就需要建立多少次TCP链接
  • 不能压缩数据

HTTP/1.0

  • 添加版本信息(方便客户端和服务端相互识别)、添加扩展 Header(控制行分割)、添加返回状态信息(确认数据接收完成)
  • 有长连接功能,在 Header 中指定 Keep-Alive,服务端就不会主动关闭 TCP 连接
  • 在 Header 中可以指定 Body 部分的数据的压缩类型,而 Header 不能压缩
  • 在 Header 中可以指定传输数据的类型(不仅可以传输HTML了)
  • 新增多种方法,使客户能确定其想要执行操作的类型(例如,引入 POST 是为了允许客户端将数据发送到服务器以处理和存储)
  • 新增状态码,为客户端提供了一种确认服务器已成功处理请求的方法(例如,如果处理失败,则可以用它了解发生了哪种错误)
  • 增加缓存属性,可以读取历史缓存,减少重复请求同一资源带来的浪费
  • 有队头阻塞问题

HTTP/1.1

  • 大名鼎鼎(IETF发布的)
  • 默认开启 TCP 连接复用,不需要指定 Header
  • 失败设计:为了解决同一域名中的多个http请求响应可以共用一个tcp连接通道的问题,提出管道。但管道设计问题很大(请求乱序和幂等/非POST请求),所以大部分浏览器和服务器默认不支持管道化
  • 增加缓存对比用的 Etag Header ,实现断点续传和多连接传输
  • 增加 Host Header ,实现同一个 IP 上搭建不同域名的网站(虚拟网站)
  • 可以切换底层TCP协议,例如换成websocket
  • Header 无法压缩
  • 协议使用文本格式,传输和解析效率都比较低
  • 服务端无法主动给客户发送内容
  • 有队头阻塞问题

HTTP/2

前几代HTTP协议主要针对文本传输,随着流媒体的崛起,视频等二进制数据传输的需求增多,HTTP的传输效率需要进行改进。

  • 小名鼎鼎(Google发布的)
  • Header 和 Body 都可以压缩
  • 推出 stream,不同请求/响应可以共用同一条 TCP 连接。(Header 和 Data 使用独立的 Frame,例如 gRPC 响应,先发一个 Header Frame,告知 HTTP 状态;再发一个 Data Frame,传输 gRPC 消息;最后又发了一个 Header Frame,告知 grpc-status 状态,这是 gRPC 自定义的状态码)
  • 大部分情况下服务端可以主动向客户端推送HTTP/2 不能完全替代 WebSocket 协议,例如在HTTP/2 客户端与服务端建立连接,但随后不发送任何请求的情况下,服务端将无法向客户端推送任何内容,而 WebSocket 协议是唯一可用于从服务端到客户端的完全主动通信的 Web 协议。
  • 底层 TCP 协议带来的丢包全部重传问题(例如发送请求/响应时网络抖动,没有按顺序接收到数据包,超时后放弃所有数据包)
  • 请求/响应重传依然会带来队头阻塞问题