CDN页面优化不生效排查遇到的坑

简介: 如果源站响应给CDN的数据是Gzip压缩以后的数据会导致CDN的页面优化不生效。本文详细讲述了问题的原因以及排查过程,并讲述了Nginx关于Gzip的压缩配置,同时介绍了CDN作为代理服务,引入了Via header以后对Nginx服务器的影响。

背景描述

阿里云CDN提供了页面优化功能,当开启页面优化功能时,CDN可以自动清除HTML页面冗余的注释和重复的空白符,缩小文件体积,提升页面可阅读性。本案例遇到的一个问题是,按照文档开启了CDN的页面优化功能,但是访问HTML页面实际并没有优化效果。

Gzip压缩引发

在排查测试的过程中,发现直接用curl URL的方式查看响应结果,是已经被页面优化了,但是直接在浏览器上访问HTML却没有被优化。进一步对比curl请求以及浏览器Network下的Request Header以及Response Header,发现浏览器的Request Header带了Accept-Encoding: gzip, deflate,Response Header返回了Content-Encoding: gzip,如下图所示
image.png
image.png

我们知道HTTP协议上的GZIP编码是一种用来改进WEB应用程序性能的技术,大流量的WEB站点常常使用GZIP压缩技术来让用户感受更快的速度。从测试来看,浏览器请求头带了Accept-Encoding: gzip表示浏览器支持解码gzip压缩后的文件,如果服务器支持gzip压缩,那么在收到这个请求头以后,就会返回gzip压缩以后的文件,在Response Header里以Content-Encoding: gzip的形式体现。直接用如下curl命令带Accept-Encoding请求头测试,发现返回结果也是带了gzip的,且页面也是没有优化的。

curl -I 'http://测试URL' -H 'Accept-Encoding: gzip'

综上可以暂时得出结论,返回结果带了Accept-Encoding: gzip以后,CDN的页面压缩不生效,返回结果不带Accept-Encoding: gzip,CDN的页面压缩生效。

Gzip压缩是在哪里发生的

由于请求的链路是:客户端Client -->CDN -->源站
这个Gzip压缩,可能是CDN产生的,也可能是源站产生的。这个比较容易验证,直接用curl命令绑定到源站IP去测试即可得出结论

curl -I 'http://测试URL' -H 'Accept-Encoding: gzip' -x '源站IP:80'

测试来看,返回结果果然带了Accept-Encoding: gzip,说明是源站gzip压缩导致的。产生这个现象的原因逐渐浮出水面,整个过程如下:

当用户在浏览器发起请求时,浏览器默认带了Accept-Encoding: gzip这个请求头,CDN作为一个代理服务器,在回源请求源服务器的时候转发了这个来自真实客户端(浏览器)的请求头,源服务器由于开了Gzip压缩,因此在收到这个请求头以后返回了Gzip压缩以后的内容给CDN,由于CDN不具备Gunzip功能,因此无法对Gzip压缩以后的内容去做页面优化,因此导致了页面优化功能不生效。

Gzip配置参数

以上基本定位问题,但是为了更明确,我搭建了一个基于Nginx的Web服务器用做CDN的源站,并在Nginx的配置文件nginx.conf里开启了Gzip压缩,配置如下图
image.png
但是测试发现,通过CDN访问,并且发了Accept-Encoding: gzip请求头以后,CDN依然可以完成页面压缩,这就比较奇怪。为了定位问题,直接在Web服务器上抓了包,看一下CDN和Web服务器的交互请求,发现一个很奇怪的现象:CDN请求Web服务器的时候转发了Accept-Encoding: gzip,但是Web服务器并没有响应Content-Encoding: gzip,报文如下图:
image.png

根据这个现象,去查了一下Nginx官网对于ngx_http_gzip_module模块的配置说明,可以看到该模块有如下配置参数
image.png

