104, 'Connection reset by peer' erreur de socket, ou ne Lorsque la fermeture d'un résultat de la douille dans un RST plutôt que FIN?

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

Question

Nous développons un service Web Python et un site Web client en parallèle. Lorsque nous faisons une requête HTTP du client au service, un appel soulève toujours un socket.error à socket.py, en lecture:

(104, 'Connection reset by peer')

Quand j'écoute avec Wireshark, les réponses « bon » et « mauvais » ressemblent beaucoup:

  • En raison de la taille de l'en-tête de OAuth, la demande est divisée en deux paquets. Le service répond à la fois avec ACK
  • Le service envoie la réponse, un paquet par tête (HTTP / 1.0 200 OK, puis l'en-tête de date, etc.). Le client répond à chacun avec accusé de réception.
  • (Bonne demande), le serveur envoie un FIN, ACK. Le client répond par un FIN, ACK. Le serveur répond ACK.
  • (demande Bad), le serveur envoie un RST, ACK, le client ne pas envoyer une réponse TCP, le socket.error est soulevé du côté client.

Tant le service Web et le client sont en cours d'exécution sur un glibc-2.6.1 en cours d'exécution boîte de Gentoo Linux. Nous utilisons Python 2.5.2 dans le même virtual_env.

Le client est une application Django 1.0.2 qui appelle httplib2 0.4.0 pour faire des demandes. Nous signons des demandes avec l'algorithme de signature OAuth, avec le jeton OAuth toujours réglé sur une chaîne vide.

Le service est en cours d'exécution Werkzeug 0.3.1, qui utilise le wsgiref.simple_server de Python. J'ai couru l'application WSGI par wsgiref.validator sans problème.

Il semble que cela devrait être facile à déboguer, mais quand je trace par une bonne demande sur le côté service, il ressemble à la mauvaise demande, dans la fonction socket._socketobject.close (), transformant les méthodes de délégué dans mannequin méthodes. Lorsque l'envoi ou la méthode sendto (ne me souviens pas qui) est éteint, la FIN ou RST est envoyé, et le client commence le traitement.

« Connexion réinitialisée par les pairs » semble placer le blâme sur le service, mais je ne fais pas confiance httplib2 non plus. Le client peut-être en faute?

** De plus débogage - Ressemble serveur sur Linux **

J'ai un MacBook, donc j'ai essayé de courir le service sur un seul et le site Web du client sur l'autre. Le client appelle le serveur Linux OS X sans bug (FIN ACK). Le client OS X appelle le service Linux avec le bogue (RST ACK, et un (54, 'Connexion réinitialisée par les pairs')). Ainsi, il semble que c'est le service en cours d'exécution sur Linux. Est-il x86_64? Une mauvaise glibc? wsgiref? Toujours à la recherche ...

** D'autres tests - wsgiref semble squameuse **

Nous sommes allés à la production avec Apache et mod_wsgi, et les remet à zéro de connexion ont disparu. Voir ma réponse ci-dessous, mais je vous conseille de vous connecter la réinitialisation de la connexion et réessayez. Cela vous permettra de gérer votre serveur OK en mode développement, et solidement dans la production.

Était-ce utile?

La solution

J'ai eu ce problème. Voir Le Python « Connexion réinitialisée par le serveur » problème.

Vous avez (le plus probable) dérogeait des petits problèmes de synchronisation basé sur Python mondial interprète Lock.

Vous pouvez (parfois) corriger avec un time.sleep(0.01) placé stratégiquement.

"Où?" tu demandes. Me bat. L'idée est de fournir une meilleure concurrence fil dans et autour des demandes des clients. Essayez de mettre juste avant vous faire la demande afin que le GIL est remis à zéro et l'interpréteur Python peut effacer tous les threads en attente.

Autres conseils

Ne pas utiliser wsgiref pour la production. Utilisez Apache et mod_wsgi, ou autre chose.

Nous continuons à voir ces réinitialisations de connexion, parfois souvent, avec wsgiref (le backend utilisé par le serveur de test werkzeug, et peut-être d'autres comme le serveur de test Django). Notre solution a consisté à enregistrer l'erreur, recommencez l'appel dans une boucle, et abandonner après dix échecs. httplib2 essaie deux fois, mais il nous fallait un peu plus. Ils semblent venir en grappes et -. Ajouter 1 seconde sommeil pourrait effacer la question

Nous avons jamais vu une connexion réinitialisée lors de l'exécution par Apache et mod_wsgi. Je ne sais pas ce qu'ils font différemment, (peut-être qu'ils les masquent), mais ils ne semblent pas.

Lorsque nous avons demandé à la communauté locale dev de l'aide, quelqu'un a confirmé qu'ils voient beaucoup de remises à zéro de connexion avec wsgiref qui disparaissent sur le serveur de production. Il y a un bug là, mais il va être difficile à trouver.

Je me rends compte que vous utilisez python, mais je trouve cet article Java pour être utile.

http: //java.sun. com / JavaSE / 6 / docs / / guides / technotes nets / articles / connection_release.html

Normalement, vous obtiendrez un TVD si vous faites un proche qui ne conserve pas (dans laquelle les données peuvent être mis au rebut par la pile si elle n'a pas été envoyé et ACK'd) et un FIN normal si vous permettre à la proximité de attarder (les temps d'attente de fermeture pour les données en transit à ACK'd).

Peut-être tout ce que vous devez faire est de configurer votre prise de s'attarder afin de supprimer la condition de course entre une non persistante proche fait sur la prise et les accusés de réception qui arrivent?

J'ai eu le même problème mais avec faire un téléchargement d'un fichier très volumineux en utilisant une demande python-affichage client à un nginx + uwsgi back-end.

Ce qui a fini par être la cause était le backend avait un plafond sur la taille du fichier max pour les téléchargements inférieurs à ce que le client a essayé d'envoyer.

L'erreur n'a jamais montré dans nos journaux de uwsgi depuis cette limite était en fait imposée par nginx.

Upping la limite dans nginx enlevé l'erreur.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top