HTTP协议1.0、1.1、2.0协议特性及区别

168 阅读6分钟

HTTP/1.0

  • 无状态:服务器不跟踪不记录请求过的状态
  • 无连接:浏览器每次请求都需要建立tcp连接

浏览器的每次请求都需要与服务器建立一个TCP连接,服务器处理完成后立马断开TCP连接(无连接),服务器不跟踪每个客户端也不记录过去的请求(无状态),这种无状态性可以借助cookie/session机制来做身份认证和状态记录。

无连接导致缺点

  1. 无法复用连接,每次发送请求都需要进行一次TCP连接释放,这导致网络利用率低
  2. 队头阻塞。由于HTTP/1.0规定下一个请求在前一个响应到达前不能发送,假设前一个请求响应一直不到达,那么下一个请求就不发送,导致阻塞后面的请求

HTTP/1.1

  1. 在缓存方面,http1.0只能使用expiresif-modified-since来进行缓存判断,http1.1则增加了cache-controle-tagif-none-match等更多缓存头来控制缓存
  2. 优化了带宽利用,http1.0客户端可能只需要某个对象的一部分,而服务端则将整个对象送过来了,到了http1.1,请求头引入了range头域,它允许只请求资源的某个部分,即返回码是206。
  3. 错误通知的管理,http1.1中新增了24个错误状态响应码,如409(Conflict)表示请求的资源与资源的当前状态发生冲突;410(Gone)表示服务器上的某个资源被永久性的删除。
  4. Host头处理,在HTTP1.0中认为每台服务器都绑定一个唯一的IP地址,因此,请求消息中的URL并没有传递主机名(hostname)。但随着虚拟主机技术的发展,在一台物理服务器上可以存在多个虚拟主机(Multi-homed Web Servers),并且它们共享一个IP地址。HTTP1.1的请求消息和响应消息都应支持Host头域,且请求消息中如果没有Host头域会报告一个错误(400 Bad Request)。
  5. 长连接,http1.1中默认开启Connection:keep-alive,可以在同一条tcp连接上进行多个请求和响应,减少了每次请求都建立和关闭连接的消耗和延迟

HTTP/2.0

前面说到的http1.1还是有些缺点:

  1. 队头阻塞:tcp上发的请求得等前一个请求响应返回了,下一个请求才能发出去,后续的请求都得排队等候,虽然http1.1管线化可以支持请求并发,这个请求并发确实依赖于创建多个tcp连接,成本很高,浏览器很难实现

  2. HTTP/1.X版本是采用文本格式,首部未压缩,http1.1的header带有大量信息,每次都要重复发送

二进制分帧层

HTTP2性能提升的核心就在于二进制分帧层。HTTP2是二进制协议,他采用二进制格式传输数据而不是1.x的文本格式。

image-20220519225226448

1.1响应是文本格式,而2.0把响应划分成了两个帧,图中的HEADERS(首部)和DATA(消息负载) 是帧的类型。也就是说一条HTTP响应,划分成了两个帧来传输,并且采用二进制来编码。

这里我们来提三个概念。

  • 流(Stream):已建立的TCP连接上的双向字节流,可以承载一个或多个消息。
  • 消息(Message):一个完整的HTTP请求或响应,由一个或多个帧组成。特定消息的帧在同一个流上发送,这意味着一个HTTP请求或响应只能在一个流上发送。
  • 帧(Frame):通信的基本单位。

一个TCP连接上可以有任意数量的流。

多路复用

上面提到HTTP/1.1的线头阻塞和多个TCP连接的问题,HTTP2的多路复用完美解决。多路复用是这样实现多路复用的:http2.0创建一个tcp连接,一个连接上面可以有任意多个流,消息分割成一个或多个帧在流里面,帧传输过去后再进行重组,形成一个完整的请求或响应。但是还是会有请求排队的情况,因为服务器的处理请求的能力不是无止境的,流控制会管理数据的传输,当请求太多时,它会减少或停止请求的发送,免得接收方不堪重负

头部压缩

在1.X版本中,首部用文本格式传输,通常会给每个传输增加500-800字节的开销,现在一个网站上百个请求已经是常态了,每个请求的头部的一些字段都是相同的,例如cookie,user-agent等,所以http2.0会用HPACK压缩格式来压缩头部,头部压缩需要在浏览器和服务器端之间:

  • 维护一份相同的静态字典,包含常见的头部名称,以及常见的头部名称和值的组合
  • 维护一份相同的动态字典,可以动态的添加内容
  • 通过静态Huffman编码对传输的首部字段进行编码

image-20220519232128631

所以我们在传输首部字段的时候,例如要传输method:GET,那我们只需要传输静态字典里面method:GET对应的索引值就可以了,一个字节搞定。

像user-agent、cookie这种静态字典里面只有首部名称而没有值的首部,第一次传输需要user-agent在静态字典中的索引以及他的值,值会采用静态Huffman编码来减小体积。第一次传输过user-agent 之后呢,浏览器和服务器端就会把它添加到自己的动态字典中。后续传输就可以传输索引了,一个字节搞定。

服务器端推送

服务器端推送使得服务器可以预测客户端需要的资源,主动推送到客户端。

例如:客户端请求index.html,服务器端能够额外推送script.js和style.css。 实现原理就是客户端发出页面请求时,服务器端能够分析这个页面所依赖的其他资源,主动推送到客户端的缓存,当客户端收到原始网页的请求时,它需要的资源已经位于缓存。


总结

HTTP 1.0

  • 无状态
  • 无连接

HTTP 1.1

  • 长连接
  • 增加缓存处理(cache-control,e-tag,If-none-match等)
  • 增加host头域
  • 增加range头域,支持断点重传,不用一整个对象返回,只返回需要的部分,返回206
  • 新增错误响应状态码

HTTP 2.0

  • 二进制分帧
  • 多路复用
  • 头部压缩
  • 服务器端推送

参考

面试官问:你了解HTTP2.0吗?

HTTP1.0、HTTP1.1 和 HTTP2.0 的区别

HTTP1.0 HTTP1.1 HTTP2.0 主要特性对比