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

Con*_*ion 149 nginx proxy varnish reverse-proxy

我最近听说 Nginx 为其反向代理功能添加了缓存。我环顾四周,但找不到太多关于它的信息。

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

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

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

是否可以设置 Nginx 来做到这一点?如何?

out*_*sed 99

我不认为有一种方法可以显式地使缓存的项目无效,但这里有一个示例,说明如何执行其余操作。更新:正如 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;
    }
  }
}
Run Code Online (Sandbox Code Playgroud)

  • @Legit - 我不知道,但传统上最后一步是“利润”:-) (44认同)
  • 对于没有 20k/req/s 的新应用程序来说,这是合理的第一步。 (7认同)
  • @Barry 第二个步骤是什么? (5认同)

Che*_*ian 48

您可以专门通过以下方式使缓存页面无效

proxy_cache_bypass       
Run Code Online (Sandbox Code Playgroud)

假设你想缓存一个页面,这样设置缓存

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;
}
Run Code Online (Sandbox Code Playgroud)

现在,当您想让该页面无效并再次缓存时

使用标题进行秘密卷曲调用

curl "www.site.com/pageid" -s -I -H "secret_header:true" 
Run Code Online (Sandbox Code Playgroud)

它会使它失效并缓存它。

从 nginx 0.7 开始工作。

作为一个额外的好处,add_header X-Cache-Status可以用来检查页面是否来自缓存。


Dav*_*ney 38

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

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

  • +1 用于清漆。为工作使用正确的工具总是要好得多。 (5认同)
  • @below:在性能和多功能性领域几乎没有希望触及清漆。这得到了一位领先的 FreeBSD 内核开发人员和一个位于欧洲的专门团队的支持。Varnish 正在 twitter、heroku 等平台上生产。 (4认同)
  • 如果可能,最好将缓存破坏者放入文件名本身,例如`style.v123.css`,因为某些缓存不会缓存具有查询字符串的请求。 (3认同)
  • 缓存破坏器的最简单示例是将查询字符串中的版本号附加到静态资源,因此 style.css 变为 style.css?123。当您想要推送文件的新版本时,您将资源的 url 更改为 style.css?124,现在缓存会将其作为一个全新的资产来单独缓存。Apache 将提供带有任何查询字符串的文件 style.css,因此不需要更改实际文件。 (2认同)

小智 10

大多数缓存工具 (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;
}
Run Code Online (Sandbox Code Playgroud)

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


小智 8

为了使选定的页面无效,您可以使用 nginx-0.8.x 的“cache_purge”补丁,这正是您想要的;)

它可以在这里找到


Sav*_*btz 5

缓存是 nginx 中相当新的功能(目前还没有很好的文档),但足够稳定,可以在生产中使用。