У меня есть сервер nginx 1.10.3, работающий на Debian Stretch. Один из обслуживаемых сайтов - это общий ресурс WebDAV, который читается и записывается настольным приложением. Приложение выполняет следующие шаги, когда файл с именем myfile
сохраняется на сервере WebDAV:
DELETE /myfile.tmp
PUT /myfile.tmp
, тело содержит новые данные файлаDELETE /myfile
MOVE /myfile.tmp
, Destination: http://webdav.example.com/myfile
GET /myfile
Клиентское приложение сравнивает ответ с шага 5 с данными, отправленными на шаге 2, и, если данные файла не совпадают, возникает ошибка. Эти шаги выполняются очень быстро в нашей конкретной сети (сервер и клиент географически близки, подключены к одному коммутатору Ethernet) - мое тестирование с помощью tcpdump показывает, что весь диалог завершается в течение 45 мс.
Проблема в том, что данные, возвращенные на шаге 5, не немедленно соответствует тому, что клиент отправил на шаге 2. Возвращаемые данные являются предыдущей версией myfile
, перед DELETE
/MOVE
шаги заменили его. Если бы я вернулся и повторил шаг 5 вручную через мгновение, данные файла были бы новой версией, как и ожидалось.
Я знаю, что клиент ожидает получения каждого ответа, прежде чем отправить следующий запрос. Мое лучшее предположение состоит в том, что разные запросы попадают в разные рабочие / потоки nginx, или, может быть, есть какая-то недействительность кеша или сброс, который происходит недостаточно быстро.
Как я могу исправить это поведение, не изменяя клиентское приложение или искусственно не замедляя запросы?
Полная конфигурация nginx.conf и сайта:
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;
}
}
РЕДАКТИРОВАТЬ: Я обнаружил интересное наблюдение. Если я перезагружу nginx (sudo service nginx reload
), первая попытка сохранить файл будет успешной. Но если я попытаюсь сохранить его в следующий раз, произойдет та же ошибка.
Оказывается, это был материал open_file_cache. В документы звучит так, будто он кэширует только метаданные файла, как кеш статистики, но в этом случае он фактически делал некоторые ответы устаревшими.
open_file_cache off;
внутри server { ... }
block был все, что нужно, и теперь он работает хорошо.