前言

记得HTTP/3即将标准化了。今日早读文章由@smallbonelu翻译授权分享。

@smallbonelu,一枚爱好跑步的前端工程师

正文从这开始~~

以正确的顺序请求页面资源对于快速的用户体验至关重要。想象一下,如果一个网页上有一堆图片,还有一个外部样式表,一些自定义Web字体和一些在head中的脚本。如果浏览器首先下载了所有图片并且最后加载了样式表,在所有内容都加载完毕前,页面将完全是空白页。如果浏览器首先加载了所有阻塞资源,接着是Web字体和图片,那么它可以更早地呈现页面,并让用户开始看到内容,同时加载其余的图片。我在Chrome浏览器性能工作上的大部分时间都花在了尝试优化加载资源的顺序以获得最佳用户体验上。

使用HTTP/1.x,浏览器可以完全控制资源加载顺序。每个连接一次只能支持一个资源请求,服务器会尽快返回请求的内容。浏览器可以通过决定何时请求资源以及打开多少个并行连接来安排请求。

HTTP/2让这些事情变得更好也更复杂了。浏览器可以一次请求多个资源,指定一些优先级信息来帮助确定应该如何处理这些资源,然后等待服务器发回所有数据,而不是一次请求一个。如果浏览器和服务器都支持优先级,则应使用浏览器指定的规则并使用所有可用带宽来传递资源,而不会有资源之间的相互竞争。

每个资源都获取一个stream ID来标识连接上的资源,并且有三个参数用于定义资源优先级:

1.父级数据流(Parent Stream):这个数据流是一个“依赖”资源或者应该在之后被传递的数据流。有一个所有数据流共享的虚拟root stream 0。
2.权重(Weight):1到256之间的数字,用于标识在多个数据流共享连接时分配给此数据流的带宽量。带宽是相对于所有其他活动的数据流的权重分配的,而不是绝对值。
3.独占位(Exclusive bit):一个标志,表示应该在不与任何其他数据流共享带宽的情况下下载。

浏览器不一定同时知道所有资源,因此服务器能够在新请求到达时重新确定请求的优先级也很关键。

那么……我们是怎么做的呢?

浏览器引擎

Chrome

这包括使用Chromium的优先级逻辑和网络堆栈的所有内容。

Chrome是唯一使用独占位的浏览器,它在每个资源上使用它。它构建了一长串资源,将较低优先级的资源链接到仍在等待的最后一个相同或更高优先级的资源。如果没有更高优先级的资源挂起,则启动新链。权重以静态映射的方式分配,Chrome的五个内部优先级分别对应相应的权重(即HIGHEST为256)。

假设给定几个请求队列,所有请求都设置了独占位,服务器将选择权重最高的一个,完成传递后,就将其从列表中弹出并重新选择。

假设Chrome正确构建了排序,这可能非常有效。独占下载资源是样式表和脚本等阻塞资源的最佳选择。当涉及到图片和视频时,你可能需要一些交错执行的任务(特别是对于渐进式图片)。否则,在转到下一个请求前,你将要等待每个图片或视频完全下载下来。

Firefox

Firefox实现了HTTP/2的树结构,并构建了一个虚拟的数据流树,用来对不同请求类型进行分组。Firefox对分组进行了加权,以便为更重要的组提供更多的带宽,并且当所有节点都已完成时,空闲周期(idle cycles)可用于响应。

在根级别中,有一个“leader”组,,它的带宽是“Other group”的两倍。在“leader”组中,有一个叫“follower”的子组,它只有在“leader”组的直系后代完成下载后才会开始下载。例如,在权重为200的“leader”组下面,一旦所有CSS完成下载后,图片和字体才会开始下载。一个组内的所有子资源具有相同的权重并均匀分配带宽(同时下载所有图片或所有脚本)。

从整体结构上来看Firefox非常出色,可以为推测请求定义空闲周期,但对同时下载所有资源优先级的划分并不是很好。像样式表和脚本等这样的阻塞资源的优先下载要比按顺序下载它们才能让解析器处理文档要好。

Safari

这包括iOS上的所有浏览器(包括Chrome)。

Safari采用了一种非常简单的方法,看起来是SPDY优先级的遗留部分。五个内部webkit优先级静态映射到权重,并且没有定义依赖关系。所有请求基于每个资源的优先级来划分带宽权重进行同时下载(例如,脚本获得图片带宽的三倍)。