其中有一个gzip_proxied参数引起了注意。这个参数的含义,可以解释如下
语法: gzip_proxied [off|expired|no-cache|no-store|private|no_last_modified|no_etag|auth|any] …
默认值: gzip_proxied off
作用域: http, server, location
Nginx作为反向代理的时候启用,开启或者关闭后端服务器返回的结果,匹配的前提是后端服务器必须要返回包含”Via”的 header头。

off – 对于所有来自代理服务器的请求,都关闭压缩
expired – 如果响应header头中包含 “Expires” 头信息则启用压缩
no-cache – 如果响应header头中包含 “Cache-Control:no-cache” 头信息则启用压缩
no-store – 如果响应header头中包含 “Cache-Control:no-store” 头信息则启用压缩
private – 如果响应header头中包含 “Cache-Control:private” 头信息则启用压缩
no_last_modified – 如果响应header头中不包含 “Last-Modified” 头信息则启用压缩
no_etag – 如果响应header头中不包含 “ETag” 头信息则启用压缩
auth – 如果响应header头中包含 “Authorization” 头信息则启用压缩
any – 无条件启用压缩,也就是对任何来自代理服务器的请求,都返回压缩的内容
image.png

由于Nginx配置里配置了 gzip_proxied expired no-cache no-store private auth
因此相当于启用了gzip_proxied参数,当Web服务器发现来自代理服务器的请求时(在这里就是来自CDN的请求),Web服务器会去校验gzip_proxied参数,当发现服务器的Response Header里没有返回Expires、"Cache-Control:no-cache"等类似响应头时,服务器就返回了不带Gzip压缩的数据。如果Gzip配置模块是按照如下配置的话,那么任何来自代理服务器的请求,服务器都会返回Gzip压缩的内容。

gzip_proxied  any

如何判断请求是来自代理服务器的

那么问题来了,服务器是如何判断这个请求是来自代理服务器的,而不是真实客户端呢。这里就涉及到Via这个HTTP Header了。关于Via的介绍,可以参考HTTP协议关于Via的文档。Via 是一个通用首部,是由代理服务器添加的,适用于正向和反向代理,在请求和响应首部中均可出现。这个消息首部可以用来追踪消息转发情况,防止循环请求,以及识别在请求或响应传递链中消息发送者对于协议的支持能力。在这里,CDN作为代理服务器,去请求源服务器的时候,请求头里会带上Via头(这点在上面的抓包截图里也可以看到),而服务器就是根据请求头里的Via得知该请求是来自上游代理服务器的。

HTTP服务器的问题是知道代理本身是否能够处理压缩响应。传入请求中的接受编码头(也就是Accept-Encoding: gzip)很可能是由原始客户机请求提供的,但这并不能表明它所经过的代理或网关的能力,也就是说,服务器并不知道上游代理服务器能否处理Gzip压缩以后的内容。因此,在此场景中,服务器采用最安全的选项,并选择不压缩它发回的响应,这也是合理的。关于Via这个Header对于Gzip压缩的影响,可以参考这篇Akamai的文章,有详细的介绍。

一个新的想法

既然源站响应了gzip内容会导致CDN的页面优化不生效,那只能源站响应未压缩过的内容,但是这样的话,最终对于客户端来说,请求到的文件没有经过有效压缩,还是会消耗客户端带宽,从而影响Web页面的访问性能。而CDN除了提供页面优化的功能外,还提供了Gzip的功能,那能不能在CDN层面去做页面优化和Gzip压缩呢?

通过测试发现,在CDN开启页面优化的同时,无论是开启Gzip压缩还是Br压缩,只要请求头带了accept-encoding: gzip, deflate, br头,则页面优化不生效。由此可见,在CDN层面,智能压缩的优先级比较高,压缩以后的内容无法页面优化,看来这个方案暂时也不可行。当然,这部分的策略有待产品层面去改良。

总结和解决方案

