关于http2,我们都知道有三大特性,头部压缩、Server Push、多路复用。
keep-alive
在聊多路复用之前先来聊聊keep-alive,在没有Keep-Alive前,我们与服务器请求数据的流程是这样:

- 浏览器请求//static.mtime.cn/a.js–>解析域名–>HTTP连接–>服务器处理文件–>返回数据–>浏览器解析、渲染文件
- 浏览器请求//static.mtime.cn/b.js–>解析域名–>HTTP连接–>服务器处理文件–>返回数据–>浏览器解析、渲染文件
- …
- …
- …
- 这样循环下去,直至全部文件下载完成。
这个流程最大的问题就是:每次请求都会建立一次HTTP连接,也就是我们常说的3次握手4次挥手,这个过程在一次请求过程中占用了相当长的时间,而且逻辑上是非必需的,因为不间断的请求数据,第一次建立连接是正常的,以后就占用这个通道,下载其他文件,这样效率多高啊!你猜对了,这就是Keep-Alive。
Keep-Alive解决哪些问题
Keep-Alive解决的核心问题:一定时间内,同一域名多次请求数据,只建立一次HTTP请求,其他请求可复用每一次建立的连接通道,以达到提高请求效率的问题。这里面所说的一定时间是可以配置的,不管你用的是Apache还是nginx。
这种方案有什么问题吗
解决了多次连接的问题,但是依然有两个效率上的问题:
- 串行的文件传输。当请求a文件时,b文件只能等待,等待a连接到服务器、服务器处理文件、服务器返回文件,这三个步骤。我们假设这三步用时都是1秒,那么a文件用时为3秒,b文件传输完成用时为6秒,依此类推。(注:此项计算有一个前提条件,就是浏览器和服务器是单通道传输)
- 连接数过多。我们假设Apache设置了最大并发数为300,因为浏览器限制,浏览器发起的最大请求数为6,也就是服务器能承载的最高并发为50,当第51个人访问时,就需要等待前面某个请求处理完成。
http2的多路复用
HTTP/2的多路复用就是为了解决上述的两个性能问题,我们来看一下,他是如何解决的。
解决第一个:在HTTP1.1的协议中,我们传输的request和response都是基本于文本的,这样就会引发一个问题:所有的数据必须按顺序传输,比如需要传输:hello world,只能从h到d一个一个的传输,不能并行传输,因为接收端并不知道这些字符的顺序,所以并行传输在HTTP1.1是不能实现的。
http2引入二进制数据帧和流的概念,其中帧对数据进行顺序标识,如下图所示,这样浏览器收到数据之后,就可以按照序列对数据进行合并,而不会出现合并后数据错乱的情况。同样是因为有了序列,服务器就可以并行的传输数据,这就是流所做的事情。

解决第二个问题:HTTP/2对同一域名下所有请求都是基于流,也就是说同一域名不管访问多少文件,也只建立一路连接。同样Apache的最大连接数为300,因为有了这个新特性,最大的并发就可以提升到300,比原来提升了6倍!
总结
HTTP2采用二进制格式传输,取代了HTTP1.x的文本格式,二进制格式解析更高效。
多路复用代替了HTTP1.x的序列和阻塞机制,所有的相同域名请求都通过同一个TCP连接并发完成。在HTTP1.x中,并发多个请求需要多个TCP连接,浏览器为了控制资源会有6-8个TCP连接都限制。
HTTP2中
- 同域名下所有通信都在单个连接上完成,消除了因多个 TCP 连接而带来的延时和内存消耗。
- 单个连接上可以并行交错的请求和响应,之间互不干扰