problema di caricamento nginx client_max_body_size


117

Sto eseguendo nginx / ruby-on-rails e ho un semplice modulo multipart per caricare i file. Tutto funziona bene finché non decido di limitare la dimensione massima dei file che voglio caricare. Per fare ciò, ho impostato nginx client_max_body_sizesu 1 m (1 MB) e mi aspetto uno stato HTTP 413 (Request Entity Too Large) in risposta quando quella regola si rompe.

Il problema è che quando carico un file da 1.2 MB, invece di visualizzare la pagina di errore HTTP 413, il browser si blocca un po 'e poi muore con un messaggio "Connessione ripristinata durante il caricamento della pagina".

Ho provato quasi tutte le opzioni offerte da nginx, niente sembra funzionare. Qualcuno ha qualche idea su questo?

Ecco il mio nginx.conf:

worker_processes  1;
timer_resolution  1000ms;
events {
    worker_connections  1024;
}

http {
    passenger_root /the_passenger_root;
    passenger_ruby /the_ruby;

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

    sendfile           on;
    keepalive_timeout  65;

    server {
      listen 80;
      server_name www.x.com;
      client_max_body_size 1M;
      passenger_use_global_queue on;
      root /the_root;
      passenger_enabled on;

      error_page 404 /404.html;
      error_page 413 /413.html;    
    }    
}

Grazie.


**Edit**

Ambiente / UA: Windows XP / Firefox 3.6.13

Risposte:


128

nginx "fallisce velocemente" quando il client lo informa che invierà un corpo più grande client_max_body_sizedi inviando una risposta 413 e chiudendo la connessione.

La maggior parte dei client non legge le risposte finché non viene inviato l'intero corpo della richiesta. Poiché nginx chiude la connessione, il client invia i dati al socket chiuso, provocando un RST TCP.

Se il tuo client HTTP lo supporta, il modo migliore per gestirlo è inviare Expect: 100-Continueun'intestazione. Nginx lo supporta correttamente a partire dalla 1.2.7 e risponderà con una 413 Request Entity Too Largerisposta anziché 100 Continuese Content-Lengthsupera la dimensione corporea massima.


1
Oh, dovrei sottolineare che questa risposta presume che il client stia inviando Content-Lengthpiuttosto che facendo Transfer-Encoding: chunked.
Joe Shaw

2
L'autore di nginx ha pubblicato una patch per risolvere questo problema sulla mailing list: nginx.2469901.n2.nabble.com/… Non si sa se verrà aggiunto al ramo stabile 1.2.x, però.
Joe Shaw

Grazie, questo spiega davvero molto. Certamente sembra Expectsia la strada da percorrere per grandi richieste.
krukid

Ho aggiornato la mia risposta per notare che la patch che ho menzionato prima è stata inserita e incorporata nella versione 1.2.7.
Joe Shaw

Solo per risparmiare il tempo di cercare una bella sintassi (come ho speso): request.setHeader(HttpHeaders.EXPECT, CONTINUE);con import org.apache.http.HttpHeaders;eimport static org.jboss.netty.handler.codec.http.HttpHeaders.Values.CONTINUE;
Erez Cohen

48

Il tuo caricamento muore alla fine? 99% prima di schiantarsi? Il corpo del client e i buffer sono fondamentali perché nginx deve bufferizzare i dati in arrivo. Le configurazioni del corpo (dati del corpo della richiesta) specificano il modo in cui nginx gestisce il flusso di massa dei dati binari dai client multiparte nella logica dell'app.

L' cleanimpostazione libera la memoria e i limiti di consumo istruendo nginx a memorizzare il buffer in entrata in un file e quindi a ripulirlo successivamente dal disco eliminandolo.

Impostare body_in_file_onlyper cleane regolare buffer per il client_max_body_size. La configurazione della domanda originale aveva già sendfile attivo, aumenta anche i timeout. Uso le impostazioni seguenti per risolvere questo problema, appropriate per i contesti di configurazione, server e http locali.

client_body_in_file_only clean;
client_body_buffer_size 32K;

client_max_body_size 300M;

sendfile on;
send_timeout 300s;

Anche se questo si traduce in nginx che restituisce un HTTP 413 corretto, UA finirà comunque per inviare l'intero corpo della richiesta, no? In tal caso, penso che valga la pena provare l'approccio suggerito da @ joe-shaw.
krukid

@krukid quando sembra che abbiamo completato il 99% di caricamento prima che NGINX "fallisca velocemente", sono d'accordo con te. In questo caso, tutti i segni intorno all'oggetto richiesta sono positivi, ovvero la diagnosi è che la logica dell'applicazione server interna va bene, qualunque cosa si trovi dietro Nginx. Quindi, sebbene sia probabile che la richiesta sia stata ben formata, il nostro bisogno è quindi di considerare il motivo per cui NGINX si strozza in risposta. client_max_body_size dovrebbe essere la prima opzione di configurazione che guardiamo, quindi considera i buffer, perché con un caricamento abbastanza grande la soluzione corretta dipende dalla quantità di memoria che il nostro server può gestire.
Bent Cardan

@Bent Cardan. Questo approccio sembrava essere il migliore e l'ho provato. Ma ricevo ancora un errore 413 dopo circa 20 secondi per un file da 4 MB. I miei aumenti di velocità non possono gestire 4 MB in 20 secondi, quindi accade dopo che i dati sono fluiti per un bel po '. Pensieri?
Jerome

Ho aggiunto le modifiche nel file nginx.conf _client_max_body_size 300M; sendfile su; send_timeout 300s; _ Per me funziona perfettamente. Grazie
Ramesh Chand

La soluzione funziona per me openshift php7 nginx.
marlo

7

Dalla documentazione :

È necessario tenere presente che i browser non sanno come mostrare correttamente questo errore.

Sospetto che questo sia quello che sta succedendo, se controlli l'HTTP avanti e indietro usando strumenti come Firebug o Live HTTP Headers (entrambe estensioni di Firefox) sarai in grado di vedere cosa sta realmente succedendo.


1
L'ho trovato anche qui: forum.nginx.org/read.php?2,2620 Dove l'autore di nginx dice che le persone potrebbero provare a cambiare lingering_time / lingering_timeout - entrambe le cose non hanno avuto alcun effetto nel mio caso. Inoltre, non vedo come potrebbe esserci un problema di timeout persistente quando sto caricando un file da 1,2 MB con un limite di 1 MB con una connessione stabile a 5 Mbps. Ho fiutato la risposta e invia la pagina 413 con l'intestazione "Connection: close", ma la connessione non sembra chiudersi.
krukid

Immagino di avere solo difficoltà a credere che anche se esiste uno stato HTTP 413 perfettamente valido, non si attiva nei browser. Ho cercato su Google molti posti in cui le persone non riescono a sbarazzarsi di quella pagina e non l'ho mai nemmeno vista.
krukid

Se disabiliti il ​​passeggero, chiude la connessione?
Mark Rose

Bene, ho confrontato le risposte con e senza passeggero. Quando tutto funziona normalmente e carico un file molte volte più grande (~ 14 MB) della mia restrizione di 1 MB, ricevo 413 risposte più volte (perché il client continua a inviare blocchi) e il "ripristino della connessione" finale sembra un timeout. Senza passeggero ricevo una risposta istantanea 413 e tutti i progressi si interrompono, ma vedo ancora la pagina "Ripristino connessione", non il mio 413.html statico o qualsiasi cosa che implichi "Entità troppo grande"
krukid
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.