综上,该问题可以总结如下
(1)如果源站响应了Gzip压缩的内容,CDN会因为无法Gunzip导致页面优化功能不生效
(2)如果希望与CDN去智能压缩和页面优化,因此CDN层面智能压缩的优先级比页面优化的优先级高,也会导致页面优化不生效
(3)如果期望使用CDN的页面优化,那么需要确保源站服务器关闭Gzip压缩。如果源站服务器是Nginx,通过修改Nginx配置文件里ngx_http_gzip_module模块的gzip_proxied参数,设定来自代理服务器的请求,不返回Gzip压缩的内容来实现。
(4)另外还有一种比较实现方案,是可以在CDN层面配置删除Accept-Encoding这个回源HTTP请求头。
image.png

相关实践学习
Serverless极速搭建Hexo博客
本场景介绍如何使用阿里云函数计算服务命令行工具快速搭建一个Hexo博客。
目录
相关文章
|
域名解析 缓存 前端开发
前端性能优化 实际应用cdn 加快静态资源访问
前端性能优化 实际应用cdn 加快静态资源访问
前端性能优化 实际应用cdn 加快静态资源访问
|
23天前
|
CDN
阿里云国际版CDN网页打不开、页面报错该如何解决?
阿里云国际版CDN网页打不开、页面报错该如何解决?
|
21天前
|
存储 JavaScript 安全
vue项目打包优化:缩小体积productionSourceMap设置,使用cdn加速
vue项目打包优化:缩小体积productionSourceMap设置,使用cdn加速
40 0
|
23天前
|
缓存 网络安全 数据安全/隐私保护
使用阿里云国际CDN加速后网站无法访问的排查步骤
使用阿里云国际CDN加速后网站无法访问的排查步骤
|
2月前
|
缓存 监控 负载均衡
在使用CDN时,如何配置缓存规则以优化性能
在使用CDN时,如何配置缓存规则以优化性能
|
6月前
|
域名解析 缓存 负载均衡
【域名解析DNS专栏】域名解析在CDN服务中的应用与优化
【5月更文挑战第30天】本文探讨了域名解析在CDN服务中的重要性,强调其对访问速度和稳定性的影响。文中提出了三种优化方法:使用智能解析以动态选择最佳节点,配置负载均衡保证服务稳定,以及利用DNS缓存提升访问速度。通过Python代码示例展示了基本的DNS解析过程,结论指出优化域名解析对于提升网站性能至关重要。
101 1
|
6月前
|
缓存 监控 UED
CDN(内容分发网络):加速网站加载与优化用户体验
CDN(内容分发网络):加速网站加载与优化用户体验
|
6月前
|
缓存 监控 网络协议
如何利用CDN优化
【4月更文挑战第21天】CDN(内容分发网络)通过在全球部署节点缓存内容,加快用户访问速度和效率。选择适合的CDN服务商,如阿里云、腾讯云,然后配置域名、DNS,并在服务商处上传文件创建节点。优化CDN使用包括设置缓存时间、启用HTTPS、压缩资源及监控性能。注意内容同步与安全问题,确保高效且安全的网站运行。
277 2
|
6月前
|
搜索推荐 机器人 索引
内容分发策略与 SEO 优化指南
内容分发是指通过各种媒介分享、发布或传播内容给受众的过程。这些媒介可以包括不同的渠道,例如社交媒体平台(Facebook、Twitter、LinkedIn、朋友圈、微博、小红书、B 站、抖音、公众号等)、电子邮件新闻稿、博客、播客、网站,甚至杂志和报纸等线下场所。内容分发的性质可以涵盖从博客文章、文章、视频、信息图表到播客的各种内容。内容分发的目的是使您的内容尽可能多地接触到相关受众,提高覆盖面、可见性和参与度。该策略可能涉及有机和付费两种分发方式,通常采用多渠道方法来最大限度地扩大覆盖面。
279 2
|
编解码 缓存 容灾
带你读《多媒体行业质量成本优化及容灾方案白皮书》2. CDN及直播出流量优化方案
带你读《多媒体行业质量成本优化及容灾方案白皮书》2. CDN及直播出流量优化方案
348 0