![告诉 Nginx 不要根据上游的响应头进行缓存](https://linux22.com/image/791977/%E5%91%8A%E8%AF%89%20Nginx%20%E4%B8%8D%E8%A6%81%E6%A0%B9%E6%8D%AE%E4%B8%8A%E6%B8%B8%E7%9A%84%E5%93%8D%E5%BA%94%E5%A4%B4%E8%BF%9B%E8%A1%8C%E7%BC%93%E5%AD%98.png)
我正在使用 Nginx 来服务 MediaWiki,并且使用 FastCGI 缓存来避免不必要的 PHP 调用。
(在 MediaWikiLocalSettings.php
文件中,我有$wgUseCdn = true
;而在 Nginx 配置中,我使用fastcgi_cache
和相关的配置选项。)
问题是,MediaWiki/PHP(又称上游)的许多 HTTP 响应都包含Vary
标头User-Agent
。由于用户代理字符串非常详细且变化多端,这可能会使 Nginx 不必要地缓存大量相同页面的副本,并且很少向新访问者提供缓存版本。
我可以为 Nginx FCGI 缓存提供整整 12 GiB 的空间,并且它会将其全部填满,但我怀疑由于这个问题它大部分都是垃圾,并且只有一小部分缓存内容实际上是有用的。
我想告诉 Nginx FastCGI 缓存不是Vary
如果从 MediaWiki PHP 代码发回的响应头包含,则缓存响应User-Agent
。
(PHP 发回的许多资源也不会根据用户代理而变化,并且 Nginx 仍然可以缓存这些资源。)
我尝试了以下方法,但似乎不起作用:
# In the http context:
map $sent_http_vary $fcgi_nocache {
default 0;
"~*user-agent" 1;
}
# In a location *.php context:
add-header X-Fcgi-Nocache $fcgi_nocache;
# Or, if it worked fine, to actually make the nocache take effect:
fastcgi_no_cache $fcgi_nocache;
这使我能够检查X-Fcgi-Nocache
HTTP 客户端(例如 Web 浏览器)收到的标头,以查看指令是否map
执行了我想要的操作,但值始终不变,0
所以我猜$sent_http_vary
变量没有按照我希望的方式工作。
有什么办法可以让它工作吗?
答案1
我不知道之前我做错了什么,但突然它就正常工作了。也许我输入的是"*~user-agent"
,"~*user-agent"
或者可能是类似的愚蠢的拼写错误,但目前它似乎按预期工作。
话虽如此,根据#nginx
Libera 的 IRC 频道中某人的建议,我现在也将其更改为使用变量$upstream_http_vary
而不是。这可能更可靠,尽管它似乎也$sent_http_vary
适用于变体。$sent_xyz
另外,我注意到 MediaWiki 要么Vary
根本没有指定标题,要么指定了包含的标题User-Agent
,因此实际上不需要该map
指令,尽管知道有这种可能性是件好事。
简而言之,简单的解决方案:
# In location context, where fastcgi_pass and fastcgi_cache are specified:
fastcgi_no_cache $upstream_http_vary;
如果需要,可以采用更精细的解决方案,例如检查Vary
标题User-Agent
:
# In http context, where fastcgi_cache_path is specified:
map $upstream_http_vary $fcgi_nocache {
default 0;
"~*user-agent" 1;
}
# In location context, where fastcgi_pass and fastcgi_cache specified:
fastcgi_no_cache $fcgi_nocache;