Lighttpd + fastcgi + django:由于意外的EOF而发送到客户端的截断响应

时间:2010-09-15 03:38:16

标签: django macos fastcgi lighttpd flup

我正在尝试将基于Django的Web应用程序转换为可用的部署配置,并且在花费大量时间尝试使其在lighttpd / fastcgi下运行之后,无法解决此问题。当客户端第一次登录时,它们会从服务器接收大量数据转储,这些数据转储被分成几个大小约为1MB的块,这些块以JSON形式发回。

每隔一段时间,客户端就会收到其中一个块的截断响应,我会在lighttpd日志中看到这条消息:

2010-09-14 23:25:01: (mod_fastcgi.c.2582) unexpected end-of-file (perhaps the fastcgi process died): pid: 0 socket: tcp:127.0.0.1:8000 
2010-09-14 23:25:01: (mod_fastcgi.c.3382) response already sent out, but backend returned error on socket: tcp:127.0.0.1:8000 for /myapp.fcgi?, terminating connection 

我真的在试图找出发生这种情况的原因(在./manage.py runserver模式下运行Django时不会发生这种情况)。以下是我尝试过但没有效果的事情:

  • 将块大小从1MB减少到256K。即使截断通常发生在600K - 900K左右,我仍然在256K块大小下截断。

  • 将Django的minspare上的maxchildrenrunfgci值设置得非常高,这样就会有很多备用线程。

  • maxchildren设置为1,以便只有一个帖子。

  • 在UNIX套接字模式和TCP / IP模式之间切换,以实现lighttpd和Django之间的fastcgi连接。

我已经搜索了很多东西,但找不到任何似乎是Django的修复程序(任何帮助似乎都在调整PHP设置)。

我的设置是:

  • OSX 10.6.4

  • Python 2.6.1(系统)

  • 从Macports安装的lighttpd(1.4.26_1 + ssl)

  • 从flup网站上的最新Python蛋安装的flup(尝试了1.0.2稳定和最新的1.0.3开发)

  • 在Django网站上从tarball安装的Django 1.2.1

我的lighttpd配置中的FastCGI块是:

fastcgi.server             = ("/myapp.fcgi" =>
                               ("django" =>
                                 (
                                  #"socket" => lighttpd_base + "fcgi.sock",
                                  "host" => "127.0.0.1",
                                  "port" => 8000,
                                  "check-local" => "disable",
                                  "max-procs" => 1,
                                  "debug" => 1
                                 )
                               )
                             )

我用来启动Django的runfcgi命令目前是:

./manage.py runfcgi daemonize=false debug=true host=127.0.0.1 port=8000 
method=threaded maxchildren=1

如果有人知道如何阻止这种情况发生,那么我们将非常感谢您的帮助。如果我不能相对快速地解决这个问题,我将不得不放弃lighttpd + fastcgi并查看Apache + mod_wsgi或者nginx + fastcgi,并且进入另一个webserver配置的前景不是我期待的......

提前感谢您的帮助。

修改:其他信息

我在轻松的论坛上发现this page表明它可能是Django的错...在那种情况下,PHP正在崩溃。我检查了我的Django方面的东西并发现即使在截断之后,发送截断响应的Python线程仍然会在之后运行并且将服务于后续请求,所以看起来流不会被线程打破异常并且崩溃了。

我想弄清楚是不是Django的fcgi impl或Lighttpd在这里有问题(因为这将决定是否移动到nginx + fastcgi实际上会解决任何问题),所以我看看了这个数据包在Wireshark中追踪。在截断之前发生的事情的简化日志如下:

No.     Time        Info
30082   233.411743  django > lighttpd [PSH, ACK] Seq=860241 Ack=869 Win=524280 Len=8184 TSV=417114153 TSER=417114153
30083   233.411749  lighttpd > django [ACK] Seq=869 Ack=868425 Win=524280 Len=0 TSV=417114153 TSER=417114153
30084   233.412235  django > lighttpd [PSH, ACK] Seq=868425 Ack=869 Win=524280 Len=8 TSV=417114153 TSER=417114153
30085   233.412250  lighttpd > django [ACK] Seq=869 Ack=868433 Win=524280 Len=0 TSV=417114153 TSER=417114153
30086   233.412615  django > lighttpd [PSH, ACK] Seq=868433 Ack=869 Win=524280 Len=8184 TSV=417114153 TSER=417114153
30087   233.412628  lighttpd > django [ACK] Seq=869 Ack=876617 Win=524280 Len=0 TSV=417114153 TSER=417114153
30088   233.412723  lighttpd > django [FIN, ACK] Seq=869 Ack=876617 Win=524280 Len=0 TSV=417114153 TSER=417114153
30089   233.412734  django > lighttpd [ACK] Seq=876617 Ack=870 Win=524280 Len=0 TSV=417114153 TSER=417114153
30090   233.412740  [TCP Dup ACK 30088#1] lighttpd > django [ACK] Seq=870 Ack=876617 Win=524280 Len=0 TSV=417114153 TSER=417114153
30091   233.413051  django > lighttpd [PSH, ACK] Seq=876617 Ack=870 Win=524280 Len=8 TSV=417114153 TSER=417114153
30092   233.413070  lighttpd > django [RST] Seq=870 Win=0 Len=0

良好的数据包在开始时来自Django(30082为8184字节,然后再在30086为另外8184字节)然后在入口30088由于某种原因Lighttpd向Django发送TCP FIN,这可能是是什么导致连接终止,这就是截断的方式。

从表面上看,似乎这是Lighttpd的错,因为看起来它在关闭事情之前应该关闭......虽然我不确定它是不是因为它收到了来自Django的一些不良数据,它通过关闭来做出反应。

2 个答案:

答案 0 :(得分:1)

为了它的价值,我最终最终跳到了nginx并且一切似乎工作正常,所以我怀疑它是lighttpd的错,而不是Django中的一个错误的fcgi impl似乎是有充分根据的。

我实际上发现nginx的设置比lighttpd容易得多,更不用说你可以安装一个nportx的macport(端口安装nginx + ssl)包含破解SSL的bug lighttpd遭受here

答案 1 :(得分:0)

您确定没有其他东西已经在端口8000上侦听。该端口通常按惯例用于HTTP服务器,并且在其上运行FASTCGI进程是个坏主意。建议您在8xxx范围附近使用不同的端口。