Nginx-Caching-Symlinks

12

Ich habe ein Bereitstellungssystem auf meinem Webserver. Jedes Mal, wenn eine App bereitgestellt wird, erstellt sie ein neues Verzeichnis mit Zeitstempel und verknüpft "aktuell" mit dem neuen Verzeichnis. Dies alles funktionierte gut und großartig auf Apache, aber auf dem neuen Nginx-Server, den ich eingerichtet habe, sieht es so aus, als würde ein Skript aus der "alten" Bereitstellung anstelle des neuen Symlink-Servers ausgeführt.

Ich habe einige Tutorials und Beiträge gelesen, wie man das löst, aber es gibt nicht viele Informationen und nichts scheint zu funktionieren. Hier ist meine vhost-Datei:

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;
    }
}

und hier sind meine 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;

Ich würde mich sehr freuen, wenn mir jemand dabei helfen könnte, da im Moment jede Bereitstellung das Löschen der vorherigen Bereitstellung beinhaltet. System ist Ubuntu 14.04.5 LTS; PHP 7.1; Nginx nginx / 1.4.6 (Ubuntu)

Auris
quelle

Antworten:

22

Eingebettete Variablen , $realpath_root: ein absoluter Pfad entsprechend die Wurzel oder Alias - Richtlinie des Wert für die aktuelle Anforderung, mit allen symbolischen Verknüpfungen gelöst realen Pfade

Die Lösung der Verwendung von $realpath_rootanstelle von $document_rootwird überall auf den Q / A-Websites und -Foren kopiert. Es ist tatsächlich schwer zu vermeiden, es zu finden. Trotzdem habe ich es nur einmal von Rasmus Lerdorf gut erklärt gesehen . Es lohnt sich zu teilen, da es beschreibt, warum es funktioniert und wann es verwendet werden sollte.

Wenn Sie also über etwas wie Capistrano bereitstellen, das einen Symlink-Austausch im Dokumentstamm durchführt, möchten Sie, dass alle neuen Anforderungen die neuen Dateien abrufen, aber Sie möchten nicht die Anforderungen verschrauben, die derzeit während der Bereitstellung ausgeführt werden. Was Sie wirklich benötigen, um eine robuste Bereitstellungsumgebung zu erstellen, ist, dass Ihr Webserver dafür verantwortlich ist. Der Webserver ist der Teil des Stapels, der versteht, wann eine neue Anforderung gestartet wird. Der Opcode-Cache befindet sich zu tief im Stapel, um dies zu wissen oder sich darum zu kümmern.

Mit Nginx ist das ganz einfach. Fügen Sie dies einfach Ihrer Konfiguration hinzu:

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

Dies weist nginx an, den docroot-Symlink mit realpath aufzulösen. Dies bedeutet, dass nach Ihrer PHP-Anwendung das Ziel des symlinks der echte document_root ist. Sobald eine Anforderung gestartet wird, löst nginx den Symlink an diesem Punkt auf und verwendet für die Dauer der Anforderung dasselbe Docroot-Verzeichnis, selbst wenn der Symlink-Wechsel während der Anforderung erfolgt. Dies beseitigt die hier beschriebenen Symptome vollständig und ist der richtige Ansatz. Dies kann auf Opcache-Ebene nicht gelöst werden.

Kanishk Dudeja hatte Probleme damit und fügte einen nützlichen Hinweis hinzu: Stellen Sie sicher, dass diese Änderungen tatsächlich in der endgültigen Konfiguration sind, dh danach werden include fastcgi_params;sie anderweitig überschrieben.

Esa Jokinen
quelle
Hallo, das ist eine großartige Antwort, aber wenn Sie in meiner Konfiguration feststellen, dass ich fastcgi_param DOCUMENT_ROOT $ realpath_root habe; fastcgi_param SCRIPT_FILENAME $ document_root $ fastcgi_script_name; enthalten nach fastcgi_params, und das hilft eigentlich nicht. Wenn ich php-fpm neu starte, werden die Symlinks aufgelöst. Würde dies darauf hinweisen, dass ich stattdessen ein PHP-Caching-Problem habe?
Auris
Überarbeiten. Dein SCRIPT_FILENAMEhat $document_rootnicht $realpath_root.
Esa Jokinen
Hmm ... aber DOCUMENT_ROOTist so eingestellt, $realpath_rootwie ich es verstehe, es sollte den Wert der Kette ziehen oder bin ich völlig falsch und DOCUMENT_ROOTist nicht verwandt mit$document_root
Auris
1
Hallo, vielen Dank für Ihre Antwort und Ihre Erklärung, mein Fehler war die Annahme, die DOCUMENT_ROOTbetrifft$document root
Auris
2
Ich verwende Apache + php-fpm auf den Servern mit diesem Problem und das Löschen von opcached bei der Bereitstellung hat für mich funktioniert. Wir haben jedoch ein Bash-Skript für die Bereitstellung, nicht Capistrano. Ich denke, es ist eine einfachere Lösung und es ist eine gute Praxis, Ihren Opcache bei der Bereitstellung trotzdem zu löschen. Esa, danke für den Link zum Rasmus-Kommentar, der Gold wert ist!
Carlos Mafla
3

Unter /unix/157022/make-nginx-follow-symlinks können Sie das Problem möglicherweise durch Ändern umgehen

fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;

zu

fastcgi_param SCRIPT_FILENAME $realpath_root$fastcgi_script_name;

(dh den Pfad von $document_rootnach ändern $realpath_root).

Ich habe derzeit keinen Zugriff auf einen Nginx-Server, um dies zu bestätigen (mein Heimserver wird derzeit neu erstellt), aber die Lösung scheint von https://medium.com/@kanishkdudeja/truly-atomic-deployments zusammengearbeitet zu werden -mit-nginx-und-php-fpm-aed8a8ac1cd9 .

Pak
quelle