关于HTTP /1.1 与 /2.0版本的常见差异和特性

3,478 阅读8分钟

HTTP 1.1

  • 默认使用长连接(connection:keep-alive)。解决了复用TCP的问题,可以减少TCP的三次握手开销。
    • 指的是用同一个TCP连接来发送和接受多个http请求/应答,而不是为了每一个新的请求/应答打开新的TCP连接的方法。
      • 另一个定义:一定时间内,同一域名多次请求数据,只建立一次HTTP请求,其他请求可复用每一次建立的连接通道,以达到提高请求效率的问题。这里面所说的一定时间是可以配置的,不管你用的是Apache还是nginx
      • 但是还是存在效率问题(HTTP2.0通过多路复用解决)
        • 串行的文件传输,只能顺序传输:当请求a文件时,b文件只能等待,等待a连接到服务器、服务器处理文件、服务器返回文件,这三个步骤。我们假设这三步用时都是1秒,那么a文件用时为3秒,b文件传输完成用时为6秒,依此类推。(注:此项计算有一个前提条件,就是浏览器和服务器是单通道传输)
        • 连接数上限:我们假设Apache设置了最大并发数为300,因为浏览器限制,浏览器发起的最大请求数为6,也就是服务器能承载的最高并发为50,当第51个人访问时,就需要等待前面某个请求处理完成。
    • 支持只发送header信息而不带任何body信息,如果客户端有权限,则返回100(代表继续),否则返回401(无权限)客户端如果接收到100,才把请求的Body发送到服务器。
      • 这样当服务器返回401的时候,客户端就可以不用发送请求body了,节约了带宽
    • 1.1开始支持获取文件的部分内容,这支持了 并行下载 和 断点续传。通过在Header的两个参数实现
      • 客户端请求的时候发送Range参数, 指定第一个字节的位置和最后一个字节的位置
      • 服务端响应的参数是:Content-Range
      • 在实际场景中,会出现一种情况,即在终端发起续传请求时,URL 对应的文件内容在服务器端已经发生变化,此时续传的数据肯定是错误的。如何解决这个问题 ? -用Last-modified / etag / if-range
        • If-Range 必须与 Range 配套使用。如果请求报文中没有 Range,那么 If-Range 就会被忽略。如果服务器不支持 If-Range,那么 Range 也会被忽略。
      • 工作原理:
        • 第一次请求,客户端发起一个get请求;服务器处理请求,返回文件内容以及相应的Header,包括Etag
        • 第二次请求(断点续传):客户端发起get请求,同时发送if-range,这个if-range的值就是第一次请求中服务器返回的etag;服务器判断etag是否匹配,是则返回206,否则返回200
    • HTTP/1.1 引入了更多的缓存控制策略,比如i
      • if-unmodified-since,其实就是和if-modified-since差不多的,常用来做判断断点续传的文件是否被修改过了。如果没有被修改,返回200;否则返回412预处理错误。
      • if-match
      • if-none-match
    • 1.1开始有Host(域) 这个概念

