Nginx 缓存符号链接

Aur*_*ris 14 nginx cache php-fpm php7

我的 Web 服务器上有一个部署系统,每次部署应用程序时,它都会创建一个新的带时间戳的目录,并将“当前”符号链接到新目录。这一切在 apache 上都运行良好,但在我设置的新 nginx 服务器上,看起来正在运行来自“旧”部署的脚本而不是新的符号链接脚本。

我已经阅读了一些关于如何解决这个问题的教程和帖子,但没有太多信息,似乎没有任何效果。这是我的 vhost 文件:

server {
    listen 80;

    server_name ~^(www\.)?(?<sname>.+?).testing.domain.com$;
    root /var/www/$sname/current/public;
    index index.html index.htm index.php;

    location / {
        try_files $uri $uri/ /index.php$is_args$args;
    }

    location ~* \.(jpg|jpeg|gif|png|bmp|ico|pdf|flv|swf|exe|html|htm|txt|css|js) {
        add_header        Cache-Control public;
        add_header        Cache-Control must-revalidate;
        expires           7d;
    }

    location ~ \.php$ {
        #fastcgi_split_path_info ^(.+\.php)(/.+)$;
        fastcgi_pass unix:/var/run/php/php7.1-fpm.sock;
        include fastcgi_params;
        fastcgi_param DOCUMENT_ROOT $realpath_root;
        fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
        fastcgi_index index.php;
    }

    location ~ /\.ht {
        deny all;
    }
}
Run Code Online (Sandbox Code Playgroud)

这是我的 fastcgi_params:

fastcgi_param   SCRIPT_FILENAME         $document_root$fastcgi_script_name;
fastcgi_param   QUERY_STRING        $query_string;
fastcgi_param   REQUEST_METHOD      $request_method;
fastcgi_param   CONTENT_TYPE        $content_type;
fastcgi_param   CONTENT_LENGTH      $content_length;

fastcgi_param   SCRIPT_NAME     $fastcgi_script_name;
fastcgi_param   REQUEST_URI     $request_uri;
fastcgi_param   DOCUMENT_URI        $document_uri;
fastcgi_param   DOCUMENT_ROOT           $realpath_root;
fastcgi_param   SERVER_PROTOCOL     $server_protocol;

fastcgi_param   GATEWAY_INTERFACE   CGI/1.1;
fastcgi_param   SERVER_SOFTWARE     nginx/$nginx_version;

fastcgi_param   REMOTE_ADDR     $remote_addr;
fastcgi_param   REMOTE_PORT     $remote_port;
fastcgi_param   SERVER_ADDR     $server_addr;
fastcgi_param   SERVER_PORT     $server_port;
fastcgi_param   SERVER_NAME     $server_name;

fastcgi_param   HTTPS           $https if_not_empty;

# PHP only, required if PHP was built with --enable-force-cgi-redirect
fastcgi_param   REDIRECT_STATUS     200;
fastcgi_param PATH_TRANSLATED $document_root$fastcgi_script_name;
Run Code Online (Sandbox Code Playgroud)

如果有人能帮我解决这个问题,我将不胜感激,因为目前每个部署都涉及删除以前的部署。系统为 Ubuntu 14.04.5 LTS ;PHP 7.1 ; Nginx nginx/1.4.6 (Ubuntu)

Esa*_*nen 25

Embedded Variables , $realpath_root: 与当前请求的rootalias指令值对应的绝对路径名,所有符号链接都解析为真实路径

使用$realpath_root而不是的解决方案$document_root是在问答网站和论坛中复制粘贴;实际上很难避免找到它。然而,我只看过一次Rasmus Lerdorf对它进行了很好的解释。值得分享,因为它描述它的工作原理以及何时应该使用它。

因此,当您通过 Capistrano 之类的东西进行部署时,它会在文档根目录上进行符号链接交换,您希望所有新请求都能获取新文件,但您不想在部署发生时搞砸当前正在执行的请求。创建健壮的部署环境真正需要的是让您的 Web 服务器负责这一点。Web 服务器是理解新请求何时开始的堆栈部分。操作码缓存在堆栈中太深而无法了解或关心它。

使用 nginx 这很简单。只需将此添加到您的配置中:

fastcgi_param SCRIPT_FILENAME $realpath_root$fastcgi_script_name;
fastcgi_param DOCUMENT_ROOT $realpath_root;
Run Code Online (Sandbox Code Playgroud)

这告诉 nginx 以 realpath 解析 docroot 符号链接,这意味着据您的 PHP 应用程序所知,符号链接的目标是真正的 document_root。现在,一旦请求开始,nginx 将解析当时的符号链接,并且在请求期间它将使用相同的 docroot 目录,即使符号链接切换发生在请求中。这完全消除了这里描述的症状,这是正确的方法。这不是在 opcache 级别可以解决的。

Kanishk Dudeja 对此有问题,并添加了一个有用的通知:确保这些更改实际上处于最终配置中,即在include fastcgi_params;此之后以其他方式覆盖它们。

  • 我在有这个问题的服务器上使用 Apache + php-fpm 并且在部署时清除 opcached 对我有用,但我们有一个用于部署的 bash 脚本而不是 Capistrano。我认为这是一个更简单的解决方案,无论如何在部署时清除您的 opcache 是一个很好的做法。Esa 感谢 Rasmus 评论的链接,那是黄金! (2认同)