Nginx 学习笔记(十)介绍HTTP / 2服务器推送(译)
原文地址:https://www.nginx.com/blog/nginx-1-13-9-http2-server-push/
我们很高兴地宣布,2018年2月20日发布的NGINX 1.13.9支持HTTP / 2服务器推送。对于NGINX Plus用户,即将发布的NGINX Plus R15版本将包含HTTP / 2服务器推送支持,计划于2018年4月发布。
HTTP / 2规范中定义的服务器推送允许服务器抢先将资源推送到远程客户端,预计客户端可能很快会请求这些资源。通过这样做,您可以在页面加载操作中将RTT(往返时间 - 请求和响应所需的时间)减少一个RTT或更多,从而为用户提供更快的响应。
服务器推送可用于为客户提供样式表,图像以及呈现网页所需的其他资源。您应该注意只推送所需的资源; 不要推送客户端可能已经缓存的资源。
在这篇博文中,我描述了:
- HTTP / 2服务器推送的基本配置
- 如何验证HTTP / 2服务器推送是否正常(使用浏览器工具或
nghttp
) - 使用
Link
标题自动推送内容 - 有选择地推送内容
- 衡量HTTP / 2服务器推送的效果
配置HTTP / 2服务器推送
要将资源与页面加载一起推送,请http2_push
按如下所示使用该指令:
server {
# Ensure that HTTP/2 is enabled for the server
listen 443 ssl http2; ssl_certificate ssl/certificate.pem;
ssl_certificate_key ssl/key.pem; root /var/www/html; # whenever a client requests demo.html, also push
# /style.css, /image1.jpg and /image2.jpg
location = /demo.html {
http2_push /style.css;
http2_push /image1.jpg;
http2_push /image2.jpg;
}
}
验证HTTP / 2服务器推送
您可以使用以下两种方法之一轻松验证服务器推送是否有效:
- Web浏览器中的开发人员工具
- 一个命令行的HTTP / 2客户端如
nghttp
使用开发人员工具进行验证(Google Chrome)
以下以Google Chrome为例,说明如何使用Web浏览器中的开发人员工具来验证服务器推送是否有效。在该图中,Chrome开发人员工具的“ 网络”标签上的“ 启动器”列指出,作为/demo.html请求的一部分,有多个资源被推送到客户端。
启动器列表示服务器推送用于发送资源
使用命令行客户端进行验证(nghttp
)
除了Web浏览器工具,您还可以使用nghttp2.org项目中的nghttp
命令行客户端来验证服务器推送是否有效。您可以从GitHub下载命令行客户端,或在可用的位置安装相应的操作系统软件包。对于Ubuntu,请使用该软件包。nghttp
nghttp2-client
在输出中,星号(*)表示服务器推送的资源。
$ nghttp -ans https://example.com/demo.html
id responseEnd requestStart process code size request path
13 +84.25ms +136us 84.11ms 200 492 /demo.html
2 +84.33ms * +84.09ms 246us 200 266 /style.css
4 +261.94ms * +84.12ms 177.83ms 200 40K /image2.jpg
6 +685.95ms * +84.12ms 601.82ms 200 173K /image1.jpg
自动将资源推送给客户
在很多情况下,列出您希望推送到NGINX配置文件中的资源是不方便的,甚至是不可能的。出于这个原因,NGINX也支持拦截Link
预加载头的约定,然后推送这些头中标识的资源。要启用预加载,请http2_push_preload
在配置中包含指令:
server {
# Ensure that HTTP/2 is enabled for the server
listen 443 ssl http2; ssl_certificate ssl/certificate.pem;
ssl_certificate_key ssl/key.pem; root /var/www/html; # Intercept Link header and initiate requested Pushes
location = /myapp {
proxy_pass http://upstream;
http2_push_preload on;
}
}
例如,当NGINX作为代理服务器(用于HTTP,FastCGI或其他流量类型)运行时,上游服务器可以Link
为其响应添加如下标题:
Link: </style.css>; as=style; rel=preload
NGINX拦截这个头并开始服务器推送/style.css。Link
标题中的路径必须是绝对路径 - 不支持像./style.css这样的相对路径。该路径可以选择包含查询字符串。
要推送多个对象,可以提供多个Link
标题,或者更好的是,将所有对象包含在逗号分隔的列表中:
Link: </style.css>; as=style; rel=preload, </favicon.ico>; as=image; rel=preload
如果你不想让NGINX推送一个预先加载的资源,请nopush
在头文件中添加一个参数:
# Resource is not pushed
Link: </nginx.png>; as=image; rel=preload; nopush
当http2_push_preload
启用时,您还可以通过在NGINX配置中设置响应标题来启动预加载服务器推送:
add_header Link "</style.css>; as=style; rel=preload";
有选择地向客户推送资源
HTTP / 2规范没有解决确定是否推送资源的挑战。显然,如果你知道他们可能需要这些资源并且不太可能已经缓存了资源,那么最好只将资源推送给客户端。
一种可能的方法是仅在首次访问该网站时将资源推送给客户。例如,您可以测试会话cookie的存在情况,并Link
有条件地设置标题,以便仅在会话cookie不存在时才预加载资源。
假设客户端运行良好,并在随后的请求中包含cookie,使用以下配置,NGINX每次浏览器会话仅向客户端推送一次资源:
server {
listen 443 ssl http2 default_server; ssl_certificate ssl/certificate.pem;
ssl_certificate_key ssl/key.pem; root /var/www/html;
http2_push_preload on; location = /demo.html {
add_header Set-Cookie "session=1";
add_header Link $resources;
}
} map $http_cookie $resources {
"~*session=1" "";
default "</style.css>; as=style; rel=preload, </image1.jpg>; as=image; rel=preload,
</image2.jpg>; as=style; rel=preload";
}
测量HTTP / 2服务器推送的效果
为了衡量服务器推送的效果,我们创建了一个简单的测试页面/demo.html,它引用了一个单独的样式表/style.css。样式表进一步引用两个图像。我们使用三种不同的配置测试了页面加载时间:
- 连续
GET
小号(无优化) -浏览器加载的资源时,才发现他们被要求 - 预加载提示 - 预加载提示(
Link
标题)包含在第一个响应中以告诉浏览器加载依赖关系 - 服务器推送(仅限HTTP / 2) - 依赖性被先发送到浏览器
测试了三种配置,以测量服务器推送时HTTP / 2的影响
我们使用HTTP,HTTPS或HTTP / 2对每个配置进行了多次测试运行。前两种配置适用于所有三种协议,并且服务器仅推送到HTTP / 2。
该行为是使用Chrome开发人员工具测量的。评估每个配置的最常见行为并对其进行平均,并将时间与链路的RTT(如使用所测量的ping
)相关联以说明每种方法的机械效应。
显示许多往返行程的测试结果是在每种配置下发生的
一些基本观察
- 已加载DOM是启动新连接并检索demo.html页面的时间。样式表是检索CSS资源的时间。
- 通过HTTP建立连接需要1个RTT; 对于HTTPS和HTTP / 2,它需要2个RTT。
- HTML和CSS资源的有效负载小于最大传输单元(MTU)大小,因此
GET
操作在大约1个RTT中完成。
解读结果:预加载提示
- 预加载提示对CSS资源的影响很小,因为它是在HTML资源中直接引用的,并且HTML资源可以快速传递。浏览器在HTML页面交付后立即启动CSS请求。
- 预加载提示确实可以快速开始下载在CSS资源(这里是两个图像)中声明的资源。使用预加载提示时,下载可以更快地启动1 RTT。
- 预加载提示的净节省可以是1 RTT或更多。在并行下载资源时,浏览器必须打开一个或多个其他连接。性能取决于缓慢的请求(较大的响应)是先排定还是延迟,而新的连接是打开的。这种不可预测的请求顺序考虑了HTTP和HTTP / 2的1-RTT加速以及HTTPS的2-RTT加速。
解释结果:服务器推送
- 服务器推进通过进一步的1 RTT改进了预加载提示时间。推送“响应”是在响应第一个请求的同时发起的,而预加载提示响应发生了1个RTT延迟 - 0.5个RTT用于响应第一个请求,另加0.5个RTT用于预加载
GET
请求。
测试笔记
- 每个配置都有多个测试运行。每次运行都从一个空的浏览器缓存开始,并且没有建立与NGINX服务器的保持连接。NGINX指令
keepalive_timeout
并http2_idle_timeout
用于快速关闭保持连接。 - 目前似乎无法将字体资源推送到Chrome,可能是由于已知的复杂情况。Chrome甚至已经推送了一个字体资源的明确请求。
- 注意在每次测试之前明确清除浏览器缓存,并且所有内容都提供了过期的缓存控制标头。
- Chrome缓存预先加载的资源。当您禁用缓存时,这些缓存的资源不会始终被忽略,并且不会通过明确的“清除浏览器缓存”操作得到一致的清除。(在Chrome中,禁用缓存的一种方法是在开发工具网络选项卡上选中禁用缓存复选框。要清除浏览器缓存,可以在打开开发工具并右键单击浏览器刷新按钮并选择清空缓存和硬重新加载) 。
- 一些尝试预加载内容导致Chrome无法成功重新验证缓存副本,然后正常下载资源。这些尝试不计入测量中。
- Chrome为所有使用先前接受的自签名证书的新SSL连接添加了不必要的2-RTT延迟。该测试使用CA签名的Let's Encrypt证书进行,以避免此2-RTT延迟。
- DNS延迟通过编辑本地/ etc / hosts文件解决。
- 这个简单的测试并不试图测量客户端已经拥有资源缓存副本的服务器推送效果。在这种情况下,在每次测试之前,所有高速缓存都已被清除,而且大多数推送都很快取消。
结论
为了突出预加载提示和服务器推送的机制,此测试非常简单。与简单情况下的预装载提示相比,服务器推送改进了1-RTT,与未优化的顺序GET
请求和从属资源的发现相比,服务器推送有了更大的改进。
更实际的用例有更多的变量:多个依赖资源,多个资源,甚至通过推送已经缓存或不需要立即需要的资源来浪费带宽。浏览器不一致还会影响性能。从这个简单的测试你的里程将会有所不同。
例如,Chrome团队已经发布了关于何时部署服务器推送的一些详细建议,并且已经在更复杂的网站上进行了测量,以比较未优化,预加载提示和服务器推送HTTP / 2的影响。对于考虑在生产中部署HTTP / 2服务器推送的人来说,他们的HTTP / 2推送报告的经验法则值得一读。
务实的结论是,如果您可以预先确定需要哪些资源,那么让上游服务器发送预加载提示会带来真正的好处。推动这些资源的额外好处虽然很小但是可以衡量,但可能会导致浪费带宽和延迟所需资源。您应该仔细测试和监控任何服务器推送配置。
附录:HTTP / 2推送如何工作?
以下信息部分基于Jake Archibald的非常详细的HTTP / 2推送研究,比我认为的博客文章更加艰难。
HTTP / 2服务器推送通常用于在客户端请求资源时抢先发送从属资源。例如,如果客户端请求网页,则服务器可能会将相关样式表,字体和图像推送到客户端。
当客户端进行HTTP / 2连接时,服务器可以选择使用连接发起一个或多个推送响应。这些推送发送客户端未明确请求的资源。
客户端可以拒绝推送(通过发送RST_STREAM
帧)或接受推送。客户端将推送的内容存储在与HTTP / 2连接关联的本地“推送缓存”中。
稍后,当客户端使用已建立的HTTP / 2连接请求资源时,它将检查连接的推送缓存,以查看是否已完成或正在传输对请求的响应。它首先使用缓存资源来为资源发出新的HTTP / 2请求。
任何推送的资源都会保留在每个连接推送缓存中,直到(a)它被使用或者(b)HTTP / 2连接关闭:
- 如果使用资源,客户端将获取副本并删除推送缓存中的条目。如果资源可缓存,则客户端可以将其副本缓存在其HTTP页面缓存中。
- 如果因任何原因关闭了HTTP / 2连接,则会删除其本地推送缓存。
这有几个含义:
- 即使推送的内容是新鲜的,浏览器中的HTTP页面缓存中的内容也优先于推送缓存中的内容。
- HTTP / 2连接可以在不同的页面加载中共享。由于一次页面加载而推送的资源可以在不同页面加载请求时使用。
- 具有凭证的请求使用不具有凭证的请求的不同HTTP / 2连接; 例如,如果浏览器为资源发出非凭证请求,则可能无法找到使用跨源请求推送的资源(凭证)。
您可以在Jake Archibald的HTTP / 2推送比我想到的博客文章更加强硬的问题中查看更详细的问题列表。
HTTP / 2服务器推送是一个有趣的功能。确保彻底测试HTTP / 2服务器推送配置,并准备在出现更可预测的缓存感知行为的情况下回退到预加载。
Nginx 学习笔记(十)介绍HTTP / 2服务器推送(译)的更多相关文章
- web前端学习(二)html学习笔记部分(8)--服务器推送事件3
1.2.22 html5服务器推送事件 1.2.22.1 html5服务器推送事件介绍 服务器推送事件(Server-sent Events)是HTML5规范中的一个组成部分,可以用来从服务器端实 ...
- Git学习笔记(SourceTree克隆、提交、推送、拉取等)
学习一下sourcetree使用git 目录 一 克隆Clone 二 提交Commit和推送Push 三 拉取pull和获取fetch 四 版本回退reset 五 检出checkout 六 标签Tag ...
- (转)OpenFire源码学习之十八:IOS离线推送
转:http://blog.csdn.net/huwenfeng_2011/article/details/43458213 IOS离线推送 场景: 如果您有iOS端的APP,在会话聊天的时候,用户登 ...
- SSE技术详解:一种全新的HTML5服务器推送事件技术
前言 一般来说,Web端即时通讯技术因受限于浏览器的设计限制,一直以来实现起来并不容易,主流的Web端即时通讯方案大致有4种:传统Ajax短轮询.Comet技术.WebSocket技术.SSE(Ser ...
- HTML5 服务器推送事件(Server-sent Events)实战开发
转自:http://www.ibm.com/developerworks/cn/web/1307_chengfu_serversentevent/ http://www.ibm.com/develop ...
- HTML5中的SSE(服务器推送技术)
本文原链接:https://cloud.tencent.com/developer/article/1194063 SSE技术详解:一种全新的HTML5服务器推送事件技术 前言 概述 基本介绍 与We ...
- ASP.NET Core Web开发学习笔记-1介绍篇
ASP.NET Core Web开发学习笔记-1介绍篇 给大家说声报歉,从2012年个人情感破裂的那一天,本人的51CTO,CnBlogs,Csdn,QQ,Weboo就再也没有更新过.踏实的生活(曾辞 ...
- nginx 学习笔记(2) nginx新手入门
这篇手册简单介绍了nginx,并提供了一些可以操作的简单的工作.前提是nginx已经被安装到你的服务器上.如果没有安装,请阅读上篇:nginx 学习笔记(1) nginx安装.这篇手册主要内容:1. ...
- Nginx学习笔记4 源码分析
Nginx学习笔记(四) 源码分析 源码分析 在茫茫的源码中,看到了几个好像挺熟悉的名字(socket/UDP/shmem).那就来看看这个文件吧!从简单的开始~~~ src/os/unix/Ngx_ ...
随机推荐
- SpringMVC 拦截器使用说明
spring-content.xml <!-- 配置用于session验证的拦截器 --> <!-- 如果有多个拦截器满足拦截处理的要求,则依据配置的先后顺序来执行 --> & ...
- 【cf789C】Functions again(最大子序列和)
C.Functions again 题意 给你一个数组a[1..n].有一个函数\(f(l,r)=\sum_{i=l}^{r-1}\left| a[i]-a[i+1]\right| (-1)^{l-i ...
- Linux iptables设置
先举例子说明,若服务器网卡: eth0 10.10.0.100 eth0:0 10.10.0.200 eth0:1 10.10.0.201 eth0:2 10.10.0.202 只允许10.10.0. ...
- SpringBoot 从application.yml中通过@Value读取不到属性值
package cn.exrick.xboot.mqtt; import org.eclipse.paho.client.mqttv3.*;import org.eclipse.paho.client ...
- 「FJOI2016」神秘数 解题报告
「FJOI2016」神秘数 这题不sb,我挺sb的... 我连不带区间的都不会哇 考虑给你一个整数集,如何求这个神秘数 这有点像一个01背包,复杂度和值域有关.但是你发现01背包可以求出更多的东西,就 ...
- suoi62 网友跳 (暴搜+dp)
传送门 sbw太神啦orz 首先N<=20可以直接暴搜 然后玄学剪枝可以过18个点 那么N<=40的时候,就把它拆成两半分别暴搜,再用dp拼起来 对于前半段,设f[i][j]是开始高度为i ...
- 【linux】Linux系统SELinux简介
安全加强型Linux(Security-Enhanced Linux)简称 SELinux,它是一个 Linux 内核模块,也是 Linux 的一个安全子系统. 是linux安全加强的另一种实现方式. ...
- mysql5.6更改datadir数据存储目录
环境需求: 有些数据存储场景可能需要将数据放到指定的挂载路径或目录,mysql默认存放数据路径在:/var/lib/mysql下. 测试环境: 操作步骤: 1. 查看当前存储目录 [root@mysq ...
- 工作笔记:/bin/bash^M: 坏的解释器: 没有那个文件或目录 问题解决
问题原因: 由于windows上换行符为CR LF而在Linux下是 LF 导致出现上述问题 解决方案 1. 在windows下 可以使用nodepad打开该shell文件,然后将shell文件中的格 ...
- @transactional注解在什么情况下会失效,为什么。
@transactional注解在什么情况下会失效,为什么. @Transactional的使用: @Transactional public void updateUserAndAccount(St ...