Nginx кеширование символических ссылок

12

У меня есть система развертывания на моем веб-сервере, каждый раз, когда приложение развертывается, оно создает новый каталог с метками времени и символические ссылки «текущие» в новый каталог. Все это работало хорошо и отлично на 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;
    }
}

и вот мой 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;

Я был бы очень признателен, если бы кто-нибудь помог мне с этим, поскольку на данный момент каждое развертывание включает удаление предыдущего развертывания. Система Ubuntu 14.04.5 LTS; PHP 7.1; Nginx nginx / 1.4.6 (Ubuntu)

Auris
источник

Ответы:

22

Встроенные переменные , $realpath_root: абсолютный путь , соответствующий в корневой или псевдониме значения директивы для текущего запроса, со всеми символическими ссылками разрешены к реальным путям

Решение использовать $realpath_rootвместо $document_rootкопировать все вокруг Q / A сайтов и форумов; это на самом деле трудно избежать обнаружения it.Yet, я только видел , что это хорошо объяснил один раз Расмус Лердорф . Стоит поделиться, так как описывает, почему он работает и когда его следует использовать.

Поэтому, когда вы развертываете через что-то вроде Capistrano, которое выполняет обмен символьными ссылками в корне документа, вы хотите, чтобы все новые запросы получали новые файлы, но вы не хотите переворачивать запросы, которые в данный момент выполняются во время развертывания. Что вам действительно нужно для создания надежной среды развертывания, так это чтобы ваш веб-сервер отвечал за это. Веб-сервер - это часть стека, которая понимает, когда начинается новый запрос. Кэш кода операции находится слишком глубоко в стеке, чтобы знать или заботиться об этом.

С nginx это довольно просто. Просто добавьте это в ваш конфиг:

fastcgi_param SCRIPT_FILENAME $realpath_root$fastcgi_script_name;
fastcgi_param DOCUMENT_ROOT $realpath_root;

Это говорит nginx, что realpath разрешает символическую ссылку docroot, что означает, что, насколько известно вашему PHP-приложению, цель символической ссылки, если это настоящий document_root. Теперь, как только запрос запускается, nginx разрешит символическую ссылку в том виде, в каком он находится в этой точке, и на время запроса он будет использовать один и тот же каталог документов, даже если переключение символической ссылки происходит в середине запроса. Это полностью устраняет симптомы, описанные здесь, и это правильный подход. Это не то, что может быть решено на уровне opcache.

У Kanishk Dudeja возникли проблемы с этим, и он добавил полезное замечание: убедитесь, что эти изменения действительно будут в окончательной конфигурации, т.е. после include fastcgi_params;чего они будут отменены.

Эса Йокинен
источник
Привет, это отличный ответ, но если вы заметили в моей конфигурации, у меня есть fastcgi_param DOCUMENT_ROOT $ realpath_root; fastcgi_param SCRIPT_FILENAME $ document_root $ fastcgi_script_name; включается после fastcgi_params, и это на самом деле не помогает. Когда я перезапускаю php-fpm, символические ссылки разрешаются. Означает ли это, что вместо этого у меня проблема с кэшированием php?
Auris
Пересмотреть. У тебя SCRIPT_FILENAMEесть $document_root, нет $realpath_root.
Эса Йокинен
Хм ... но DOCUMENT_ROOTнастроен $realpath_rootтак, как я понимаю, это должно цеплять тянуть значение или я совершенно не прав и DOCUMENT_ROOTне связан с$document_root
Auris
1
Привет, большое спасибо за ваш ответ и ваши объяснения, моя ошибка заключалась в предположении, которое DOCUMENT_ROOTвлияет$document root
Auris
2
Я использую Apache + php-fpm на серверах с этой проблемой, и очистка opcached при развертывании работала для меня, у нас есть сценарий bash для развертывания, а не Capistrano. Я думаю, что это более простое решение, и в любом случае рекомендуется очистить операционную кеш при развертывании. Эса, спасибо за ссылку на комментарий Расмуса, это золото!
Карлос Мафла
3

Из /unix/157022/make-nginx-follow-symlinks вы можете решить проблему, изменив

fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;

в

fastcgi_param SCRIPT_FILENAME $realpath_root$fastcgi_script_name;

(т.е. изменение пути от $document_rootк $realpath_root).

У меня нет доступа к серверу nginx в настоящее время, чтобы подтвердить это (мой домашний сервер в настоящее время подвергается перестройке), но решение, кажется, сотрудничает с https://medium.com/@kanishkdudeja/truly-atomic-deployments -with-nginx-и-php-fpm-aed8a8ac1cd9 .

Пак
источник