Links simbólicos de cache do Nginx

12

Eu tenho um sistema de implantação no meu servidor Web, toda vez que um aplicativo é implantado, ele cria um novo diretório com registro de data e hora e os links simbólicos "atuais" para o novo diretório. Tudo funcionou muito bem no apache, mas no novo servidor nginx que eu configurei, parece que um script da implantação "antiga" está sendo executado em vez do novo link simbólico.

Eu li alguns tutoriais e posts sobre como resolver isso, mas não há muita informação e nada parece funcionar. Aqui está o meu arquivo 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;
    }
}

e aqui está o meu 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;

Eu realmente apreciaria se alguém pudesse me ajudar com isso, pois no momento toda implantação envolve a exclusão da implantação anterior. O sistema é o Ubuntu 14.04.5 LTS; PHP 7.1; Nginx nginx / 1.4.6 (Ubuntu)

Auris
fonte

Respostas:

22

Variáveis embutidos , $realpath_root: um caminho absoluto correspondente à raiz ou apelido valor da directiva para a solicitação atual, com todos os links simbólicos resolveram caminhos reais

A solução de usar em $realpath_rootvez de $document_rooté copiada e colada em todos os sites e fóruns de perguntas e respostas; é realmente difícil evitar encontrá-lo. No entanto, só o vi bem explicado uma vez por Rasmus Lerdorf . Vale a pena compartilhar, pois descreve por que funciona e quando deve ser usado.

Portanto, quando você implanta através de algo como o Capistrano, que faz uma troca de link simbólico na raiz do documento, deseja que todas as novas solicitações obtenham os novos arquivos, mas não deseja estragar as solicitações que estão sendo executadas no momento em que a implantação está acontecendo. O que você realmente precisa para criar um ambiente de implementação robusto é ter seu servidor da Web encarregado disso. O servidor da Web é a parte da pilha que entende quando uma nova solicitação está sendo iniciada. O cache do opcode está muito profundo na pilha para saber ou se importar com isso.

Com o nginx, isso é bastante simples. Basta adicionar isso à sua configuração:

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

Isso indica ao nginx para o caminho real resolver o link simbólico do docroot, o que significa que, até onde seu aplicativo PHP sabe, o destino do link simbólico se o document_root real. Agora, uma vez iniciada uma solicitação, o nginx resolverá o link simbólico como está nesse ponto e, durante a solicitação, ele usará o mesmo diretório docroot, mesmo que a opção do link simbólico ocorra no meio da solicitação. Isso elimina completamente os sintomas descritos aqui e é a abordagem correta. Isso não é algo que pode ser resolvido no nível do opcache.

Kanishk Dudeja teve problemas com isso e acrescentou um aviso útil: verifique se essas alterações realmente estarão na configuração final, ou seja, após o include fastcgi_params;que as substituirá.

Esa Jokinen
fonte
Olá, esta é uma ótima resposta, mas se você perceber na minha configuração, tenho fastcgi_param DOCUMENT_ROOT $ realpath_root; fastcgi_param SCRIPT_FILENAME $ document_root $ fastcgi_script_name; incluído após fastcgi_params, e isso realmente não ajuda. Quando eu reinicio o php-fpm, os links simbólicos são resolvidos. Isso indicaria que eu tenho um problema de cache php?
Auris
Rever. Você não SCRIPT_FILENAMEtem . $document_root$realpath_root
Esa Jokinen
Hmm ... mas DOCUMENT_ROOTestá definido para $realpath_rootassim do jeito que eu entendo, ele deve cadeia de puxar o valor ou estou completamente errado e DOCUMENT_ROOTnão está relacionado com$document_root
Auris
1
Oi, muito obrigado pela sua resposta e sua explicação, meu erro foi a suposição de que DOCUMENT_ROOTafecta$document root
Auris
2
Estou usando o Apache + php-fpm nos servidores com esse problema e a limpeza do opcached no deploy funcionou para mim, mas temos um script bash para implantação, não o Capistrano. Eu acho que é uma solução mais simples e é uma boa prática limpar seu opcache na implantação de qualquer maneira. Esa obrigado pelo link para o comentário Rasmus que é ouro!
Carlos Mafla
3

Em /unix/157022/make-nginx-follow-symlinks , parece que você pode solucionar o problema alterando

fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;

para

fastcgi_param SCRIPT_FILENAME $realpath_root$fastcgi_script_name;

(ou seja, alterando o caminho de $document_rootpara $realpath_root).

No momento, não tenho acesso a um servidor nginx para confirmar isso (meu servidor doméstico está passando por uma reconstrução), mas a solução parece ser colaborada por https://medium.com/@kanishkdudeja/truly-atomic-deployments -com-nginx-e-php-fpm-aed8a8ac1cd9 .

Pak
fonte