Possibile causa dei codici di errore NGINX 499


116

Ricevo molti codici di errore 499 NGINX. Vedo che questo è un problema lato client. Non è un problema con NGINX o il mio stack uWSGI. Noto la correlazione nei log uWSGI quando si ottiene un 499.

address space usage: 383692800 bytes/365MB} {rss usage: 167038976
bytes/159MB} [pid: 16614|app: 0|req: 74184/222373] 74.125.191.16 ()
{36 vars in 481 bytes} [Fri Oct 19 10:07:07 2012] POST /bidder/ =>
generated 0 bytes in 8 msecs (HTTP/1.1 200) 1 headers in 59 bytes (1
switches on core 1760)
SIGPIPE: writing to a closed pipe/socket/fd (probably the client
disconnected) on request /bidder/ (ip 74.125.xxx.xxx) !!!
Fri Oct 19 10:07:07 2012 - write(): Broken pipe [proto/uwsgi.c line
143] during POST /bidder/ (74.125.xxx.xxx)
IOError: write error

Sto cercando una spiegazione più approfondita e spero che non ci sia niente di sbagliato nella mia configurazione NGINX per uwsgi. Lo prendo per valore nominale. Sembra un problema del cliente.


Hai mai trovato una soluzione a questo? Vedo esattamente lo stesso problema sia con uWSGI che con nginx.
Raj

1
Lo ottengo quando annullo una richiesta jQuery ajax.
mpen

1
So che questa è una domanda molto vecchia, ma la quantità di domande mal riposte su SO è sbalorditiva. Questo chiaramente appartiene a SF.
Sosukodo

Risposte:


164

HTTP 499 in Nginx significa che il client ha chiuso la connessione prima che il server rispondesse alla richiesta. Nella mia esperienza è solitamente causato dal timeout lato client . Come so, si tratta di un codice di errore specifico di Nginx.


1
Come caso speciale, ho notato che a volte accade quando l'utente finale fa doppio clic su un pulsante di invio del modulo. Il modulo viene inviato due volte, ma il cliente si aspetta una sola risposta. Questo può essere aggirato disabilitando (almeno per alcuni secondi) i pulsanti in JS la prima volta che vengono cliccati.
Antoine Pinsard

14
È importante notare che il "client" potrebbe effettivamente essere un proxy. Ad esempio, se stai utilizzando un bilanciatore del carico, potrebbe annullare la richiesta al server nginx a causa di un timeout.
Brad Koch

Succede sulla mia APP Angular se l'utente chiude la scheda e le mie richieste API non vengono completate.
Vivek Saurabh,

È importante notare che questo può essere causato anche dal server ; se il server impiega troppo tempo a rispondere, il client si arrende.
ijoseph

78

Nel mio caso, ero impaziente e ho finito per interpretare male il registro.

In effetti, il vero problema era la comunicazione tra nginx e uwsgi, e non tra il browser e nginx. Se avessi caricato il sito nel browser e avessi aspettato abbastanza a lungo avrei ottenuto un "504 - Bad Gateway". Ma ci è voluto così tanto tempo, che ho continuato a provare cose e poi aggiornare nel browser. Quindi non ho mai aspettato abbastanza a lungo per vedere l'errore 504. Quando si aggiorna nel browser, cioè quando la richiesta precedente viene chiusa e Nginx la scrive nel registro come 499.

Elaborazione

Qui presumo che il lettore sappia così poco come ho fatto io quando ho iniziato a giocare.

La mia configurazione era un proxy inverso, il server nginx e un server applicazioni, il server uWSGI dietro di esso. Tutte le richieste dal client andavano al server nginx, quindi inoltrate al server uWSGI, e quindi la risposta veniva inviata allo stesso modo. Penso che questo sia il modo in cui tutti usano nginx / uwsgi e dovrebbero usarlo.

Il mio nginx ha funzionato come dovrebbe, ma qualcosa non andava con il server uwsgi. Ci sono due modi (forse più) in cui il server uwsgi può non rispondere al server nginx.

