http协议是一个不大不小的知识体系,当新手还没有整体视角的时候,只会记忆某一版本的某一特性,以为搞懂了一个知识点但随后又发现一个更大的盲区。当抛弃这些繁杂知识点,以解决互联网传输问题为导向,才能更好的理解http的变迁,毕竟http和软件开发有诸多类似,都是一个根据发展现状不算迭代补漏的过程,毕竟设计者也没有预支未来的能力,而这些迭代主要在以下方面:

  • 丰富传输内容:最开始并不支持图片视频类的多媒体文件
  • 减少来回传输次数:减少RTT(Round Trip Time)即消息一来一回所花费的时间
  • 一次传输尽可能传输更多:压缩
  • 尽可能多路复用
  • 加密
  • 缓存:减少不必要的传输

###先看时间线
1991年:http0.9 那个年代的互联网有多简陋可想而知,仅支持get
1996年:http1.0 不够用了,添加请求方法POST用于提交,文件类型,如图片视频,添加请求头http Header
1997年:http1.1 目前用的都是1.1,居然诞生于二十多年前
2009年:SPDY1 (http2前身)
2012年:SPDY2 (http2前身)
2015年:http2

http1.1

1997年的http1.1引入和很多实用机制:

  • 持久连接: 减少了RTT,不必每次都重新建立tcp链接,重复三次握手
  • 分块传输编码
  • 缓存控制机制:减少没必要的传输
  • 内容协商机制:给请求头中客户端所期望的内容,如json,text等
  • 管道机制:尴尬

持久连接依然有性能问题:http1中每个请求和响应都有建立一个tcp连接,虽然1.1引用了持久连接机制,但每个连接上同时只能有一个请求或响应,这样,一来,一回完成后,再继续下一个一来一回,处于半双工状态利用率不高。因为服务器发送第一个响应后,到手打第二个请求之前,都是空闲状态。
为了解决此问题,引入了管道。

尴尬的管道机制:管道可以让浏览器把所有请求都发过来,服务器则可以响应一个后继续响应下一个,但有个严重的问题:当第一个非常耗时阻塞时,后续所有响应都要等待,这就是队首阻塞问题(Head-of-Line Blocking)。
第二个主要尴尬原因:链路中间的其他设备不一定支持管道,这些导致管道一直处于理论状态,实际应用很少。

题外话:现代浏览器允许统一域名下并发连接6-8个tcp连接,为此很多网页静态资源放在散列的多个域名下。

还有请求头是未压缩的纯文本,且有很多冗余信息,如cookie、UserAgent等,造成不必要的浪费,优化方法是采用短小的独立域名托管静态资源:1.域名段,字段少,2.独立域名不共享cookie减少无用内容。

http2

  • 格式化传输数据:
    http1.1中请求和响应报文,由起始行、首部和实体正文组成,中间由文本换行符分割,http2把报文分割成更小的帧,并进行二进制编码,帧(Frame)作为http2通信的最小单位。帧都包含帧首部用来进行流标识,这样帧可以乱序发送,最后靠首部的流标识进行顺序组装。

  • 多路复用
    http2中,同域名下的所有通信都在一个tcp连接上完成,且连接是双向通信数据流,这正是tcp协议的长项:三次握手后,持续发送大量数据。
    重点:之前http之所以性能差,是因为频繁建立多个tcp,虽然基于tcp,但因为一次连接传输内容少,而连接频发,导致tcp的优势利于的少,劣势利用的多。