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 :
DELETE /myfile.tmp
PUT /myfile.tmp
Le corps contient les nouvelles données du fichierDELETE /myfile
MOVE /myfile.tmp
,Destination: http://webdav.example.com/myfile
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.