1) uWSGI dice "Sto elaborando, aspetta e riceverai presto una risposta". nginx ha un certo periodo di tempo, che è disposto ad aspettare, fx 20 secondi. Dopodiché, risponderà al client, con un errore 504.

2) uWSGI è morto o uWSGi muore mentre nginx lo sta aspettando. nginx lo vede subito e in tal caso restituisce un errore 499.

Stavo testando la mia configurazione effettuando richieste nel client (browser). Nel browser non è successo nulla, è rimasto bloccato. Dopo forse 10 secondi (meno del timeout) ho concluso che qualcosa non andava (il che era vero) e ho chiuso il server uWSGI dalla riga di comando. Quindi andrei alle impostazioni di uWSGI, proverei qualcosa di nuovo, e poi riavvierei il server uWSGI. Nel momento in cui ho chiuso il server uWSGI, il server nginx restituiva un errore 499.

Quindi ho continuato a eseguire il debug con 499 erroe, il che significa cercare su Google l'errore 499. Ma se avessi aspettato abbastanza a lungo, avrei ricevuto l'errore 504. Se avessi ricevuto l'errore 504, sarei stato in grado di comprendere meglio il problema e quindi di eseguire il debug.

Quindi la conclusione è che il problema era con uWGSI, che continuava a rimanere sospeso ("Aspetta ancora un po ', solo un po' di più, poi avrò una risposta per te ...").

Come mi fisso che problema, non mi ricordo. Immagino che potrebbe essere causato da molte cose.


1
Come sei finito a risolverlo? Sto riscontrando lo stesso problema e non sono stato in grado di individuare la causa.
Colin Nichols

1
Ho aggiunto un'elaborazione, purtroppo non credo risolverà il tuo problema.
Mads Skjern

1
Volevo solo dirti grazie! Ho avuto la stessa identica situazione e questo mi ha messo sulla strada giusta.
Aaron

3
@Shafiul: La mia elaborazione non spiega cosa ha causato il problema con uWSGI, spiega semplicemente che uWSGI era la causa (e non nginx). L'elaborazione descrive i sintomi e come li ho interpretati male. Capisco la tua delusione, ma hai frainteso l'essenza della mia risposta. Cordiali saluti.
Mads Skjern

2
Risposta estremamente utile, non cancellare mai! Questi concetti dovrebbero essere approfonditi nella documentazione da qualche parte, fai un ottimo servizio elaborando come si comporta in modo diverso da quello che implicherebbero i documenti!
jerclarke

21

Il client ha chiuso la connessione non significa che sia un problema del browser !? Affatto!

Puoi trovare 499 errori in un file di log se hai un LB (load balancer) davanti al tuo server web (nginx) AWS o haproxy (personalizzato). Detto questo, LB agirà come un cliente di nginx.

Se esegui valori predefiniti haproxy per:

    timeout client  60000
    timeout server  60000

Ciò significherebbe che LB scadrà dopo 60000 ms se non c'è risposta da nginx. Possono verificarsi timeout per siti Web o script occupati che richiedono più tempo per l'esecuzione. Dovrai trovare un timeout che funzioni per te. Ad esempio, estendilo a:

    timeout client  180s
    timeout server  180s

E probabilmente sarai pronto.

A seconda della configurazione, potresti vedere un errore di timeout del gateway 504 nel tuo browser che indica che qualcosa non va con php-fpm, ma questo non sarà il caso degli errori 499 nei tuoi file di registro.


12

Mentre indichi 499un aborto di connessione registrato da nginx. Ma di solito questo viene prodotto quando il server di backend è troppo lento e prima un altro proxy timeout o il software utente interrompe la connessione. Quindi controlla se uWSGI sta rispondendo velocemente o meno se c'è un carico sul server uWSGI / Database.

In molti casi ci sono altri proxy tra l'utente e nginx. Alcuni possono essere nella tua infrastruttura come forse un CDN, Load Balacer, una cache Varnish ecc. Altri possono essere lato utente come un proxy di cache, ecc.

