图文介绍HTTP/2(特性、解决的问题、实现方法)

HTTP/2,主要是 基于Google的SPDY,是自HTTP/1.1从1999年发布16年后的首次更新。Servlet4.0将完全支持HTTP/2。

参考: https://www.youtube.com/watch?v=3uHhx-TMV8o

主要特性:
  • request/response多路复用(multiplexing):每个TCP连接都是全双工的
  • 二进制帧传输(binary framing)
  • 数据流优先级(stream prioritization):每个流都有优先级,用于决定哪些流最重要
  • 服务器推送(server push)
  • 头信息压缩(header compression)

HTTP/1.1的问题:
  • Head-Of-Line Blocking:假设一个网站需要加载几十个资源(css、js、jpg、等等),等到html文件加载成功后,浏览器会一个一个请求这些资源,并等待服务器按顺序一个一个返回。这时候,假设某一个文件返回比较慢或者由于某种原因在服务器那边阻塞了,后面排队中的文件还是得等待这个文件先返回。这就是Head-Of-Line Blocking问题。
各种解决的方法:
  • 方法1:建立多个tcp链接来请求资源:比如,第一个链接用来获取css文件、第二个链接用来获取js文件、等等
    • 方法1的不足之处:会增加TCP socket的使用量,如果不加限制,会导致服务器的TCP socket不够用;而且浏览器对某一个host的访问也会有最大链接数的限制,无法同时建立几十个链接。
  • 方法2:文件合并(File concatenation and image sprites):比如把多个js文件合并成一个;把多个icon文件放进一个文件中,通过js告诉浏览器在某个地方显示这个文件中的某个位置。
  • 方法3:分域(Domain sharding):为了解决浏览器对某个host访问的最大链接数限制,可以把不同的资源文件放到不同的domain中,比如js文件放一个domain、css文件放另外一个domain
  • 方法4:文件超级合并(Inlined assets):把所有的js、css文件合并到html中,甚至把图片文件通过base64编码后也合并到html中然后由js来decode和显示(哈哈哈……)

HTTP/2是站在HTTP/1.1肩膀上的一个改进而已,它只是HTTP/1.1下面的一个传输层,跟HTTP/1.1相比:
相同之处:
  • 相同的request/response模式
  • 没有新的method
  • 没有新的header
  • 在应用层没有引入新的花样
  • 没有修改URL规范、没有修改其他底层规范

不同之处:
  • Socket被当做稀有资源,一个server只开放一个socket
  • 实现比HTTP/1.1复杂很多,(不能再用telent host 80 然后GET abc.html的方法)

HTTP/2在OSI七层网络中的示意图:

相关概念:
  • 链接(Connection):就是一个TCP socket
  • 流(Stream):链接中的一个通道(channel)
  • 消息(Message):request、response、或控制消息
  • 帧(Frame):HTTP/2中用来传输消息的最小单位,一个消息可以被拆分成多个Frame来传输,用于解决Head-Of-Line Blocking问题
他们的包括关系:Connection > Stream > Message > Frame
如下图所示,单个Connection里面有向上和向下几个不同Stream,同一个Stream由不同的Frame来传输一个Message的Headers和Data。这种情况下,就不存在消息互相等待的问题了。


一个frame的结构:
  • Type可以为:DATA, HEADERS, PRIORITY, RST_STREAM, SETTINGS, PUSH_PROMISE, PING, GOAWAY, WINDOW_UPDATE, CONTINUATION。(DATA表示request/response中的body,如果长的body可以拆分为DATA1、DATA2……)
  • Flags:配置相关
  • Stream Identifier:标识这个frame是属于哪个Stream的

一个HTTP/1.1和HTTP/2请求比较的例子:
左边是HTTP/1.1的请求和头,右边是HTTP/2的头frame中的内容。“+END_STREAM”表示这是Stream中的最后一个Frame了。

他们对response比较的例子:
其中“-END_STREAM”表示这个frame不是stream中的最后一个。

HTTP/2 Header压缩(Compression)的实现(也叫做HPACK):
  • 一个connection中,几乎所有的header都是相同的,所以,没必要每次都重复传输
  • 可以让服务器和客户端保存这些header列表(在接收到第一个Stream的时候),后面的stream发送request/response的时候都只传输变化的header

数据流优先级(stream prioritization)的实现:
  • 客户端通知服务器每一个stream的优先级,(服务器不一定支持)
  • 两种方式:
    1. 在HEADER中指定依赖关系
    2. 通过一个独立的PRIORITY帧来指定改stream的优先级

HTTP/2服务器推送(Server Push):
  • 可以在浏览器请求之前就提前把相关资源推送给浏览器的缓存
  • 浏览器需要这些资源的时候,就可以直接从缓存中获取了
  • 注意:这个功能并不是为了代替WebSocket,只是为了提前push一下资源给客户端而已
  • Servlet4.0中关于Server Push的实现如下(Server接到对index.html的请求后,先把css和js文件push给客户端,然后再返回index.html。这样的话,浏览器获得index.html的时候,css和js文件已经在缓存中了,可以直接使用。):

从HTTP/1.1升级到HTTP/2:
  • 非安全方式(H2C):使用用来的端口(80)和101状态码(表示“switching protocols”)
  • 安全方式(H2):使用Application Layer Protocol Negotiatin (ALPN)

相关协议:
  • RFC7540:HTTP/2
  • RFC7541:HPACK
  • RFC7230:HTTP/1.1
  • RFC4648:BASE64 encoding







你可能感兴趣的:(网络协议)