104, 'Connection reset dal peer' errore di socket, o quando non la chiusura di un risultato socket in un RST piuttosto che FIN?

StackOverflow https://stackoverflow.com/questions/383738

Domanda

Stiamo sviluppando un servizio web Python e un sito web del cliente in parallelo. Quando facciamo una richiesta HTTP dal client al servizio, una chiamata solleva costantemente un socket.error in socket.py, in modalità di lettura:

(104, 'Connection reset by peer')

Quando ascolto con Wireshark, il "buono" e "cattivi" le risposte sono molto simili:

  • A causa della dimensione dell'intestazione OAuth, la richiesta viene diviso in due pacchetti. Il servizio risponde sia con ACK
  • Il servizio invia la risposta, un pacchetto per ogni intestazione (HTTP / 1.0 200 OK, quindi l'intestazione Data, ecc). Il cliente risponde a ciascuno con ACK.
  • (Buono richiesta) il server invia un FIN, ACK. Il client risponde con un FIN, ACK. Il server risponde ACK.
  • (Bad richiesta) il server invia un RST, ACK, il client non invia una risposta TCP, il socket.error è sollevata sul lato client.

Sia il servizio Web e il client sono in esecuzione su una scatola di Gentoo Linux x86-64 esecuzione glibc-2.6.1. Stiamo utilizzando Python 2.5.2 all'interno dello stesso virtual_env.

Il client è un Django 1.0.2 app che sta chiamando httplib2 0.4.0 per effettuare richieste. Stiamo firmando le richieste con l'algoritmo OAuth firma, con il token OAuth sempre impostato su una stringa vuota.

Il servizio è in esecuzione Werkzeug 0.3.1, che sta utilizzando wsgiref.simple_server di Python. Ho eseguito l'applicazione WSGI attraverso wsgiref.validator senza problemi.

Sembra che questo dovrebbe essere facile per eseguire il debug, ma quando traccio attraverso un buon richiesta sul lato di servizio, sembra proprio come il cattivo richiesta, nella funzione socket._socketobject.close (), trasformando metodi delegato in manichino metodi. Quando l'invio o sendto (non ricordo quale) il metodo è spento, la FIN o RST viene inviato, e il client avvia l'elaborazione.

"Connection reset by peer" sembra dare la colpa sul servizio, ma non mi fido httplib2 neanche. Il cliente può essere in colpa?

** Ulteriori debug - Sembra server su Linux **

Ho un MacBook, così ho provato a fare funzionare il servizio su uno e il sito web del cliente, dall'altro. Il client Linux chiama il server OS X senza il bug (FIN ACK). Il client di OS X chiama il servizio di Linux con il bug (RST ACK, ed una (54, 'Connection reset by peer')). Così, sembra che il servizio in esecuzione su Linux. E 'x86_64? Un cattivo glibc? wsgiref? Ancora alla ricerca ...

** Ulteriori test - wsgiref sembra traballante **

Siamo passati alla produzione con Apache e mod_wsgi, e il ripristino di connessione sono andati via. Vedere la mia risposta qui sotto, ma il mio consiglio è quello di accedere il ripristino di connessione e riprovare. Questo vi permetterà di eseguire il server su OK nella modalità di sviluppo, e solidamente in produzione.

È stato utile?

Soluzione

Ho avuto questo problema. Vedere Il pitone "Connessione ripristinata dal peer" Problema .

Hai (più probabile) conciliarsi con piccoli problemi di temporizzazione in base alla Interpreter Lock Python Globale.

È possibile (a volte) correggere questo con una time.sleep(0.01) posizione strategica.

"Dove?" tu chiedi. Mi batte. L'idea è quella di fornire alcuni meglio concorrenza filo in ed intorno alle richieste dei client. Prova a mettere semplicemente prima a fare la richiesta in modo che il GIL viene azzerato e l'interprete Python può cancellare qualsiasi thread in attesa.

Altri suggerimenti

Non utilizzare wsgiref per la produzione. Utilizzare Apache e mod_wsgi, o qualcos'altro.

Continuiamo a vedere queste cadute della connessione, a volte spesso, con wsgiref (il backend utilizzato dal server di prova Werkzeug, e, eventualmente, altri come il server di test Django). La nostra soluzione era quella di registrare l'errore, ripetere la chiamata in un ciclo, e rinunciare dopo dieci fallimenti. httplib2 prova due volte, ma abbiamo bisogno di un paio di più. Essi sembrano venire in grappoli, come pure -. L'aggiunta di un secondo di sonno 1 potrebbe cancellare il problema

Non abbiamo mai visto una connessione reimpostata quando si esegue attraverso Apache e mod_wsgi. Non so quello che fanno in modo diverso, (forse semplicemente li maschera), ma non appaiono.

Quando abbiamo chiesto la comunità locale dev aiuto, qualcuno ha confermato che vedono un sacco di cadute della connessione con wsgiref che va via sul server di produzione. C'è un bug lì, ma sta per essere difficile da trovare.

Mi rendo conto che si sta utilizzando Python, ma ho trovato questo articolo Java per essere utile.

http: //java.sun. com / JavaSE / 6 / docs / note tecniche / guide / net / articoli / connection_release.html

In genere, si otterrebbe un RST se si fa un vicino, che non indugia (cioè in cui i dati possono essere eliminati dallo stack, se non è stato inviato e ACK'd) e una FIN normale se si consentono la chiusura a soffermarsi (vale a dire gli stretti attende i dati in transito da ACK'd).

Forse tutto quello che dovete fare è impostare la tua presa di soffermarsi in modo da rimuovere la condizione di competizione tra un non persistente stretta fatta sul socket e le ACK in arrivo?

Ho avuto lo stesso problema ma con il fare un upload di un file molto grande con un pitone-le richieste dei client annuncio a un nginx + uwsgi backend.

Quello che ha finito per essere la causa era il backend ha avuto un limite della dimensione massima del file per il caricamento inferiori a ciò che il cliente stava cercando di trasmettere.

L'errore mai arrivato nei nostri registri di uwsgi dal momento che questo limite è stato in realtà uno imposto dalla nginx.

Aumentando il limite in nginx rimosso l'errore.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top