Se ci sono proxy dalla tua parte come LoadBalancer / CDN ... dovresti impostare i timeout prima del tuo backend e progressivamente gli altri proxy per l'utente.

Se hai:

user >>> CDN >>> Load Balancer >>> Nginx >>> uWSGI

Ti consiglio di impostare:

  • n secondi al timeout di uWSGI
  • n+1 secondi al timeout di nginx
  • n+2 secondi al timeout per Load Balancer
  • n+3 secondi di timeout al CDN.

Se non puoi impostare alcuni dei timeout (come CDN), trova qual è il suo timeout e regola gli altri in base ad esso ( n, n-1...).

Ciò fornisce una corretta catena di timeout. e troverai davvero chi dà il timeout e restituisci il codice di risposta corretto all'utente.


8

Nel mio caso ho ottenuto 499 quando l'API del client ha chiuso la connessione prima che ricevesse una risposta. Ha letteralmente inviato un POST e chiude immediatamente la connessione. Questo è risolto dall'opzione:

proxy_ignore_client_abort attivo

Nginx doc


3
Non capisco come questo aiuti
Vladimir Starkov

Forse non è il tuo caso? Il cliente invia i dati e non è interessato a cosa gli succederà e quale sarà la risposta. Ma la mia domanda dovrebbe elaborare i dati. Senza questa opzione, i dati semplicemente non hanno il tempo di raggiungere la mia domanda.
DerSkythe

Grazie. Sintomi esatti e soluzione perfetta.
TTimo

Whoa! È quasi esattamente ciò di cui ho bisogno. L'unica cosa che aggiungerei sarebbe inviare 200 risposte alla fonte del webhook un po ' prima che chiuda la connessione stessa. Altrimenti, tendono a disabilitare i webhook e a non inviarli di nuovo ... Posso farlo per gli URL selezionati?
pilat

1
Questo non risolve il problema del tuo cliente che non riceve una risposta. Elimina solo 499 errori nei log e li sostituisce con il codice di stato 200. Pessima idea per farlo. La vera soluzione è dire al tuo cliente di aumentare l'impostazione del timeout ...
marcinx

7

Si scopre che 499 significa davvero "connessione interrotta dal client".

Ho avuto un timeout di lettura del client di 60s (e nginx ha anche un proxy_read_timeout predefinito di 60s). Quindi quello che stava accadendo nel mio caso è che nginx avrebbe error.log upstream timed out (110: Connection timed out) while reading upstreame poi nginx riprova "il prossimo server proxy nel gruppo di server backend che hai configurato." Questo se ne hai più di uno.

Quindi prova il successivo e il successivo finché (per impostazione predefinita ) non li ha esauriti tutti. Quando ciascuno di essi scade, li rimuove anche dall'elenco dei server di backend "live". Dopo che tutti sono esauriti, restituisce a504 gateway timeout.

Quindi nel mio caso nginx ha contrassegnato il server come "non disponibile", ha riprovato sul server successivo, quindi si è verificato il 60stimeout del mio client (immediatamente), quindi vedrei un upstream timed out (110: Connection timed out) while reading upstreamregistro, immediatamente seguito da un registro 499. Ma era solo una coincidenza temporale.

Relazionato:

Se tutti i server nel gruppo sono contrassegnati come attualmente non disponibili, viene restituito anche un 502 Bad Gateway.per 10 secondi. Vedi qui max_fails e fail_timeout. Inn the logs diràno live upstreams while connecting to upstream.

Se hai solo un backend proxy nel tuo gruppo di server, prova a essere l'unico server e restituisce un 504 Gateway Time-oute non rimuove il singolo server dall'elenco dei server "live", se proxy_read_timeoutviene superato. Vedi qui "Se c'è un solo server in un gruppo, i parametri max_fails, fail_timeout e slow_start vengono ignorati e tale server non sarà mai considerato non disponibile."

