我使用 Nginx 服务器,它充当我的 Apache 原始服务器的缓存/反向代理。
我很难调试MISS
当我发现这是因为响应头时,缓存率很高Vary: Accept-Encoding
,不同的 www 客户端Accept-Encoding
都无法获取HIT
,即使另一个客户端先前请求了完全相同的 url。
可以通过添加 nginx 配置来解决此问题:
proxy_ignore_headers Vary;
此后,我收到了HIT
缓存回复。
A)这是否会禁用不同的缓存页面变体只是在我的缓存服务器和原始服务器之间?(例如,使用起来很安全)
b)或者它是否为所有最终客户端缓存一个版本(gzip 或非 gzip 文件),而不管客户端的编码/解码功能如何?我认为这可能会导致不支持 gzip 的客户端收到 gzip 文件?
即使通过上述指令改进/修复了缓存,最终客户端仍然会收到Vary: Accept-Encoding
,它可以被隐藏proxy_hide_header Vary
,但我应该这样做吗?
答案1
我对这个主题做了一些调查。我想我在 Yichun Zhang(OpenResty nginx fork 的作者)的 GitHub 讨论中找到了一些有价值的信息回复:
我建议以下选项:
- 缓存压缩和未压缩的响应,并将 Accept-Encoding 的(规范化)值添加到缓存键。这样,不期望 gzip 响应的客户端将导致缓存未命中(并触发缓存未压缩版本)。
- 缓存压缩的响应并使用标准 ngx_gunzip 模块为不接受 gzip 编码的客户端解压响应主体:。请参阅http://nginx.org/en/docs/http/ngx_http_gunzip_module.html但是您需要注意 nginx 输出过滤器的顺序(ngx_srcache 的过滤器和 ngx_gunzip 的过滤器之间)。
- 仅缓存未压缩的内容,并依靠 ngx_gzip 模块为需要 gzip 的客户端压缩数据。设置 proxy_set_header Accept-Encoding '';例如,如果使用代理模块作为内容处理程序。
因此,它看起来并不安全,您应该缓存两个(压缩和非压缩)回复。
但是如果您收到多个带有以下Accept-Encoding
标头的请求,会发生什么情况:
Accept-Encoding: gzip
Accept-Encoding: gzip, br
Accept-Encoding: gzip;q=0.8, br;q=0.9
Accept-Encoding: gzip, deflate, br
这是否意味着每个响应都将单独缓存?我还不知道,这需要比我之前做的更广泛的测试。到目前为止我发现:
- nginx 不会对
Accept-Encoding: deflate
deflated 响应做出响应(与 gzip 压缩的响应只有一点点不同)。 - nginx 不尊重 header 的权重 qvalue 部分。它将对带有
Accept-Encoding: identity;q=0.8, gzip;q=0.5
header 的请求进行压缩响应。如果您有ngx_brotly
Accept-Encoding
模块安装后,如果您的请求标头包含br
压缩方法,无论为压缩方法指定了什么权重,nginx 将始终以 brotly 压缩的响应进行响应。
Yichun Zhang 提到了将 Accept-Encoding 的(规范化)值添加到缓存键。这可以是这样的
map $http_accept_encoding $encoding_key {
~[\s:,]br(?:[\s,\;]|$) 2; # brotli
~[\s:,]gzip(?:[\s,\;]|$) 1; # gzip
default 0; # uncompressed
}
如果不使用ngx_brotly
模块,事情可以简化:
if ($http_accept_encoding ~ "[\s:,]gzip(?:[\s,;]|$)") {
set $encoding_key 1;
}
之后,$encoding_key
向表达式中添加变量proxy_cache_key
就可以解决问题,但正如我已经说过的,这需要更广泛的测试。