这样导致高并发性并不是很好,而且落后于Firefox的实现,在Firefox中至少follower组的资源会等到leader组资源全部完成任务之后(尽管它可能不足以证明Firefox中树的复杂性)。

Microsoft Edge / Internet Explorer

简而言之,Microsoft Edge(和Internet Explorer)根本不支持优先级。所有请求均匀分配带宽(几乎是最糟糕的情况)。

Servers/Hosting/CDNs

现在大多数服务器都支持HTTP/2了,通常也”支持”优先级的。支持加了引号,是因为即使一个服务器内部支持资源优先级,实际上让它能够与浏览器工作也需要调整网络堆栈并尽可能减少输出缓冲而不影响吞吐量。

缓冲可能是一个问题,因为服务器可以发送一堆低优先级的响应,这些响应在高优先级响应到来之前已经在缓冲区中排队。发送高优先级响应时,无法抢占已缓冲的低优先级响应。缓冲可以来自服务器本身,TLS层,TCP发送的缓冲,甚至来自网络上的bufferbloat,跟踪并消除所有多余的缓冲可能会很复杂。我在今年早些时候的一篇博文中谈到了一些原因和解决方案,但这并不是一个详尽的清单。

为了测试服务器优先级的有效性,我构建了一个测试页面,你可以在你的服务堆栈上部署该测试页面以查看优先级是否正常工作。它专门针对Chrome的优先级逻辑,因此最好使用慢速连接上的Chrome进行测试。它先将3MB低优先级图片排队,然后在下载并执行高优先级脚本后,脚本会发送4个高优先级请求(一张图片,一个页面背景,一个自定义的webfont和一个阻塞脚本)。当优先级正常工作时,后置的高优先级请求的资源会跳过低优先级请求并快速得到响应:

当优先级工作不正常时,部分或全部后置的高优先级请求的资源会被延迟,直到优先级较低的请求完成为止:

后置请求的阻塞脚本的延迟超出了“DOM Content Loaded”的度量值,字体和2个图片的延迟对视觉体验产生了相当大的影响:

我们从哪里开始?

为了跟踪CDN和托管服务提供商支持HTTP/2优先级的程度,Andy Davies创建了一个GitHub仓库,用于跟踪当前的支持状况,任何人都可以提交测试结果来群策群力。在撰写本文时,情况非常糟糕,只有两个CDN确实正确地确定了优先级,并且存在一些非常令人震惊的失败(例如每个云提供商甚至Google的GFE)。希望通过提高对这种情况的认知,我们将能够为优先级提供更广泛的支持。

对托管和服务器来说,好消息是你总是可以在它们之前配置一个支持优先级的CDN来解决问题(尽管直接支持它会很好)。

在浏览器方面,除了敦促浏览器厂商以获得更好的支持之外,没有太多可以做的事情。其中的一些厂商可能会遇到架构问题,如他们的浏览器引擎在操作系统的网络堆栈层之上,导致无法传递优先级信息。可能是我的偏见,但我认为Chrome是最接近“正确”的做法,但仍有相当大的改进空间。

HTTP/3也即将到来,但目前的优先级方案不会改变。这个改变是网络堆栈的终结。在服务器端,这意味着操作系统的缓冲和拥塞控制不再起作用,服务器软件100%负责最小化缓冲(包括拥塞控制算法以最小化缓冲区)。
那么就说到这里,希望为了HTTP/2和一个安全,高性能的网络,我们可以在2019年修复资源优先级。

关于本文
译者:@smallbonelu
译文:https://github.com/FE-star/speed/blob/master/2018.06.md
作者:@Patrick Meenan
原文:https://calendar.perfplanet.com/2018/http2-prioritization/

