为什么这个 Nginx 设置不缓存响应?

为什么这个 Nginx 设置不缓存响应?

我让 Nginx 位于 前面gunicorn,而 ​​又位于应用程序前面django

核心问题是“为什么我的回复没有被缓存?”然而,我对此还不是很了解,因此以下是我的假设:应该发生(以防我的核心理解有缺陷)。

请求A命中Nginx,例如,请求json来自 REST 服务的一些内容。Nginx 的缓存中没有这些内容,因此它会将其传递给Gunicorn/Django。生成响应,将其传回 Nginx,然后缓存,最后返回到客户端。

然后!

请求B请求相同的资源。Nginx 已将其缓存,因此可直接提供服务,而无需访问 django 应用程序。

基于这个假设并经过大量阅读后,我最终在我的 nginx 配置中得到了这个最小的配置sites-enabled

proxy_cache_path /tmp/nginx keys_zone=one:20m inactive=60m;
proxy_cache_key "$host$request_uri";


server {
    listen 8080;
    server_name localhost;

    proxy_cache one;

    location / {
        add_header X-Proxy-Cache $upstream_cache_status;
        proxy_ignore_headers X-Accel-Expires Expires Cache-Control;
        proxy_pass http://127.0.0.1:8000;
    }
}

此代码基于以下文档nginx 缓存以及教程这里

如果我测试几个请求,我会得到以下响应:

curl -X GET -I http://localhost:8080

HTTP/1.1 200 OK
Server: nginx/1.4.6 (Ubuntu)
Date: Wed, 06 May 2015 01:35:38 GMT
Content-Type: text/html; charset=utf-8
Transfer-Encoding: chunked
Connection: keep-alive
Vary: Cookie
X-Frame-Options: SAMEORIGIN
Set-Cookie: csrftoken=b6UG5X4ZlGwVUYfHSIkq4PKBIxicpWxc; expires=Wed, 04-May-2016 01:35:38 GMT; Max-Age=31449600; Path=/
X-Proxy-Cache: MISS

注意:我认为 cookie 没问题,因为我没有将其包含在cache_key指令中。但我也可能错了。

尽管对同一资源发出了多次请求,但我从未获得缓存命中。此外,proxy_cache_path目录中没有写入任何缓存文件。

有人能告诉我为什么没有缓存任何响应吗?

谢谢!

答案1

尝试缓存包含Set-Cookie标头的实体是一个非常糟糕的主意。这是天生禁止由 nginx 执行,除非proxy_ignore_headers指令中说明。

忽略此标头加上Vary: Cookie回复中的标头将使您的缓存非常无效,因为单一资源将具有与请求它的访问者数量一样多的缓存条目。

还请注意,Vary只有从版本开始,缓存算法才会考虑标头1.7.7。使用以前的 nginx 版本proxy_ignore_headers Set-Cookie;会导致大量 cookie 重复,因为Set-Cookie缓存回复中的标头将被发送回所有命中缓存条目的请求。

答案2

在我看来,问题在于上游服务器没有发送包含到期日期(Expires:)或缓存验证器(例如Last-Modified:)的响应。(cookie 到期时间与缓存无关。)

HTTP 1.1 规范说:

如果响应中没有缓存验证器或明确的过期时间,我们不希望它被缓存,但某些缓存可能会违反此期望(例如,当网络连接很少或没有网络连接时)。

(重点已添加。)

因此,您的 Django 设置似乎未启用缓存。我建议您启用每个站点缓存。如果这样做,Django 将在其响应中生成 Nginx 缓存所需的标头。

另一个选项是使用proxy_cache_validNginx 配置中的选项。我使用了与您的设置类似的设置并复制了您的行为,然后我添加了一个选项proxy_cache_valid any 5m;,告诉 Nginx 将具有任何状态代码 ( ) 的响应缓存any5 分钟5m。一旦我这样做了,我就获得了缓存命中。

相关内容