HTTP 2.0

  • 最大的一个目标是在用户和网站间只用一个连接

  • 二进制分帧(Binary Framing)

  • http1.x诞生的时候是明文协议,其格式由三部分组成:start line(request line或者status line),header,body。要识别这3部分就要做协议解析,http1.x的解析是基于文本。基于文本协议的格式解析存在天然缺陷,文本的表现形式有多样性,要做到健壮性考虑的场景必然很多,二进制则不同,只认0和1的组合。基于这种考虑http2.0的协议解析决定采用二进制格式,实现方便且健壮

  • 几个概念:

    • frame 帧:http/2通信的最小单位,单个帧包含帧首部,其中标注了当前帧所属的stream
    • message 消息:由若干个frame组合而成,例如请求,响应
    • connection 连接:与http/1 相同,指的都是对应的tcp连接
    • stream 流,已建立的连接上的双向字节流。
    • 数据流以消息的形式发送,而消息由一个或多个帧组成,帧可以在数据流上乱序发送,然后再根据每个帧首部的流标识符重新组装。二进制分帧是HTTP/2的基石,其他优化都是在这一基础上来实现的。
  • 支持多路复用(Multiplexing),在数据链路层使用二进制分帧,可以允许同时通过单一的ht2连接发起多重的请求-响应消息,同个域名只需要占用一个 TCP 连接,解决了请求阻塞的问题。

    • 在HTTP1.1中,同一域名在同一时间的请求数量是有限制的,超过限制会阻塞请求。
    • Head-of-Line Blocking,在http1.x中,TCP的connection在同一时间只能允许一个请求经过,因为HTTP1.x需要每条请求都是可是识别,按顺序发送,否则server就无法判断该相应哪个具体的请求。
    • 多路复用指的是:在同一个域名下,开启一个TCP的connection,每个请求以stream的方式传输,每个stream有唯一标识,connection一旦建立,后续的请求都可以复用这个connection并且可以同时发送,server端可以根据stream的唯一标识来相应对应的请求。之所以可以复用,是因为每个stream高度独立,堵塞的stream不会影响其它stream的处理。一个连接上可以有多个stream,每个stream的frame可以随机的混杂在一起,接收方可以根据stream id将frame再归属到各自不同的request里面。
    • 而多路复用什么时候关闭呢?
      • 用户离开这个页面
      • server主动关闭connection
    • 那么在HTTP2.0下,我们就不需要做
      • JS文件的合并:在之前,我们会将上线若干个模块的代码进行压缩合并成一个文件,减少http请求数。但是这样就会导致缓存问题:如果有一个模块修改了,就会导致客户端重新下载整个大文件,难以缓存。现在用HTTP2.0就不需要做这件事情了
      • CDN资源放在不同域名下,绕开浏览器的通道上限。
  • 头部压缩:

    • http2.0使用encoder来减少需要传输的header大小,通讯双方各自cache一份header fields表,既避免了重复header的传输,又减小了需要传输的大小。高效的压缩算法可以很大的压缩header,减少发送包的数量从而降低延迟。
  • 服务端推送(server push):

    • 从HTTP/2开始,服务器除了相应客户端的请求之外,还可以向客户端额外推送资源,这些资源遵守同源协议,有自己独立的URL,可以被浏览器缓存,可以多页面共享;同时客户端还可以拒绝推送过来的资源
    • 有了server push,客户端可以通过额外的http头部,列出需要服务器push 哪些资源
    • 服务器可以提前向客户端推送需要的资源。
  • 流量控制(flow control):

    • 在TCP的流量控制中,是以单个tcp为单位的流量控制;可是在http2.0时代,传输已经以单个stream为单位,tcp的流量控制无法做到这么精细的粒度,因此就在应用层引入了flow control,从而对每一个stream都做了不同的限流
    • 而HTTP/2利用stream来实现flow-control,引入了stream对TCP连接的抢占,不加控制就会造成stream被阻塞。而http/2上的flow-control就是确保同一连接上的多个流之间不会造成破坏性的干扰
  • 流优先级(stream priority):

    • 在HTTP/2中,每个请求都可以带一个31bit的优先值,0表示最高优先级, 数值越大优先级越低。有了这个优先值,客户端和服务器就可以在处理不同的流时采取不同的策略,以最优的方式发送流、消息和帧。(其实我的理解还是为了解决TCP抢占的问题?)

从HTTP/1.x到HTTP/2的过程中,仍然适用的优化规则

  • 减少DNS查询。DNS查询需要时间,没有resolved的域名会阻塞请求。
  • 减少TCP连接。HTTP/2只使用一个TCP连接。
  • 使用CDN。使用CDN分发资源可以减少延迟。
  • 减少HTTP跳转。特别是非同一域名的跳转,需要DNS,TCP,HTTP三种开销。
  • 消除不必要的请求数据。HTTP/2压缩了Header。
  • 压缩传输的数据。gzip压缩很高效。
  • 客户端缓存资源。缓存是必要的。
  • 消除不必要的资源。激进的提前获取资源对客户端和服务端都开销巨大。

因为HTTP/2而不一样的优化规则

  • 域名分片:大概意思就是我们把资源放在不同域名下,绕过浏览器HTTP连接数的限制。HTTP2.0不用了
  • 文件合并:在HTTP2.0中,我们要使用更小的模块,优化缓存策略(因为大文件的某一部分更改了,整个大文件就无法缓存了)
  • 内联资源:在HTTP2.0中直接使用server push。

参考资料:

  1. github.com/creeperyang…
  2. 关于http2.0中的流量控制:www.zhihu.com/question/27…
  3. www.cnblogs.com/memset/p/ht…