http 各个版本差异

1,518 阅读8分钟

HTTP 0.9

日期:1991 
  1. 只支持GET请求方式
  2. 服务器只返回html字符串信息,不包含头信息
  3. 服务器返回后就断开tcp连接
  4. 只有一个请求行,并没有HTTP 请求头和请求体
  5. 是返回的文件内容是以 ASCII 字符流来传输的 世界上第一个网站info.cern.ch

HTTP 1.0

日期:1996
  1. 引入了请求头和响应头
  2. 支持GET,POST,HEAD请求方式
  3. 新增了请求的字段 文件类型,压缩,编码格式,使用语言(多字符集)
accept: text/html  
accept-encoding: gzip, deflate, br  
accept-Charset: ISO-8859-1,utf-8  
accept-language: zh-CN,zh
  1. 新增了服务端响应字段
content-encoding: br  
content-type: text/html; charset=UTF-8
  1. Content-Type支持的返回类型 支持图片,视频,二进制文件
    text/plain
    text/html
    text/css
    image/jpeg
    image/png
    image/svg+xml
    audio/mp4
    video/mp4
    application/javascript
    application/pdf
    application/zip
    application/atom+xml
  1. 多部分对象集合(Multipart) 如文件上传 Content-Type: multipart/form-data ,HTTP 协议中使用了多部分对象集合,发送的一份报文主体内可含有多类型实体
  2. 缓存Expires
  3. 新增状态码
  4. 可以使用Connection:keep-alive 实现请求后,tcp不断开,但是不是标准,并不是每个浏览器都支持。
  5. 新增http header信息来描述元数据。
  6. 增加了用户代理UserAgent获取客户端的基础信息
  7. 权限

缺陷:

  • 无状态: 服务器不跟踪不记录请求过的状态: 可以借助 cookie/session 机制做身份认证和状态记录
  • 无连接:无法复用连接, 每次都需要进行三次握手, 四次挥手, 浪费网络资源
  • 队头阻塞: HTTP1.0 规定, 在前一个响应完成后, 下一次请求才能发出, 如果前一个阻塞, 后面的请求也阻塞了

HTTP 1.1

日期:1999 当前-主流
  1. 在原有的基础上新增了许多请求方法:PUT、PATCH、HEAD、 OPTIONS、DELETE。
  2. 官方默认就支持Persistent Connection(持久连接), Connection: keep-alive,不用特意声明。 客户端和服务器发现对方一段时间没有活动,服务端会有keepAliveTimeout超时时间(nginx 60秒),主动发起关闭连接。或者连接数maxKeepAliveRequests 超过指定请求,也会主动发起关闭连接。 当然客户端也可以主动发送 Connection: close,明确要求服务器关闭 TCP 连接。
  3. 尚未成熟的HTTP 管线化 :传统tcp一次只能发送一个请求A,等请求A结束后才能重新发起请求B。但是在管道机制中,一个tcp可以发起多个请求,不过服务端还是会按顺序返回A和B的内容。由于同时进行,就需要区分数据包。使用Content-length区分,由于服务端还是按顺序响应,所以效果不明显。
  4. 客户端请求的头信息新增了 Host 字段,用来指定服务器的域名。由于在一台物理服务器上可以存在多个虚拟主机,并且它们共享一个IP地址,就需要通过Host区分
  5. 支持文件断点续传,RANGE:bytes,用于分片下载
  6. 支持只发送header信息,并且加入了一个新的状态码100。客户端事先发送一个只带头域的请求,如果服务器因为权限拒绝了请求,就回送响应码401(Unauthorized);如果服务器接收此请求就回送响应码100,客户端就可以继续发送带实体的完整请求了。
  7. 新的缓存策略Cache-Control
  8. 对动态内容的支持Transfer-Encoding
  9. 客户端 Cookie和安全机制

Transfer-Encoding

由于 Content-Length 字段必须真实反映实体长度,但实际应用中,有些时候实体长度并没那么好获得,例如实体来自于网络文件,或者由动态语言生成。这时候要想准确获取长度,只能开一个足够大的 buffer,等内容全部生成好再计算。但这样做一方面需要更大的内存开销,另一方面也会让客户端等更久。

  • 当 Content-Length 大于实际值会超时
  • 当 Content-Length小于实际值会截断并可能导致后续的数据解析混乱。

