Estou executando o Django por trás do nginx usando o FastCGI. Descobri que, em algumas das respostas enviadas ao cliente, ocorre uma corrupção aleatória de dados no meio das respostas (pode ser de 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 (isto é, provavelmente um bug no flup), já que esse problema nunca ocorre quando eu executo o servidor Django em independente (ou seja, runserver
). Acontece apenas no modo FastCGI.
Outras tendências interessantes:
-
Isso tende a acontecer em respostas maiores. Quando um cliente faz o login pela primeira vez, eles recebem um monte de blocos de 1 MB para sincronizá-los no banco de dados do servidor. Depois dessa primeira sincronização, as respostas são muito menores (geralmente alguns KB por vez). A corrupção parece sempre acontecer naqueles pedaços de 1MB enviados no início.
-
Acontece com mais frequência quando o cliente está conectado ao servidor via LAN (por exemplo, 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 na taxa de dados.
Neste momento, tive que contornar isso colocando um resumo SHA1 extra no cabeçalho de resposta e fazendo com que o cliente rejeitasse respostas em que o cabeçalho não correspondia à soma de verificação do corpo, mas essa é uma solução horrível .
Alguém mais experimentou algo assim, ou tem alguma indicação sobre como identificar se é flup ou nginx que está com defeito aqui, para que eu possa registrar um bug com a equipe apropriada?
Agradecemos antecipadamente por qualquer ajuda.
Nota: Eu também postei um bug similar no lighttpd + FastCGI + Django um tempo atrás: link ... mesmo que isso não seja a mesma coisa (truncation vs corruption), ele está começando a parecer que o culpado comum é flup / Django ao invés do servidor web ..
Editar: também devo observar o que é 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 parece (editado para 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 Content-Length 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 acontece apenas de forma intermitente, não acho que isso explique, caso contrário, presumivelmente, você o veria a cada solicitação.
EDIT @ionelmc: Você precisa definir o Content-Length no Django - o nginx não define isso para você, conforme o exemplo abaixo, uma vez que eu desativei explicitamente o 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