La parte veramente complicata è che se specifichi proxy_pass su "localhost" e la tua casella ha anche le "versioni di posizione" ipv6 e ipv4 contemporaneamente (la maggior parte delle caselle lo fa per impostazione predefinita), conterà come se tu avessi un "elenco" di più server nel tuo gruppo di server, il che significa che puoi entrare nella situazione precedente di vederlo restituire "502 per 10s" anche se elenchi solo un server . Vedi qui "Se un nome di dominio si risolve in più indirizzi, tutti verranno utilizzati in modo round-robin." Una soluzione alternativa è dichiararlo come proxy_pass http://127.0.0.1:5001;(il suo indirizzo ipv4) per evitare che sia sia ipv6 che ipv4. Quindi conta come comportamento "solo un singolo server".

Ci sono alcune impostazioni differenti che puoi modificare per rendere questo "meno" un problema. Come aumentare i timeout o farlo in modo che non contrassegni i server come "disabilitati" quando scadono ... o correggere l'elenco in modo che sia solo di dimensione 1, vedi sopra :)

Vedi anche: https://serverfault.com/a/783624/27813


3

Questo errore è abbastanza facile da riprodurre usando la configurazione standard di nginx con php-fpm.

Tenere premuto il pulsante F5 su una pagina creerà dozzine di richieste di aggiornamento al server. Ogni richiesta precedente viene annullata dal browser al nuovo aggiornamento. Nel mio caso ho trovato dozzine di 499 nel file di registro del negozio online del mio cliente. Da un punto di vista nginx: se la risposta non è stata consegnata al client prima della successiva richiesta di aggiornamento, nginx registra l'errore 499.

mydomain.com.log:84.240.77.112 - - [19/Jun/2018:09:07:32 +0200] "GET /(path) HTTP/2.0" 499 0 "-" (user-agent-string)
mydomain.com.log:84.240.77.112 - - [19/Jun/2018:09:07:33 +0200] "GET /(path) HTTP/2.0" 499 0 "-" (user-agent-string)
mydomain.com.log:84.240.77.112 - - [19/Jun/2018:09:07:33 +0200] "GET /(path) HTTP/2.0" 499 0 "-" (user-agent-string)
mydomain.com.log:84.240.77.112 - - [19/Jun/2018:09:07:33 +0200] "GET /(path) HTTP/2.0" 499 0 "-" (user-agent-string)
mydomain.com.log:84.240.77.112 - - [19/Jun/2018:09:07:33 +0200] "GET /(path) HTTP/2.0" 499 0 "-" (user-agent-string)
mydomain.com.log:84.240.77.112 - - [19/Jun/2018:09:07:34 +0200] "GET /(path) HTTP/2.0" 499 0 "-" (user-agent-string)
mydomain.com.log:84.240.77.112 - - [19/Jun/2018:09:07:34 +0200] "GET /(path) HTTP/2.0" 499 0 "-" (user-agent-string)
mydomain.com.log:84.240.77.112 - - [19/Jun/2018:09:07:34 +0200] "GET /(path) HTTP/2.0" 499 0 "-" (user-agent-string)
mydomain.com.log:84.240.77.112 - - [19/Jun/2018:09:07:34 +0200] "GET /(path) HTTP/2.0" 499 0 "-" (user-agent-string)
mydomain.com.log:84.240.77.112 - - [19/Jun/2018:09:07:35 +0200] "GET /(path) HTTP/2.0" 499 0 "-" (user-agent-string)
mydomain.com.log:84.240.77.112 - - [19/Jun/2018:09:07:35 +0200] "GET /(path) HTTP/2.0" 499 0 "-" (user-agent-string)

Se l'elaborazione php-fpm richiede più tempo (come una pagina WP pesante) può causare problemi, ovviamente. Ho sentito parlare di crash di php-fpm, ad esempio, ma credo che possano essere impediti configurando correttamente i servizi come gestire le chiamate a xmlrpc.php.


2

... è venuto qui da una ricerca su Google

Ho trovato la risposta altrove qui -> https://stackoverflow.com/a/15621223/1093174

