题 如何将Nginx设置为缓存反向代理?


我最近听说Nginx已将缓存添加到其反向代理功能中。我环顾四周,但找不到有关它的信息。

我想在Apache / Django前面设置Nginx作为缓存反向代理:为Apache提供一些(但不是全部)动态页面的Nginx代理请求,然后缓存生成的页面并从缓存中提供对这些页面的后续请求。

理想情况下,我想以两种方式使缓存无效:

  1. 在缓存的项目上设置到期日期
  2. 显式使缓存的项无效。例如。如果我的Django后端更新了某些数据,我想告诉Nginx使受影响页面的缓存无效

是否可以设置Nginx来做到这一点?怎么样?


139
2018-06-24 01:35






答案:


我不认为有一种方法可以明确地使缓存的项目无效,但这里有一个如何完成其​​余工作的示例。 更新: 正如Piotr在另一个答案中提到的,有一个 缓存清除模块 你可以使用。您还可以使用nginx的proxy_cache_bypass强制刷新缓存的项目 - 请参阅 Cherian的回答 欲获得更多信息。

在此配置中,将从example.net检索未存储的项目并进行存储。缓存版本将提供给未来的客户端,直到它们不再有效(60分钟)。

您的Cache-Control和Expires HTTP标头将受到尊重,因此如果您想明确设置过期日期,您可以通过在您要代理的任何内容中设置正确的标头来实现。

您可以调整许多参数 - 有关所有这些的详细信息,请参阅nginx代理模块文档,包括有关不同设置/参数含义的详细信息: http://nginx.org/r/proxy_cache_path

http {
  proxy_cache_path  /var/www/cache levels=1:2 keys_zone=my-cache:8m max_size=1000m inactive=600m;
  proxy_temp_path /var/www/cache/tmp; 


  server {
    location / {
      proxy_pass http://example.net;
      proxy_cache my-cache;
      proxy_cache_valid  200 302  60m;
      proxy_cache_valid  404      1m;
    }
  }
}

94
2017-09-23 20:01



对于没有20k / req / s的新应用,这是合理的第一步。 - Barry
@Barry什么是第二个steP? - Jürgen Paul
@Legit - 我不知道,但传统上最后一步是“利润”:-) - Stephen C
可悲的是,它不适用于nginx 1.11。自上次更新大约3年前,看起来这已不再是解决方案。 - izogfif


你可以具体 使缓存无效 通过页面

proxy_cache_bypass       

假设您要缓存页面,请以这种方式设置缓存

location = /pageid {
  proxy_pass http://localhost:82;
  proxy_set_header   Host             $host;
  proxy_set_header   X-Real-IP        $remote_addr;
  proxy_set_header   X-Forwarded-For  $proxy_add_x_forwarded_for;
  proxy_ignore_headers Set-Cookie; 
  proxy_ignore_headers Cache-Control; 
  proxy_cache_bypass        $http_secret_header;
  add_header X-Cache-Status $upstream_cache_status;
}

现在,当你想要的时候 使该页面无效并再次缓存 

用标题做一个秘密的卷曲调用

curl "www.site.com/pageid" -s -I -H "secret_header:true" 

它将使其无效并缓存它。

来自nginx 0.7。

作为一个额外的奖励 add_header X-Cache-Status 可用于检查页面是否来自缓存。


46
2017-11-26 04:00



这只能在新页面可缓存时更新缓存页面。如果您已删除页面(404或其他错误现在由后端提供),则页面现在发送Set-Cookie或“Content-Control:private”标头,缓存的内容将不会“无效”。 - rbu


我建议你给  一试。 Varnish专门设计为反向代理缓存。它将支持您从源服务器发送的所有缓存控制头,这满足您的第一个请求。

对于您的第二个请求,显式失效。我强烈建议通过重命名文件或使用某种形式的查询字符串缓存区块来更改要使其无效的资源的URL名称。清漆确实有 PURGE 将从Varnish的缓存中删除资源的操作,但它不会让您控制您和用户之间的任何其他缓存。正如您所说,您希望显式清除资源,那么标准的http控件头将无法帮助您。在这种情况下,打败资源缓存最简单的方法是重命名它。


36
2018-06-24 02:43



你能解释一下“重命名文件或使用某种形式的查询字符串缓存破坏者”是什么意思吗?我不确定我理解为什么使用像PURGE这样的操作不是一个好主意。 - Continuation
清漆+1。使用正确的工具来完成工作总是好得多。 - Tom O'Connor
@below:在性能和多功能性领域几乎没有希望触摸清漆。这得到了一位领先的FreeBSD内核开发人员和一支位于欧洲的专业团队的支持。 Varnish正在twitter,heroku和更多产品中生产。 - Barry
cache-buster最简单的例子是将查询字符串中的版本号附加到静态资源,因此style.css成为style.css?123。当你想推送新版本的文件时,你将资源的url更改为style.css?124,现在缓存将把它作为一个全新的资产来单独缓存。 Apache将为文件style.css提供附加的任何查询字符串,因此不需要对实际文件进行任何更改。 - chmac
如果可能的话,最好将缓存破坏者放入文件名本身,例如 style.v123.css 因为某些缓存不会缓存具有查询字符串的请求。 - Noah McIlraith


为了使所选页面无效,你可以使用nginx-0.8.x的“cache_purge”补丁,它可以实现你想要的;)

它可用 这里


7
2017-11-17 07:38





大多数缓存工具(Citrix)允许强制刷新(Ctrl + r)重新填充缓存页面。

这是我发现在nginx中做类似事情的技巧。

server  {
        # Other settings
        proxy_pass_header       Set-Cookie; # I want to cache logged-in users
        proxy_ignore_headers    X-Accel-Redirect;
        proxy_ignore_headers    X-Accel-Expires Expires Cache-Control;
        if ($http_cache_control ~ "max-age=0") {set $eac 1;}
        proxy_cache_bypass $eac;
}

这假设当您在浏览器中执行Ctrl + r时,Cache-Control标头的请求中的max-age = 0。我知道Chrome会这样做,但我没有在其他浏览器中尝试过。通过添加更多if语句来添加更多的头字段可以很容易 $eac 变量为1。


6
2018-04-10 23:02





缓存在nginx中是一个非常新的功能(现在还没有很好的记录),但是足够稳定以便在生产中使用。


4
2018-06-24 02:25





我相信 NginxHttpProxyModule 能够解决http请求。查找从以下开始的指令:

proxy_cache

是的,可以通过以下指令控制缓存行为:

proxy_cache_valid

3
2018-06-24 10:12





基于你无法找到文档的事实,我对在生产中依赖它有点谨慎。你考虑过清漆了吗?这是我的“反向代理的nginx”,体积小,重量轻,做一份工作并做得很好。


2
2018-06-24 01:38



文档在这里: wiki.nginx.org/NginxHttpProxyModule#proxy_cache - rmalayter