2 votes

S'agit-il d'un problème de concurrence entre nginx et WebDAV, et comment le contourner ?

J'ai un serveur nginx 1.10.3 fonctionnant sous Debian Stretch. L'un des sites qu'il dessert est un partage WebDAV qui est lu et écrit par une application de bureau. L'application effectue les étapes suivantes lorsqu'un fichier nommé myfile est enregistré sur le serveur WebDAV :

  1. DELETE /myfile.tmp
  2. PUT /myfile.tmp Le corps contient les nouvelles données du fichier
  3. DELETE /myfile
  4. MOVE /myfile.tmp , Destination: http://webdav.example.com/myfile
  5. GET /myfile

L'application client compare la réponse de l'étape 5 aux données envoyées à l'étape 2, et si les données du fichier ne correspondent pas, une erreur est levée. Ces étapes se déroulent très rapidement sur notre réseau particulier (le serveur et le client sont géographiquement proches, connectés au même commutateur Ethernet) - mes tests avec tcpdump suggèrent que l'ensemble de la conversation se termine en moins de 45 ms.

Le problème est que les données renvoyées à l'étape 5 ne sont pas immédiatement correspondent à ce que le client a envoyé à l'étape 2. Les données renvoyées sont la version précédente de myfile , avant que le DELETE / MOVE l'ont remplacée. Si je revenais en arrière et répétais manuellement l'étape 5 un peu plus tard, les données du fichier correspondraient à la nouvelle version, comme prévu.

Je sais que le client attend que chaque réponse arrive avant d'émettre une nouvelle demande. Mon hypothèse la plus plausible est que les différentes requêtes touchent différents travailleurs/threads de nginx, ou peut-être qu'il y a une sorte d'invalidation ou de vidage de cache qui ne se produit pas assez rapidement.

Comment puis-je corriger ce comportement sans modifier l'application client ou ralentir artificiellement les requêtes ?

La configuration complète de nginx.conf et du site suit :

pid /run/nginx.pid;
user www-data;
worker_processes auto;
worker_rlimit_nofile 20000;

events {
    multi_accept on;
    use epoll;
    worker_connections 4000;
}

http {
    access_log /var/log/nginx/access.log;
    error_log /var/log/nginx/error.log warn;

    sendfile on;
    server_tokens off;
    tcp_nodelay on;
    tcp_nopush on;
    keepalive_requests 100000;
    keepalive_timeout 65;
    client_body_timeout 10;
    send_timeout 10;
    reset_timedout_connection on;
    types_hash_max_size 2048;

    open_file_cache max=200000 inactive=20s;
    open_file_cache_errors on;
    open_file_cache_min_uses 2;
    open_file_cache_valid 30s;

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

    gzip on;
    gzip_buffers 16 8k;
    gzip_comp_level 6;
    gzip_disable msie6;
    gzip_http_version 1.1;
    gzip_min_length 10240;
    gzip_proxied any;
    gzip_vary on;
    gzip_types
        application/atom+xml
        application/javascript
        application/json
        application/ld+json
        application/manifest+json
        application/rss+xml
        application/vnd.geo+json
        application/vnd.ms-fontobject
        application/x-font-ttf
        application/x-javascript
        application/x-web-app-manifest+json
        application/xhtml+xml
        application/xml
        application/xml+rss
        font/opentype
        image/bmp
        image/svg+xml
        image/x-icon
        text/cache-manifest
        text/css
        text/javascript
        text/plain
        text/vcard
        text/vnd.rim.location.xloc
        text/vtt
        text/x-component
        text/x-cross-domain-policy
        text/xml;

    server {
        listen 80;
        listen [::]:80;
        server_name webdav.example.com;

        root /var/www/webdav.example.com;

        autoindex on;
        autoindex_exact_size off;
        autoindex_localtime on;
        dav_access user:rw group:r all:r;
        dav_methods DELETE MOVE PUT;
        create_full_put_path on;
    }
}

EDITAR: J'ai découvert une observation intéressante. Si je recharge nginx ( sudo service nginx reload ), la toute première tentative d'enregistrement du fichier réussit. Mais si j'essaie de l'enregistrer à nouveau, la même erreur se produit.

1voto

Randall Hauch Points 3231

Il s'est avéré que c'était le truc open_file_cache. Il s'est avéré qu'il s'agissait de la fonction open_file_cache. documents donne l'impression de ne mettre en cache que les métadonnées des fichiers, à l'instar du cache de statistiques, mais dans ce cas, il rendait certaines réponses périmées.

open_file_cache off; à l'intérieur du server { ... } Il a suffi de bloquer le système pour qu'il fonctionne bien.

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