Transfer-Encoding: chunked 该编码将实体分块传送并逐块标明长度,直到长度为0块表示传输结束, 这在实体长度未知时特别有用(比如由数据库动态产生的数据), Content-Length将被忽略。

HTTP 2.0

日期:2015  Google SPDY方案

针对http1.1的痛点做优化

  1. 慢启动,为了避免启动暂用太多资源,策略是先慢后快
  2. 多个tcp会互相竞争资源,当网速不足时,部分tcp会进行降速处理
  3. http队头阻塞,管道中同一时刻只能处理一个请求,在当前的请求没有结束之前,其他的请求只能处于阻塞状态。

解决方案-多路复用

  1. 多路复用,一个域名只保留一个tcp,只有一次慢启动,也不存在资源竞争
  2. 对头阻塞是通过把所有数据分帧传输,服务端选择性返回
  3. 基于二进制数据帧的传输、消息、流,所以可以做到乱序的传输,所有请求都是基于流。
  4. 支持请求设置优先级
  5. 服务器推送
  6. 头部压缩
  7. 增加全双工模式,不仅客户端能够同时发送请求,服务端也能同时处理多个请求,解决了队头堵塞的问题.
  8. 添加数据编号,可以取消某一次请求
  9. 彻底的二进制协议,头信息和数据体都是二进制,将所有的信息字段建立一张表,头信息复用,通过不同帧不不同处理

多路复用原理

  1. 在http 和 tcp中间 加入了 二进制分帧层
  2. http层数据会被转化为一个个带有请求ID编号的帧,通过协议栈将这些帧发送给服务器
  3. 服务器接收到所有帧之后,会将所有相同ID的帧合并为一条完整的请求信息。
  4. 然后服务器处理该条请求,并将处理的响应行、响应头和响应体分别发送至二进制分帧层。
  5. 二进制分帧层会将这些响应数据转换为一个个带有请求ID编号的帧,经过协议栈发送给浏览器。
  6. 浏览器接收到响应帧之后,会根据ID编号将帧的数据提交给对应的请求。

HTTP 3.0

 日期:2018
 

tcp的缺陷

  1. 依然没有解决tcp层面包的队头阻塞问题,而且http2一个域名只有一个tcp,当丢包严重更容易导致全停顿

  2. tcp 连接耗时,3次握手需要1.5个RTT,ssl 握手1-2RTT,共需要3-4个RTT

         Round Trip Time 浏览器发送一个数据包到服务器,再从服务器返回数据包到浏览器的整个往返时间称为 RTT
    
  3. TCP 协议僵化,升级tcp版本很难

  • 中间设备的僵化,早期很多硬件和软件都对tcp做了定制或优化
  • 操作系统只对tcp做了优化比较多

解决方案-使用QUIC

  1. 实现了类似 TCP 的流量控制、传输可靠性的功能。虽然 UDP 不提供可靠性的传输,但 QUIC 在 UDP 的基础之上增加了一层来保证数据可靠性传输。它提供了数据包重传、拥塞控制以及其他一些 TCP 中存在的特性。
  2. 集成了 TLS1.3 加密功能。
  3. 实现了 HTTP/2 中的多路复用功能。在同一物理连接上可以有多个独立的逻辑数据流。实现了数据流的单独传输
  4. 实现了快速握手功能。0-RTT 或者 1-RTT 来建立连接
  5. 流量控制
  6. 快速重启会话:普通基于tcp的连接,是基于两端的ip和端口和协议来建立的。在网络切换场景,例如手机端切换了无线网,使用4G网络,会改变本身的ip,这就导致tcp连接必须重新创建。而QUIC协议使用特有的UUID来标记每一次连接,在网络环境发生变化的时候,只要UUID不变,就能不需要握手,继续传输数据。

http3面临的困难

  1. 服务端和客户端对http3的支持不够
  2. 各个操作系统对UDP的优化没有TCP那么完善和成熟
  3. 中间设备不怎么支持UDP,导致丢包率高

HTTPS

日期1994 ,网景在1994年创建了HTTPS

基于http的基础上,新增ssl加密。

  1. 确认服务端的身份
  2. 主要实现传输通道的加密,保证客户端到服务端过程中,不被篡改或窃听。

而实际的内容传输依然保留原来的http的传输内容,也就是不加密。