【问题标题】:Purging nginx cache files does not always work清除 nginx 缓存文件并不总是有效
【发布时间】:2015-09-23 05:13:42
【问题描述】:

我运行一个 nginx 服务器 + PHP webservices API。我使用 nginx 的 fastcgi_cache 来缓存所有 GET 请求,当某些资源更新时,我会清除一个或多个相关的缓存资源。

我用来执行此操作的方法是计算我要清除的每个资源的 nginx 缓存文件名,然后删除该文件。在大多数情况下,这很有效。

但是我发现有时候,即使缓存文件被删除后,nginx 还是会从缓存中返回数据。

选择要删除的正确缓存文件不是问题——作为我测试的一部分,我已经删除了整个缓存目录,而 nginx 仍然返回 HIT 响应

有人知道为什么会发生这种情况吗?是否可能涉及另一个缓存?例如,可能是操作系统正在将缓存文件的缓存版本返回给 nginx,因此 nginx 不知道它已被删除?

我在 CentOS 上运行它,并使用这个 nginx 配置(减去不相关部分):

user nginx;

# Let nginx figure out the best value
worker_processes auto;

events {
    worker_connections  10240;
    multi_accept        on;
    use                 epoll;
}

# Maximum number of open files should be at least worker_connections * 2
worker_rlimit_nofile 40960;

# Enable regex JIT compiler
pcre_jit on;

http {

    # TCP optimisation
    sendfile        on;
    tcp_nodelay     on;
    tcp_nopush      on;

    # Configure keep alive
    keepalive_requests  1000;
    keepalive_timeout   120s 120s;

    # Configure SPDY
    spdy_headers_comp 2;

    # Configure global PHP cache
    fastcgi_cache_path /var/nginx/cache levels=1:2 keys_zone=xxx:100m inactive=24h;

    # Enable open file caching
    open_file_cache max=10000 inactive=120s;
    open_file_cache_valid 120s;
    open_file_cache_min_uses 5;
    open_file_cache_errors off;

    server {
        server_name xxx;
        listen 8080;

        # Send all dynamic content requests to the main app handler
        if (!-f $document_root$uri) {

            rewrite ^/(.+)    /index.php/$1         last;
            rewrite ^/        /index.php            last;
        }

        # Proxy PHP requests to php-fpm
        location ~ [^/]\.php(/|$) {

            # Enable caching
            fastcgi_cache xxx;

            # Only cache GET and HEAD responses
            fastcgi_cache_methods GET HEAD;

            # Caching is off by default, an can only be enabled using Cache-Control response headers
            fastcgi_cache_valid 0;

            # Allow only one identical request to be forwarded (others will get a stale response)
            fastcgi_cache_lock on;

            # Define conditions for which stale content will be returned
            fastcgi_cache_use_stale error timeout invalid_header updating http_500 http_503;

            # Define cache key to uniquely identify cached objects
            fastcgi_cache_key "$scheme$request_method$host$request_uri";

            # Add a header to response to indicate cache results
            add_header X-Cache $upstream_cache_status;

            # Configure standard server parameters
            fastcgi_split_path_info ^(.+\.php)(/.+)$;
            include fastcgi_params;

            # php-fpm config
            fastcgi_param SCRIPT_URL        $fastcgi_path_info;
            fastcgi_param PATH_INFO         $fastcgi_path_info;
            fastcgi_param SCRIPT_FILENAME   $document_root$fastcgi_script_name;
            fastcgi_param REQUEST_SCHEME    $scheme;
            fastcgi_param REMOTE_USER       $remote_user;

            # Read buffer sizes
            fastcgi_buffer_size 128k;
            fastcgi_buffers 256 16k;
            fastcgi_busy_buffers_size 256k;
            fastcgi_temp_file_write_size 256k;

            # Keep connection open to enable keep-alive
            fastcgi_keep_conn on;

            # Proxy to PHP
            fastcgi_pass unix:/var/run/php-fpm/fpm.sock;
        }
    }
}

现在我看到了,open_file_cache 参数会影响缓存文件吗?

有什么想法吗?

【问题讨论】:

  • 仔细想想,这其实是一个很好的问题。 :-)

标签: caching nginx reverse-proxy purge


【解决方案1】:

不,操作系统不缓存文件。

但是,发生这种情况的原因是文件实际上并没有完全删除,直到链接计数和打开文件的进程数都降为零。

unlink(2) manual page 记录了rm 等工具使用的system call,内容如下:

unlink() 函数将路径命名的链接从其目录中删除,并减少链接所引用文件的链接计数。如果该减量将文件的链接计数减少到零,并且没有进程打开该文件,则与该文件关联的所有资源都将被回收。如果在删除最后一个链接时有一个或多个进程打开了文件,则链接会被删除,但文件的删除会延迟到对它的所有引用都已关闭。

根据系统的不同,您实际上仍然可以完全恢复此类打开的文件而不会丢失任何数据,例如,请参阅https://unix.stackexchange.com/questions/61820/how-can-i-access-a-deleted-open-file-on-linux-output-of-a-running-crontab-task

因此,确实,open_file_cache 将有效地阻止您的删除对在其缓存中仍具有相关文件描述符的进程产生任何影响。如果删除后的紧急清除对您非常重要,您可能需要使用较短的 open_file_cache_valid

【讨论】:

  • @10us,我不这么认为;就文件名而言,文件通常仍会被删除;如果rm 不处理打开的文件,mv 也不会。
猜你喜欢
  • 2013-04-13
  • 2011-09-08
  • 1970-01-01
  • 2012-08-21
  • 2016-08-01
  • 1970-01-01
  • 2021-07-07
  • 2017-08-18
  • 2011-12-07
相关资源
最近更新 更多