9 votes

Comment invalider le cache du reverse proxy de nginx devant d'autres serveurs nginx ?

Je fais tourner un serveur Proxmox sur une seule adresse IP, qui distribue les requêtes HTTP aux conteneurs en fonction de l'hôte demandé.

J'utilise nginx du côté de Proxmox pour écouter les demandes HTTP et j'utilise l'option proxy_pass dans mes différents server pour distribuer les demandes en fonction des server_name .

Mes conteneurs fonctionnent sous Ubuntu et exécutent également une instance de nginx.

J'ai des problèmes avec la mise en cache sur un site web particulier qui est entièrement statique : nginx continue à me servir du contenu périmé après les mises à jour de fichiers, jusqu'à ce que je.. :

  • Effacer /var/cache/nginx/ et redémarrer nginx
  • ou set proxy_cache off pour ce serveur et recharger la configuration

Voici le détail de ma configuration :

Sur le serveur (proxmox) :

/etc/nginx/nginx.conf :

user www-data;
worker_processes 8;
pid /var/run/nginx.pid;

events {
    worker_connections 768;
    # multi_accept on;
    use epoll;
}

http {

    ##
    # Basic Settings
    ##

    sendfile on;
    #tcp_nopush on;
    tcp_nodelay on;
    #keepalive_timeout 65;
    types_hash_max_size 2048;
    server_tokens off;

    # server_names_hash_bucket_size 64;
    # server_name_in_redirect off;

    include /etc/nginx/mime.types;
    default_type application/octet-stream;

    client_body_buffer_size 1k;
    client_max_body_size    8m;
    large_client_header_buffers 1 1K;
    ignore_invalid_headers on;

    client_body_timeout 5;
    client_header_timeout 5;
    keepalive_timeout 5 5;
    send_timeout 5;
    server_name_in_redirect off;

    ##
    # Logging Settings
    ##

    access_log /var/log/nginx/access.log;
    error_log /var/log/nginx/error.log;

    ##
    # Gzip Settings
    ##

    gzip on;
    gzip_disable "MSIE [1-6]\.(?!.*SV1)";

    gzip_vary on;
    gzip_proxied any;
    gzip_comp_level 6;
    # gzip_buffers 16 8k;
    gzip_http_version 1.1;
    gzip_types text/plain text/css application/json application/x-javascript text/xml application/xml application/xml+rss text/javascript;

    limit_conn_zone $binary_remote_addr zone=gulag:1m;
    limit_conn gulag 50;

    ##
    # Virtual Host Configs
    ##

    include /etc/nginx/conf.d/*.conf;
    include /etc/nginx/sites-enabled/*;
}

/etc/nginx/conf.d/proxy.conf :

proxy_redirect          off;
proxy_set_header        Host            $host;
proxy_set_header        X-Real-IP       $remote_addr;
proxy_set_header        X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_hide_header       X-Powered-By;
proxy_intercept_errors  on;
proxy_buffering         on;

proxy_cache_key         "$scheme://$host$request_uri";
proxy_cache_path        /var/cache/nginx levels=1:2 keys_zone=cache:10m inactive=7d max_size=700m;

/etc/nginx/sites-available/my-domain.conf :

server {
    listen 80;
    server_name .my-domain.com;

    access_log off;

    location / {
            proxy_pass http://my-domain.local:80/;
            proxy_cache cache;
            proxy_cache_valid 12h;
            expires 30d;
            proxy_cache_use_stale error timeout invalid_header updating;
    }
}

Sur le conteneur (mon-domaine.local) :

nginx.conf : (tout est dans le fichier de configuration principal -- cela a été fait rapidement...)

user  www-data;
worker_processes  1;

error_log  logs/error.log;

events {
    worker_connections  1024;
}

http {
    include       mime.types;
    default_type  application/octet-stream;

    sendfile        on;
    #tcp_nopush     on;

    keepalive_timeout  65;

    gzip  off;

    server {
        listen       80;
        server_name  .my-domain.com;
        root /var/www;

        access_log  logs/host.access.log;
    }
}

J'ai lu de nombreux articles de blog et réponses avant de me résoudre à poster mes propres questions... la plupart des réponses que j'ai pu voir suggèrent de mettre en place sendfile off; mais qui n'a pas fonctionné pour moi . J'ai essayé de nombreuses autres choses, j'ai vérifié deux fois mes paramètres et tout semble correct.

Je me demande donc si je n'attends pas du cache de nginx qu'il fasse quelque chose qu'il n'est pas censé faire... ?

En fait, je pensais que si l'un de mes fichiers statiques dans mon conteneur était mis à jour, le cache de mon proxy inverse serait invalidé et mon navigateur obtiendrait la nouvelle version du fichier lorsqu'il le demanderait...

Mais j'ai maintenant le sentiment d'avoir mal compris beaucoup de choses.

De toutes les choses, je me demande maintenant comment nginx sur le serveur peut connaître un fichier dans le conteneur a changé ? J'ai vu une directive proxy_header_pass (ou quelque chose de similaire), dois-je l'utiliser pour permettre à l'instance nginx du conteneur d'informer celle de Proxmox des fichiers mis à jour ?

Cette attente n'est-elle qu'un rêve, ou puis-je le faire avec nginx sur mon architecture actuelle ?

6voto

user221618 Points 61

Ce que vous voulez faire n'est pas possible. Lorsqu'une URL est mise en cache par le proxy, aucune autre requête ne sera effectuée auprès du backend pour cette URL jusqu'à l'expiration du cache. Il n'y a aucun moyen pour le proxy de savoir que le fichier a été mis à jour sur le backend.

Certains caches avancés comme Varnish sont capables de gérer les demandes d'invalidations par le biais des en-têtes ou des requêtes PURGE. Par exemple, lorsqu'un utilisateur modifie une page mediawiki, la réponse à la demande POST contient un en-tête qui invalide l'entrée du cache pour l'article. Mais ce processus ne fonctionne que si une ressource est modifiée en utilisant un appel d'URL : la modification d'un fichier statique sur le backend n'informe pas le cache proxy.

On peut mettre en œuvre ce type d'invalidation sur nginx par le biais du module lua : http://syshero.org/post/68479556365/nginx-passive-cache-invalidation .

3voto

muodov Points 131

Vous pouvez réaliser cette fonctionnalité en utilisant un cache autonome (par exemple, memcached ou redis). nginx dispose de modules pour travailler avec eux. Vous aurez besoin d'une certaine convention sur les clés de cache (par exemple, construire la clé à partir du cookie de l'utilisateur et de l'url). Dans ce cas, vous pouvez contrôler les éléments du cache depuis le backend, y compris l'invalidation et la mise à jour.

SistemesEz.com

SystemesEZ est une communauté de sysadmins où vous pouvez résoudre vos problèmes et vos doutes. Vous pouvez consulter les questions des autres sysadmins, poser vos propres questions ou résoudre celles des autres.

Powered by:

X