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


143

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

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

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

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

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


未经测试,但来自gumroad.com/l/ngx_purge:“ ngx_purge是Nginx的纯Lua模块,允许用户从nginx缓存中清除对象。”
Jaime Hablutzel

Answers:


97

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

7
对于没有20k / req / s的新应用,这是合理的第一步。

5
@Barry第二个步骤是什么?
尔根·保罗

42
@Legit-我不知道,但是传统上最后一步是“ Profit” :-)
Stephen C

可悲的是,它不适用于nginx 1.11。由于上一次更新大约是3年前,因此看来这不再是解决方案。
izogfif

这是什么inactive=600m意思?不是inactive应该时间吗?`[inactive=time]
NeverEndingQueue '18

47

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

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呼叫

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

它将无效并缓存它。

从nginx 0.7开始工作。

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


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

36

我建议您尝试一下Varnish。Varnish特别设计为反向代理缓存。它将满足您从原始服务器发送的所有缓存控制标头,这些标头可以满足您的第一个请求。

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


您能否解释一下“重新命名文件或使用某种形式的查询字符串缓存破坏程序”是什么意思?我不确定我是否理解为什么使用像PURGE这样的操作不是一个好主意。
延续

5
+1清漆。在工作中使用正确的工具总是总好得多。
汤姆·奥康纳

4
@以下:在性能和多功能性领域几乎没有希望接触清漆。这由FreeBSD领先的内核开发人员之一和欧洲的专门团队支持。Twitter,heroku等公司正在生产Varnish。

2
缓存破坏器的最简单示例是将查询字符串中的版本号附加到静态资源,因此style.css变为style.css?123。当您要推送文件的新版本时,请将资源的URL更改为style.css?124,现在,缓存会将其拾取为全新资源,以单独缓存。Apache将在文件style.css中附加任何查询字符串,因此不需要更改实际文件。
chmac 2012年

3
如果可能的话,最好将缓存破坏style.v123.css符放入文件名本身,例如,因为某些缓存不会缓存具有查询字符串的请求。
Noah McIlraith,2012年

8

为了使选定的页面无效,您可以为nginx-0.8.x使用“ cache_purge”补丁,它确实可以满足您的要求;)

在这里可用。


8

大多数缓存工具(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可以做到这一点,但是我没有在其他浏览器中尝试过。只需添加更多将$eac变量设置为1的if语句,即可添加更多的标头字段很容易。



4

我相信NginxHttpProxyModule能够缓存HTTP请求。查找以以下内容开头的指令:

proxy_cache

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

proxy_cache_valid


2

如果在应用程序上使用eTag并将nginx放在它的前面,则它将为您处理到期时间,因为如果eTag更改,它将使缓存无效。


真?好像ngnix与etag匹配,并且从不与应用程序对话以查找是否有更新的etag。
John Naegle 2013年

2

您可以使用多个指令/参数来控制Nginx的缓存过期:

  • proxy_cache_valid 200 302 10m;
  • 在下面添加HTTP标头之一(优先级很重要-请查看我的博客文章):
    • Expires
    • Cache-Control
    • X-Accel-Expires
  • inactive参数的proxy_cache_path指令:

    proxy_cache_path /data/nginx/cache keys_zone=one:10m inactive=60m;

如果您想了解有关Nginx缓存的更多信息,我推荐我的博客文章

清除主题确实很有趣,因为此功能仅在Nginx Plus(Nginx的商业版)中存在。我真的很喜欢@ randy-wallace的答案。但是还有其他可能性,例如ngx_cache_purge模块

您可以做的最简单的事情是手动删除缓存的文件:

  • 生成您的哈希密钥:

    echo -n ‘httpczerasz.com/time.php’ | md5sum
    
  • 从文件系统中删除文件:

    rm /data/nginx/cache/1/27/2bba799df783554d8402137ca199a271
    

1

对于未来的访问者:同时,nginx反向代理已集成了缓存,并且可以从以下位置获得文档:

语法:proxy_cache区域| 关

默认值:proxy_cache off;

上下文:http,服务器,位置

定义用于缓存的共享内存区域。同一区域可以在多个地方使用。参数值可以包含变量(1.7.9)。off参数禁用从先前配置级别继承的缓存。


嗨,塔里克(Tarik),这个问题非常具体地说明了需要实现的目标,这超出了“仅启用缓存”的范围。
asdmin

0
fastcgi_cache_path / opt / nginx缓存级别= 2:2 keys_zone = img:50m;

    位置/ img / {
        fastcgi_pass $ backend;
        包括fcgi_params;
        fastcgi_intercept_errors关闭;   
        fastcgi_cache_key $ server_addr $ request_uri;       
        fastcgi_cache img;
        fastcgi_cache_valid 1m;
        fastcgi_hide_header Set-Cookie;
    }

这将为/ img /位置创建缓存。它在/ opt / nginx-cache中。对象被缓存1分钟。

您可以编写其他任何形式的响应代码。

现在,您无法使所选页面的缓存无效。也许在0.8.x中是可能的。


最初的问题是关于在Apache前面使用nginx,而不是在nginx处理的fastcgi应用程序前面使用。
格雷厄姆·邓普尔顿2009年

0

有一个名为ncache的nginx插件,该插件声称是“基于nginx Web服务器的Web缓存系统。比squid更快,更高效。”

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.