Estou executando o Django atrás do nginx usando o FastCGI. Descobri que em algumas das respostas enviadas ao cliente, ocorre corrupção aleatória de dados no meio das respostas (pode haver algumas centenas de bytes no meio).
Neste ponto, reduzi-o a ser um bug no manipulador FastCGI do nginx ou no manipulador FastCGI do Django (ou seja, provavelmente um bug no flup), pois esse problema nunca ocorre quando eu executo o servidor Django no modo autônomo (ou seja runserver
). Isso acontece apenas no modo FastCGI.
Outras tendências interessantes:
Tende a acontecer com respostas maiores. Quando um cliente efetua login pela primeira vez, eles recebem um monte de blocos de 1 MB para sincronizá-los com o banco de dados do servidor. Após a primeira sincronização, as respostas são muito menores (geralmente alguns KB de cada vez). A corrupção sempre parece ocorrer nos blocos de 1 MB enviados no início.
Isso acontece com mais frequência quando o cliente está conectado ao servidor via LAN (ou seja, conexão de baixa latência e alta largura de banda). Isso me faz pensar que há algum tipo de condição de corrida no nginx ou flup que é exacerbada por um aumento da taxa de dados.
No momento, eu tive que contornar isso colocando um resumo SHA1 extra no cabeçalho de resposta e solicitando ao cliente que rejeitasse respostas onde o cabeçalho não coincidisse com a soma de verificação do corpo, mas essa é uma solução horrível.
Alguém já experimentou algo assim, ou tem alguma dica sobre como identificar se é o flup ou o nginx que está com falha aqui, para que eu possa registrar um bug com a equipe apropriada?
Agradecemos antecipadamente por qualquer ajuda.
Nota: Eu também postou um bug similar em lighttpd + FastCGI + Django um tempo atrás aqui: /programming/3714489/lighttpd-fastcgi-django-truncated-response-sent-to-client-due-to -inesperado ... mesmo que isso não seja a mesma coisa (truncamento x corrupção), está começando a parecer que o culpado mais comum é o flup / Django, em vez do servidor da web.
Edit: Também devo observar qual é o meu ambiente:
OSX 10.6.6 em um Mac Mini
Python 2.6.1 (Sistema)
Django 1.3 (do tarball oficial)
flup 1.0.2 (do ovo Python no site flup)
nginx + ssl 1.0.0 (de Macports)
EDIT: Em resposta ao comentário de Jerzyk, o caminho do código que monta a resposta se parece (editado para ser sucinto):
# 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
Eu não acho que é possível que o Comprimento do Conteúdo esteja errado com base nisso, e o AFAIK não tem como marcar um objeto Django HttpResponse como explicitamente binário em oposição ao texto. Além disso, como o problema ocorre apenas de forma intermitente, não creio que isso explique o contrário, provavelmente você o veria em todas as solicitações.
EDIT @ionelmc: Você precisa definir o comprimento do conteúdo no Django - o nginx não define isso para você, conforme o exemplo abaixo, uma vez que eu desabilitei a definição explícita do comprimento do conteúdo:
$ 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