nginx + fastCGI + Django - 在发送给客户端的响应中出现数据损坏

gle*_*enc 10 nginx fastcgi corruption django

我正在使用 FastCGI 在 nginx 后面运行 Django。我发现在发送给客户端的一些响应中,响应中间发生了随机数据损坏(中间可能有几百个字节左右)。

在这一点上,我已将其范围缩小为 nginx 的 FastCGI 处理程序或 Django 的 FastCGI 处理程序中的错误(即可能是 flup 中的错误),因为当我在独立(即runserver)模式下运行 Django 服务器时,从未发生此问题。它只发生在 FastCGI 模式下。

其他有趣的趋势:

  • 它往往发生在较大的响应上。当客户端第一次登录时,它们会被发送一堆 1MB 块以将它们同步到服务器数据库。在第一次同步之后,响应要小得多(通常一次只有几 KB)。损坏似乎总是发生在开始时发送的那些 1MB 块上。

  • 当客户端通过 LAN 连接到服务器(即低延迟、高带宽连接)时,这种情况发生得更频繁。这让我觉得在 nginx 或 flup 中存在某种竞争条件,并且会因数据速率的增加而加剧。

现在,我不得不通过在响应标头中放置一个额外的 SHA1 摘要来解决这个问题,并让客户端拒绝标头与正文校验和不匹配的响应,但这是一种可怕的解决方案。

有没有其他人经历过这样的事情,或者有任何关于如何确定是 flup 还是 nginx 有问题的指示,以便我可以向适当的团队提交错误?

在此先感谢您的帮助。

注意:我也在 lighttpd + FastCGI + Django 中发布了一个类似的错误:https : //stackoverflow.com/questions/3714489/lighttpd-fastcgi-django-truncated-response-sent-to-client-due-to - 出乎意料......即使这不是一回事(截断与损坏),它开始看起来像共同的罪魁祸首是 flup / Django 而不是 web 服务器..

编辑:我还应该注意我的环境是什么:

  • Mac Mini 上的 OSX 10.6.6

  • Python 2.6.1(系统)

  • Django 1.3(来自官方压缩包)

  • flup 1.0.2(来自 flup 站点上的 Python egg)

  • nginx +ssl 1.0.0(来自 Macports)

编辑:为了回应 Jerzyk 的评论,组装响应的代码路径看起来像(为了简洁而编辑):

# 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
Run Code Online (Sandbox Code Playgroud)

基于此,我认为 Content-Length 不可能是错误的,而且 AFAIK 没有办法将 Django HttpResponse 对象标记为明确的二进制而不是文本。此外,由于问题只是间歇性发生,我认为这不能解释它,否则您可能会在每个请求中看到它。

编辑@ionelmc:您必须在 Django 中设置 Content-Length - nginx 不会为您设置此项,根据以下示例,一旦我明确禁用了设置 Content-Length:

$ 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
Run Code Online (Sandbox Code Playgroud)

小智 0

解决此问题的一种方法是:

  • 让 nginx 和 django 在不同的硬件上运行(以便您可以轻松捕获流量)
  • 捕获从客户端到--/-> nginx的流量以及nginx --/-> django(即使用wireshark)

一旦您在客户端检测到错误(基于 sha1),请转到网络捕获,查看记录的(TCP)流并尝试查找问题是由 nginx 产生的还是(直接)来自 django 。