HTTP/2的优先级的更多相关文章

  1. Linux资源管理-IO优先级

    前一篇博客介绍了利用 cgroup 来控制进程的 CPU和内存使用情况, 这次补上使用 cgroup 来控制进程的IO优先级的方法. 前提条件 如果想控制进程的IO优先级, 需要内核的支持, 内核编译 ...

  2. Cocos2dx中线程优先级

    Cocos2dx中线程优先级问题 不论是ios还是android,遇到耗时的任务都要另起线程处理,否则程序不能及时用户的反馈.游戏中如果一圈循环不能在1/frameRate(帧率是30则1/30)秒内 ...

  3. 体验Rabbitmq强大的【优先级队列】之轻松面对现实业务场景

    说到队列的话,大家一定不会陌生,但是扯到优先级队列的话,还是有一部分同学是不清楚的,可能是不知道怎么去实现吧,其实呢,,,这东西已 经烂大街了...很简单,用“堆”去实现的,在我们系统中有一个订单催付 ...

  4. C语言运算符优先级

    优先级 运算符 名称或含义 使用形式 结合方向 说明 1 [] 数组下标 数组名[常量表达式] 左到右 -- () 圆括号 (表达式)/函数名(形参表) -- . 成员选择(对象) 对象.成员名 -- ...

  5. CSS优先级

    一.CSS代码出现的几个位置 多重样式(Multiple Styles):如果外部样式.内部样式和内联样式同时应用于同一个元素,就是使多重样式的情况. 一般情况下,优先级如下:(外部样式)Extern ...

  6. nginx之location匹配优先级和安全问题

    最近一直在做location的配置,遇到优先级别问题(如有配置不当,会存在安全隐患),以下是个人的一些学习体会 一.location 匹配符 1.等于匹配符:      ##"=" ...

  7. C#夯实基础之多线程三:线程的优先级

    一.为什么需要优先级--线程调度的问题 在现实生活中,优先级是一个很常见的现象:在火车站,如果你是孕妇,你是可以走进站中的专门绿色通道的,可以提前上火车以免拥挤:火警119匪警110出警的时候,都是人 ...

  8. js算数优先级

    .fullwidth-table { background: white } .fullwidth-table>th { background: #f50 } 优先级 运算类型 关联性 运算符 ...

  9. css知多少(6)——选择器的优先级

    1. 引言 上一节<css知多少(5)——选择器>最后提到,选择器类型过多将导致一些问题,是什么问题呢?咱们直接举例子说明. 上图中,css中的两个选择器都是针对<span>的 ...

  10. 深入理解this机制系列第二篇——this绑定优先级

    前面的话 上一篇介绍过this的绑定规则,那如果在函数的调用位置上同时存在两种以上的绑定规则应该怎么办呢?本文将介绍this绑定的优先级 显式绑定 pk 隐式绑定 显式绑定胜出 function fo ...

随机推荐

  1. Razor 保存动态表格

    本文转载自  ASP.NET MVC数组模型绑定 ,https://www.cnblogs.com/choon/p/5429065.html 内容根据评论内容中的方式有所调整 在ASP.NET MVC ...

  2. 2019HDU多校第三场 Distribution of books 二分 + DP

    题意:给你一个序列,你可以选择序列的一个前缀,把前缀分成k个连续的部分,要求这k个部分的区间和的最大值尽量的小,问这个最小的最大值是多少? 思路:首先看到最大值的最小值,容易想到二分.对于每个二分值m ...

  3. 使用Maven创建Web项目(转)

    转自:http://ju.outofmemory.cn/entry/49508 本文通过Maven完成一个简单的Web项目(注意,Spring配置不是重点,看看就行) 1.从Maven模板创建Web应 ...

  4. Java使用SSH远程访问Windows并执行命令

    转载于:http://blog.csdn.net/carolzhang8406/article/details/6760430   https://blog.csdn.net/angel_xiaa/a ...

  5. Kaggle数据集下载

    Kaggle数据集下载步骤: 安装Kaggle库: 注册Kaggle账户: 找到数据集,接受rules: 在My Account>>API中,点击Create New API Token, ...

  6. datagrid+toolbar 不分页 显示

    1 新建DataGrid.js文件 /*** * * *el: table id * ***/ function showDataGrid(el) { $(el).datagrid({ title: ...

  7. paper 133:结构张量Structure Tensor(一)

    1.结构张量的作用:       能够区分图像中的平坦区域,边缘,角点: 2.图像中的结构张量的定义    1)是一个矩阵:    2)与图像的水平,垂直梯度有关,定义如下: 在MATLAB中,可以用 ...

  8. 快速搜索插件之quicksearch

    项目中如果遇到快速搜索table表格,select下拉框,ul>li列表等内容的时候,可以使用quicksearch快速搜索插件,举个栗子: 首先要引用jquery.js + jquery.qu ...

  9. angularjs的select使用2

    https://cnodejs.org/topic/549007b44823a0234c9e1716 myAppModule.controller('FrmController', ['$scope' ...

  10. Procedure or function 'pu_usr_User' expects parameter '@WhiteIp', which was not supplied.

    遇到这个问题,是因为存储过程的参数,设置默认值写错了. 错误写法 @WhiteIp NVARCHAR(MAX) NULL, Stored procedure with default paramete ...