背景
最近在回顾HTTP协议,回顾到HTTP/1.1时,发现它对1.0的改进,有一点是增加了持久连接。HTTP/1.0 每进行一次 HTTP通信,都需要经历建立TCP连接、传输HTTP数据和断开,这一点无疑会增加大量开销。为了解决这个问题。HTTP/1.1中增加了持久连接的方法,它的特点是在一个TCP连接上可以传输多个HTTP请求,只要浏览器或者服务器没有明确断开连接,那么该TCP连接会一直保持。
问题
我的问题先开始不是一个TCP连接可以发多少个HTTP请求,而是这句话“目前浏览器中对于同一个域名,默认允许同时建立6个TCP持久连接”。这时我就在想?为什么要建立6个连接?它的资源是怎么分配的?都放到一个TCP连接中请求不行吗?并行请求吗?还是说一个一个TCP连接有HTTP请求次数限制?...
由此才引出了“一个TCP连接可以发多少个HTTP请求”这一问题。
1、一个TCP连接可以发多少个HTTP请求
一般情况下,一个TCP可以发送多个HTTP请求。只要请求头字段中的connection字段不为close,那么就一直保持连接。如果在请求头中设置connection:close,才会在请求完成之后断开连接。
那么,问题来了如果收到的HTML包含大量资源,如几百张图片、那这些大量的图片资源是如何请求的呢?
呃呃呃呃~继续分析一下。
- 肯定不能只开一个TCP连接顺序下载,那样肯定很耗时。
- 但是也不能有多少张图片,开多少个TCP连接发HTTP请求,那电脑或者服务器都可能受不了。
关键点:目前浏览器中对于同一个域名,默认允许同时建立6个TCP持久连接。也就是说在同一个域名下,浏览器可以开6个TCP请求(Chrome)
2、大量资源如何请求
如果这些资源都是HTTPS并且在一个域名下(HTTP/2.0都是在HTTPS的基础上实现的),那么就可以采用多路复用技术 去请求资源。如果不是HTTPS,则通过HTTP/1.0中同域名下建立6个TCP连接并行去请求资源(Chrmoe)。
关于资源如何分配给这六个TCP连接,这个问题还未知晓。
继续思考:一个TCP连接下,HTTP请求是否可以并行呢?我们目前了解到,虽然持久连接可以减少TCP建立与断开的次数,在一定程度上减少了服务器的负担。但是!!!后一个HTTP请求只能等前一个HTTP请求返回结果之后,才能继续请求。如果上一个HTTP请求因为某些原因没有及时返回,那么就会造成后面的请求无法进行,这就是队头阻塞问题。
HTTP/1.1中试图通过HTTP Pipelining(管线化)的技术来解决队头阻塞的问题。HTTP/1.1中的管线化是指将多个HTTP请求整批提交给服务器的技术,虽然可以整批发送请求,不过服务器依然需要根据请求顺序来回复浏览器的请求。甚至一些代理服务器无法处理HTTP Pipelining。
FireFox、Chrome 都做过管线化的试验,但是由于各种原因,它们最终都放弃了管线化技术。
3、HTTP/1.1一个TCP连接中HTTP请求可以并且发送吗?
浏览器默认关闭管道技术,因此不可以。
4、那么HTTP/2.0可以吗?
可以的
HTTP/2.0-多路复用
HTTP/2 最核心、最重要且最具颠覆性的就是多路复用机制
先来谈谈为什么会出现多路复用?主要有是因为HTTP/1.1的两个问题,带宽利用率低的问题和队头阻塞问题
带宽利用率低的问题
之所以说 HTTP/1.1 对带宽的利用率不理想,是因为 HTTP/1.1 很难将带宽用满。比如我们常说的 100M 带宽,实际的下载速度能达到 12.5M/S,而采用 HTTP/1.1 时,也许在加载页面资源时最大只能使用到 2.5M/S,很难将 12.5M 全部用满。主要有以下三个原因:
- 第一个原因,TCP 的慢启动:TCP成功连接之后,先开始会以一个慢速去发送数据,之后会慢慢加快发送速度,这就是TCP的慢启动。慢启动是 TCP 为了减少网络拥塞的一种策略,我们是没有办法改变的
- 同时开启了多条 TCP 连接,那么这些连接会竞争固定的带宽:无法协商资源的下载顺序,图片、视频等普通资源文件会抢夺高优先级的资源(JavaScript、CSS)带宽,导致关键资源下载速度很慢。
- HTTP/1.1 队头阻塞的问题:一个TCP连接同一时间只能处理一个HTTP连接,因此,如果当前请求没有结束,则会阻碍后面的HTTP请求。
HTTP/2.0的多路复用
HTTP/2 的思路就是一个域名只使用一个 TCP 长连接来传输数据,减少慢启动次数,同时也避免了多个TCP连接竞争带宽。并且实现资源的并行请求,避免队头阻塞。
HTTP/2.0-多路复用实现方式
通过引入二进制分帧层,就实现了HTTP的多路复用技术,本质是将串行的请求处理并行化,为了实现功能需要双方多维护一个数据结构。
HTTP/2.0的其它特性
- 设置优先级:对资源设置优先级,优先处理重要请求。
- 服务器推送:服务器将资源提前推送到浏览器,以此加快打开页面速度。
- 头部压缩:将请求头压缩。