J'exécute Django derrière nginx en utilisant FastCGI. J'ai découvert que dans certaines des réponses envoyées au client, une corruption de données aléatoire se produit au milieu des réponses (peut-être quelques centaines d'octets au milieu).
À ce stade, je l'ai réduit à un bug dans le gestionnaire FastCGI de nginx ou dans le gestionnaire FastCGI de Django (c'est-à-dire probablement un bogue en flup), car ce problème ne se produit jamais lorsque j'exécute le serveur Django en mode autonome (c'est-à-dire runserver
). Cela ne se produit qu'en mode FastCGI.
Autres tendances intéressantes:
Cela a tendance à se produire sur des réponses plus importantes. Lorsqu'un client se connecte pour la première fois, il reçoit un groupe de blocs de 1 Mo pour les synchroniser avec la base de données du serveur. Après cette première synchronisation, les réponses sont beaucoup plus petites (généralement quelques Ko à la fois). La corruption semble toujours se produire sur ces morceaux de 1 Mo envoyés au début.
Cela se produit plus souvent lorsque le client est connecté au serveur via LAN (c'est-à-dire une connexion à faible latence et à large bande passante). Cela me fait penser qu'il existe une sorte de condition de concurrence dans nginx ou flup qui est exacerbée par un débit de données accru.
En ce moment, j'ai dû contourner cela en mettant un résumé SHA1 supplémentaire dans l'en-tête de réponse et en demandant au client de rejeter les réponses lorsque l'en-tête ne correspond pas à la somme de contrôle du corps, mais c'est une sorte de solution horrible.
Quelqu'un d'autre a-t-il vécu quelque chose comme ça, ou a-t-il des conseils sur la façon d'identifier si c'est flup ou nginx qui est en cause ici afin que je puisse déposer un bogue avec l'équipe appropriée?
Merci d'avance pour votre aide.
Remarque: j'ai également publié un bug similaire dans lighttpd + FastCGI + Django il y a quelque temps ici: /programming/3714489/lighttpd-fastcgi-django-truncated-response-sent-to-client-due-to -inattendu ... même si ce n'est pas la même chose (troncature vs corruption), ça commence à ressembler au coupable commun est flup / Django plutôt que le serveur web ..
Edit: je devrais également noter quel est mon environnement:
OSX 10.6.6 sur un Mac Mini
Python 2.6.1 (système)
Django 1.3 (du tarball officiel)
flup 1.0.2 (de l'oeuf Python sur le site de flup)
nginx + ssl 1.0.0 (de Macports)
EDIT: En réponse au commentaire de Jerzyk, le chemin de code qui assemble la réponse ressemble (édité pour être succinct):
# This returns an objc NSData object, which is an array.array
# when pushed through the PyObjC bridge
ret = handler( request )
response = HttpResponse( ret )
response[ "Content-Length" ] = len( ret )
return response
Je ne pense pas qu'il soit possible que la longueur du contenu soit erronée sur cette base, et AFAIK il n'y a aucun moyen de marquer un objet Django HttpResponse comme explicitement binaire par opposition au texte. De plus, comme le problème ne se produit que de manière intermittente, je ne pense pas que cela l'explique autrement, vous le verriez probablement à chaque demande.
EDIT @ionelmc: Vous devez définir la longueur du contenu dans Django - nginx ne le définit pas pour vous, comme dans l'exemple ci-dessous une fois que j'ai désactivé la définition de la longueur du contenu explicitement:
$ curl -i http://localhost/io/ping
HTTP/1.1 200 OK
Server: nginx/1.0.0
Date: Thu, 23 Jun 2011 13:37:14 GMT
Content-Type: text/html; charset=utf-8
Transfer-Encoding: chunked
Connection: keep-alive
AKSJDHAKLSJDHKLJAHSD
la source
Réponses:
Avez-vous une sorte de directive de mise en cache nginx (bypass / no_cache) active pour les réponses fastcgi?
Dans nginx '1.0.3 Changenotes, ils ont corrigé une corruption de réponse:
Source: http://nginx.org/en/CHANGES (section 1.0.3.)
la source
Peut-être que la corruption occasionnelle ne se produit que si la sortie contient au moins un caractère UTF-8.
Content-length et string length ne sont pas la même chose, car un caractère UTF-8 peut contenir de 2 à 5 octets.
la source
Une façon de résoudre ce cas un peu plus serait de:
Une fois que vous avez détecté une erreur côté client (basée sur sha1), accédez à la capture réseau, examinez le flux enregistré (TCP) et essayez de savoir si le problème est généré par nginx ou provient-il (directement) de django .
la source
J'ai eu un problème très similaire qui me tourmentait depuis aussi longtemps que j'avais cette configuration. Comme vous, j'utilise FastCGI, Nginx et macOS, et j'ai trouvé une corruption aléatoire au milieu de demandes importantes (c'était environ 2% des demandes d'un document de 1,5 Mo).
J'ai pu résoudre mon problème en passant aux sockets Unix via TCP pour la connexion FastCGI entre PHP-FPM (dans mon cas) et Nginx. Je ne sais pas quelle pièce du puzzle est responsable de la corruption, mais éviter la connexion TCP interne l'a corrigé.
la source