Enlaces simbólicos de almacenamiento en caché de Nginx

12

Tengo un sistema de implementación en mi servidor web, cada vez que se implementa una aplicación, crea un nuevo directorio con marca de tiempo y enlaces simbólicos "actuales" al nuevo directorio. Todo esto funcionó bien y genial en Apache, pero en el nuevo servidor nginx que configuré, parece que se está ejecutando un script de la implementación "antigua" en lugar del nuevo enlace simbólico.

He leído algunos tutoriales y publicaciones sobre cómo resolver esto, pero no hay mucha información y nada parece funcionar. Aquí está mi archivo 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;
    }
}

y aquí está mi 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;

Realmente agradecería si alguien pudiera ayudarme con esto, ya que en este momento cada implementación implica eliminar la implementación anterior. El sistema es Ubuntu 14.04.5 LTS; PHP 7.1; Nginx nginx / 1.4.6 (Ubuntu)

Auris
fuente

Respuestas:

22

Las variables incorporadas , $realpath_root: una ruta absoluta que corresponde a la raíz o alias valor de directiva de la solicitud actual, con todos los enlaces simbólicos resolvieron caminos reales

La solución de usar en $realpath_rootlugar de $document_rootpegarla en todos los sitios y foros de preguntas y respuestas; en realidad es difícil evitar encontrarlo. Sin embargo, solo lo he visto bien explicado una vez por Rasmus Lerdorf . Vale la pena compartirlo, ya que describe por qué funciona y cuándo debe usarse.

Por lo tanto, cuando implementa a través de algo como Capistrano, que hace un intercambio de enlaces simbólicos en la raíz del documento, desea que todas las solicitudes nuevas obtengan los nuevos archivos, pero no desea atornillar las solicitudes que se están ejecutando actualmente mientras se lleva a cabo la implementación. Lo que realmente necesita para crear un entorno de implementación robusto es que su servidor web se encargue de esto. El servidor web es la parte de la pila que comprende cuándo se inicia una nueva solicitud. El caché del código de operación es demasiado profundo en la pila para saberlo o preocuparse por eso.

Con nginx esto es bastante simple. Simplemente agregue esto a su configuración:

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

Esto le dice a nginx que realpath resuelva el enlace simbólico docroot, lo que significa que, por lo que su aplicación PHP sabe, el objetivo del enlace simbólico es la raíz_documento real. Ahora, una vez que se inicia una solicitud, nginx resolverá el enlace simbólico tal como está en ese punto y durante la solicitud usará el mismo directorio docroot, incluso si el cambio de enlace simbólico ocurre a mitad de la solicitud. Esto elimina por completo los síntomas descritos aquí y es el enfoque correcto. Esto no es algo que se pueda resolver a nivel de opcache.

Kanishk Dudeja tuvo problemas con esto y agregó un aviso útil: asegúrese de que estos cambios estén realmente en la configuración final, es decir, después de lo include fastcgi_params;cual los anula.

Esa Jokinen
fuente
Hola, esta es una gran respuesta, pero si notas en mi configuración tengo fastcgi_param DOCUMENT_ROOT $ realpath_root; fastcgi_param SCRIPT_FILENAME $ document_root $ fastcgi_script_name; incluido después de fastcgi_params, y esto en realidad no ayuda. Cuando reinicio php-fpm, los enlaces simbólicos se resuelven. ¿Esto indicaría que tengo un problema de almacenamiento en caché de php en su lugar?
Auris
Revisar. Tu SCRIPT_FILENAMEtiene $document_root, no $realpath_root.
Esa Jokinen
Hmm ... pero DOCUMENT_ROOTestá configurado para $realpath_rootque, por lo que entiendo, debería encadenar el valor o estoy completamente equivocado y DOCUMENT_ROOTno está relacionado con$document_root
Auris
1
Hola, muchas gracias por tu respuesta y tu explicación, mi error fue la suposición que DOCUMENT_ROOTafecta$document root
Auris
2
Estoy usando Apache + php-fpm en los servidores con este problema y el borrado opcached en la implementación funcionó para mí, tenemos un script bash para la implementación, no Capistrano. Creo que es una solución más simple y de todos modos es una buena práctica limpiar su opcache en la implementación. Esa gracias por el enlace al comentario de Rasmus que es oro!
Carlos Mafla
3

Desde /unix/157022/make-nginx-follow-symlinks , parece que puede solucionar el problema cambiando

fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;

a

fastcgi_param SCRIPT_FILENAME $realpath_root$fastcgi_script_name;

(es decir, cambiar la ruta de $document_roota $realpath_root).

No tengo acceso a un servidor nginx en este momento para confirmar esto (mi servidor doméstico está actualmente en proceso de reconstrucción), pero la solución parece estar colaborada por https://medium.com/@kanishkdudeja/truly-atomic-deployments -with-nginx-and-php-fpm-aed8a8ac1cd9 .

Pak
fuente