Esta é uma condição de corrida nginx / WebDAV e como resolver isso?

1

Eu tenho um servidor nginx 1.10.3 rodando no Debian Stretch. Um dos sites que ele atende é um compartilhamento WebDAV lido e gravado por um aplicativo de desktop. O aplicativo executa as seguintes etapas quando um arquivo chamado myfile é salvo no servidor WebDAV:

  1. DELETE /myfile.tmp
  2. PUT /myfile.tmp , body contém novos dados de arquivo
  3. DELETE /myfile
  4. MOVE /myfile.tmp , Destination: http://webdav.example.com/myfile
  5. GET /myfile

O aplicativo cliente compara a resposta da etapa 5 com os dados enviados na etapa 2 e, se os dados do arquivo não corresponderem, será gerado um erro. Essas etapas acontecem com extrema rapidez em nossa rede particular (o servidor e o cliente estão geograficamente próximos, conectados ao mesmo switch Ethernet) - meu teste com o tcpdump sugere que toda a conversa termine dentro de 45 ms.

O problema é que os dados retornados na etapa 5 não correspondem imediatamente ao que o cliente enviou na etapa 2. Os dados que estão sendo retornados são da versão anterior de myfile , antes da DELETE / MOVE etapas substituiu-o. Se eu fosse voltar e repetir o passo 5 manualmente um momento depois, os dados do arquivo seriam a nova versão conforme o esperado.

Eu sei que o cliente espera que cada resposta chegue antes de emitir uma solicitação subsequente. Meu melhor palpite é que diferentes solicitações estão atingindo diferentes operadores / threads do nginx, ou talvez haja algum tipo de invalidação de cache ou flush que não esteja acontecendo rápido o suficiente.

Como posso corrigir esse comportamento sem modificar o aplicativo cliente ou desacelerar artificialmente as solicitações?

O nginx.conf completo e a configuração do site são os seguintes:

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

EDIT: Uma observação interessante que descobri. Se eu recarregar o nginx ( sudo service nginx reload ), a primeira tentativa de salvar o arquivo será bem-sucedida. Mas se eu tentar salvá-lo em um momento posterior, o mesmo erro acontecerá.

    
por smitelli 02.01.2018 / 03:55

1 resposta

0

Acontece que foi o material open_file_cache. Os docs fazem parecer que são apenas metadados do arquivo em cache no cache de estatísticas, mas neste caso No caso, estava realmente tornando algumas das respostas obsoletas.

open_file_cache off; dentro do bloco server { ... } foi o suficiente e agora está funcionando bem.

    
por 02.01.2018 / 05:23

Tags