【问题标题】:NGINX caching upstream server when it shouldn't beNGINX 在不应该缓存上游服务器时
【发布时间】:2020-05-02 05:50:54
【问题描述】:

我想设置一个 NGINX 服务器,它提供以下功能:

  1. 当 NGINX 发出请求以获取位于 /path/to/page 的页面时,它会获取位于 /path/to/page 的页面。
  2. 如果上游服务器关闭或 NGINX 因某种原因无法连接到它,NGINX 会返回页面的缓存版本(如果有)。
  3. 如果缓存文件超过 6 小时,请不要使用它,只需返回 502。
  4. 如果上游服务器可用,从不使用缓存。

我在这里有一个 NGINX 配置,根据我对文档的理解,我认为它应该可以工作,但它没有,我不明白为什么。问题出在第 (4) 点,即使上游服务器在线,这个 NGINX 服务器也会返回文件的缓存版本。

daemon off;
error_log /dev/stdout info;

events {
}

http {
    proxy_cache_path
        "/home/jack/Code/NGINX Caching/Codebase/cache"    # Cache path
        keys_zone=cache:10m # Name of cacahe, max size for keys 10 megabytes
        levels=1:2              # Don't store all cached files in a single directory
        max_size=500m           # Max size of cache
        inactive=6h;            # Cached file deleted if not used within six hours
    proxy_cache_valid 6h;
    proxy_cache_key "$request_method$request_uri";

    access_log /dev/stdout;

    server {
        listen 8080;

        location ~ ^/(.+)$ {
            proxy_pass http://0.0.0.0:8000/$1;
            proxy_cache cache;
            proxy_cache_valid 6h;
            proxy_buffering on;
            proxy_cache_use_stale error timeout;
        }
    }
}

proxy_cache_path 替换为您机器上的目录路径,并在您机器上的 8000 端口上运行另一个网络服务器。当我修改服务器在 8000 端口上提供的文件时,NGINX 直到看到更改我清除缓存。问题出在 NGINX 而不是我的客户端 (Firefox),即使我在浏览器中关闭缓存,NGINX 也会返回 200 和旧文件内容。

【问题讨论】:

    标签: nginx caching


    【解决方案1】:

    您能否检查一下这两个指令是否对您有帮助:

    proxy_cache_revalidate: http://nginx.org/en/docs/http/ngx_http_proxy_module.html#proxy_cache_revalidate

    proxy_cache_use_stale:http://nginx.org/en/docs/http/ngx_http_proxy_module.html#proxy_cache_use_stale

    来自 nginx.conf '17 的在线视频描述了您可以通过缓存实现的所有很酷的事情:https://www.youtube.com/watch?v=xZrOjmAkFC8。也许这也是你感兴趣的。

    【讨论】:

    • 不,不是。
    • 嗨,杰克,我正在我的实验室环境中测试你的场景并告诉你结果。
    • 不用了,我想通了。我误解了 proxy_cache_use_staleproxy_cache_valid 指令的工作原理。
    【解决方案2】:

    所以,我似乎误解了 NGINX 代理缓存指令。文档在这个主题上相当混乱,所以我将逐点列出。

    This official help page 给出了各种指令的一个不错的概述,但是它没有提到一些东西,事实证明这是理解 NGINX 缓存如何工作的一个非常重要的概念构建块:缓存文件的概念是 陈旧

    NGINX 的 默认 行为是始终使用缓存(如果存在),而不是查询上游服务器。有了这个配置,做缓存的最小配置,NGINX 将在第一次访问页面时查询上游服务器,然后永远使用缓存版本:

    events {
    }
    
    http {
        proxy_cache_path
            /path/to/cache
            keys_zone=my_cache:10m;
            proxy_cache_key "$request_method$request_uri";
    
        server {
            listen 8080;
    
            location ~ ^/(.+)$ {
                proxy_pass http://0.0.0.0:8000/$1;
                proxy_cache cache;
            }
        }
    }
    

    您可以使用 proxy_cache_valid 指令告诉 NGINX 缓存文件何时应被视为“陈旧”。例如,如果我们设置proxy_cache_valid 5m,那么在创建缓存文件 5 分钟后,NGINX 将停止为其提供服务,并在下一次请求时再次查询上游服务器。如果上游宕机,NGINX 会返回 502。但是,在这 5 分钟内,即使上游服务器可用,NGINX 仍然会使用缓存,所以这仍然不是我们想要的。

    NGINX 有另一个指令proxy_cache_use_stale,它给出了 NGINX 可以使用缓存文件的条件即使它们是陈旧的。我们可以将它们组合在一起,得到一个缓存页面的服务器,立即(或几乎立即)使它们过时,然后仅在上游关闭时才使用它们:

    events {
    }
    
    http {
        proxy_cache_path
            /path/to/cache
            keys_zone=my_cache:10m;
            proxy_cache_key "$request_method$request_uri";
    
        server {
            listen 8080;
    
            location ~ ^/(.+)$ {
                proxy_pass http://0.0.0.0:8000/$1;
                proxy_cache cache;
                proxy_cache_valid 1s;
                proxy_cache_use_stale error timeout;
            }
        }
    }
    

    这个配置几乎有我们想要的行为,除了如果上游服务器长时间宕机,NGINX 将无限期地继续使用缓存。据我所知,没有办法告诉 NGINX 在给定时间后完全无效/清除缓存文件。通常这就是proxy_cache_valid 的用途,但我们已经将它用于不同的目的,使文件在 1 秒后过时,因此它们在上游关闭时使用。在“陈旧”之后我们需要一些下一个级别,这意味着文件完全无效,但我认为 NGINX 中不存在。

    所以最简单的解决方案就是手动清除缓存。只需删除缓存目录(或其子目录)中上次修改时间超过 6 小时的所有文件,或者您希望到期时间的任何文件就足够了。在 Linux 系统上,您可以每 5 分钟运行一次此脚本,例如:

    find /path/to/cache -type f -mmin +360 -delete
    

    【讨论】:

    • 仅供参考:有一个proxy_cache_purge 指令。但我认为这仅在 nginx plus 中可用。您可以看到我在回答中提到的in the video 的示例。我想这不是比您提到的手动/cron作业查找和删除方式更好的解决方案。
    猜你喜欢
    • 2011-08-13
    • 1970-01-01
    • 1970-01-01
    • 2019-02-27
    • 2017-12-20
    • 2017-07-04
    • 1970-01-01
    • 2022-01-24
    • 2017-03-16
    相关资源
    最近更新 更多