HTTP/2的优先级
前言
记得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的优先级的更多相关文章
- Linux资源管理-IO优先级
前一篇博客介绍了利用 cgroup 来控制进程的 CPU和内存使用情况, 这次补上使用 cgroup 来控制进程的IO优先级的方法. 前提条件 如果想控制进程的IO优先级, 需要内核的支持, 内核编译 ...
- Cocos2dx中线程优先级
Cocos2dx中线程优先级问题 不论是ios还是android,遇到耗时的任务都要另起线程处理,否则程序不能及时用户的反馈.游戏中如果一圈循环不能在1/frameRate(帧率是30则1/30)秒内 ...
- 体验Rabbitmq强大的【优先级队列】之轻松面对现实业务场景
说到队列的话,大家一定不会陌生,但是扯到优先级队列的话,还是有一部分同学是不清楚的,可能是不知道怎么去实现吧,其实呢,,,这东西已 经烂大街了...很简单,用“堆”去实现的,在我们系统中有一个订单催付 ...
- C语言运算符优先级
优先级 运算符 名称或含义 使用形式 结合方向 说明 1 [] 数组下标 数组名[常量表达式] 左到右 -- () 圆括号 (表达式)/函数名(形参表) -- . 成员选择(对象) 对象.成员名 -- ...
- CSS优先级
一.CSS代码出现的几个位置 多重样式(Multiple Styles):如果外部样式.内部样式和内联样式同时应用于同一个元素,就是使多重样式的情况. 一般情况下,优先级如下:(外部样式)Extern ...
- nginx之location匹配优先级和安全问题
最近一直在做location的配置,遇到优先级别问题(如有配置不当,会存在安全隐患),以下是个人的一些学习体会 一.location 匹配符 1.等于匹配符: ##"=" ...
- C#夯实基础之多线程三:线程的优先级
一.为什么需要优先级--线程调度的问题 在现实生活中,优先级是一个很常见的现象:在火车站,如果你是孕妇,你是可以走进站中的专门绿色通道的,可以提前上火车以免拥挤:火警119匪警110出警的时候,都是人 ...
- js算数优先级
.fullwidth-table { background: white } .fullwidth-table>th { background: #f50 } 优先级 运算类型 关联性 运算符 ...
- css知多少(6)——选择器的优先级
1. 引言 上一节<css知多少(5)——选择器>最后提到,选择器类型过多将导致一些问题,是什么问题呢?咱们直接举例子说明. 上图中,css中的两个选择器都是针对<span>的 ...
- 深入理解this机制系列第二篇——this绑定优先级
前面的话 上一篇介绍过this的绑定规则,那如果在函数的调用位置上同时存在两种以上的绑定规则应该怎么办呢?本文将介绍this绑定的优先级 显式绑定 pk 隐式绑定 显式绑定胜出 function fo ...
随机推荐
- setquota - 设置磁盘配额或时间限制
SYNOPSIS(总览) setquota [ -u | -g ] filesystem-name block-soft block-hard inode-soft inode-hard name.. ...
- python实现发送文本邮件
简单实现了python发送文本邮件 #!/usr/bin/env python # -*- coding: utf-8 -*- # @Time : 2018/4/25 17:09 # @Author ...
- EventBus总结(原)
1.EventBus的作用 EventBus is a publish/subscribe event bus for Android and Java. EventBus可以被用来在各种自定义的监听 ...
- 转载关于struts命名空间的一则报警
今天花了点时间把struts2警告事件彻底的测试了一边,终于有点眉目了.希望能给其他人带来一点帮助.文章属于原创.并不需要转载的时候注明出处,而是希望转载的朋友一定要看明白本文内容再转载,因为我你都清 ...
- C语言小笔记(1)
枚举类型的大小是4,和一个int整形大小一样 就是最后一个逗号后面的表达式的值,比如: int a=1,b; b=(a+1,a+2,a+3); 那么b的值就是a+3,也就是4 函数名 :print ...
- 在Anaconda环境下使用Jupyter Notebook
!!!Anaconda 和 Jupyter Notebook 在 zsh 环境下不能正常使用! 启动建立的 Anaconda 环境 安装 nb_conda:conda install nb_conda ...
- mac 安装Navicat_Premium 破解版带汉化
因为近期要用mongodb,本想着下载一个Navicat for mongodb 但是一直没有给力带帖子,所以就靠着百度自己找,功夫不负有心人. 下面附上百度网盘,里面有一个txt文档,在安装前一定要 ...
- sigaction函数学习
sigaction(查询或设置信号处理方式) 相关函数 signal,sigprocmask() ,sigpending,sigsuspend, sigemptyset 表头文件 #include&l ...
- linux下lamp.sh一键配置lamp环境流程
linux下lamp.sh一键配置lamp环境流程 一.总结 一句话总结: 2.将网站从github上clone到/data/www/网站域名/ 3.更改网站目录权限:chown -R apache: ...
- VMware 虚拟机NAT模式如何设置网络连接,从头到尾全过程~!!
一.首先查看自己的虚拟机服务有没有开启,选择电脑里面的服务查看: 1.计算机点击右键选择管理 2.进入管理选择VM开头的服务如果没有开启的话就右键开启 二.虚拟机服务开启后就查看本地网络虚拟机的网 ...