che era aumentare il timeout di inattività della connessione del mio bilanciatore del carico elastico AWS!

(Avevo configurato un sito Django con proxy inverso nginx / apache e un lavoro / visualizzazione di backend di log davvero davvero scadente era scaduto)


0

Una volta ottenuto 499 "La richiesta è stata vietata dall'antivirus" come risposta http AJAX (falso positivo di Kaspersky Internet Security con un'analisi euristica leggera, un'analisi euristica profonda sapeva correttamente che non c'era nulla di sbagliato).


0

Ho riscontrato questo problema e la causa era dovuta al plug-in Kaspersky Protection sul browser. Se stai riscontrando questo problema, prova a disabilitare i tuoi plugin e vedi se questo risolve il tuo problema.


0

Uno dei motivi di questo comportamento potrebbe essere che stai usando httpper uwsgiinvece di socket. Usa il comando seguente se stai usando uwsgidirettamente.

uwsgi --socket :8080 --module app-name.wsgi

Lo stesso comando nel file .ini è

chdir = /path/to/app/folder
socket = :8080
module = app-name.wsgi

0

Questo non risponde alla domanda dell'OP, ma poiché sono finito qui dopo aver cercato furiosamente una risposta, ho voluto condividere ciò che abbiamo scoperto.

Nel nostro caso, risulta che questi 499 sono previsti. Quando gli utenti utilizzano la funzione di digitazione anticipata in alcune caselle di ricerca, ad esempio, nei log viene visualizzato qualcosa di simile.

GET /api/search?q=h [Status 499] 
GET /api/search?q=he [Status 499]
GET /api/search?q=hel [Status 499]
GET /api/search?q=hell [Status 499]
GET /api/search?q=hello [Status 200]

Quindi nel nostro caso penso che sia sicuro da usare, proxy_ignore_client_abort oncome suggerito in una risposta precedente. Grazie per quello!



0

Nel mio caso, ho una configurazione simile

AWS ELB >> ECS(nginx) >> ECS(php-fpm).

Avevo configurato il gruppo di sicurezza AWS sbagliato per il servizio ECS (php-fpm), quindi Nginx non è stato in grado di contattare il contenitore delle attività php-fpm. Ecco perché ricevevo errori nel registro delle attività di nginx

499 0 - elb-healthchecker/2.0

Il controllo di integrità è stato configurato per controllare il servizio php-fpm e confermare che è attivo e restituire una risposta.


0

So che questo è un vecchio thread, ma corrisponde esattamente a quello che mi è successo di recente e ho pensato di documentarlo qui. La configurazione (in Docker) è la seguente:

  • nginx_proxy
  • nginx
  • php_fpm che esegue l'app effettiva.

Il sintomo era un "502 Gateway Timeout" nel prompt di accesso dell'applicazione. Esame dei log trovati:

  • il pulsante funziona tramite un HTTP POSTper /login... e quindi ...
  • nginx-proxy ha ricevuto la /loginrichiesta e alla fine ha segnalato un timeout.
  • nginx ha restituito una 499risposta, che ovviamente significa "l'ospite è morto".
  • la /loginrichiesta non appariva affatto (!) nei log del server FPM!
  • non c'erano traceback o messaggi di errore in FPM ... nada, zero, zippo, none.

Si è scoperto che il problema era la mancata connessione al database per verificare l'accesso. Ma come capirlo si è rivelato essere pura supposizione.

La completa assenza di log di traceback dell'applicazione ... o anche un record che la richiesta era stata ricevuta da FPM ... è stata una sorpresa completa (e, devastante ...) per me. Sì, l'applicazione dovrebbe registrare gli errori, ma in questo caso sembra che il processo di lavoro di FPM sia morto con un errore di runtime, portando alla 499risposta di nginx. Ora, questo ovviamente è un problema nella nostra applicazione ... da qualche parte. Ma volevo registrare i dettagli di quello che è successo a beneficio delle persone successive che affrontano qualcosa del genere.

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.