Lighttpd + fastcgi + django: усеченный ответ, отправленный клиенту из-за неожиданного EOF - PullRequest
0 голосов
/ 15 сентября 2010

Я пытаюсь перевести мое веб-приложение на Django в рабочую конфигурацию развертывания, и, потратив кучу времени, пытаясь заставить его работать под lighttpd / fastcgi, не могу обойти эту проблему.Когда клиент входит в систему в первый раз, он получает большой дамп данных с сервера, который разбивается на несколько кусков размером ~ 1 МБ, которые отправляются обратно в формате 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 

Я действительно выдергиваю волосы, пытаясь понять, почему это происходит (чего не происходит, когдазапуск Django в режиме ./manage.py runserver).Следующие вещи, которые я пробовал, не дали никакого эффекта:

  • Уменьшение размера чанка с 1 МБ до 256 КБ.Несмотря на то, что усечение обычно происходит при отметке 600–900 КБ, я все еще получал усечения при размере фрагмента 256 КБ.

  • Установка значений minspare и maxchildren на Джанго runfgci очень высоко, так что вокруг будет висеть множество запасных нитей.

  • Установка maxchildren на 1, чтобы была только одна резьба.

  • Переключение между режимом сокета UNIX и режимом TCP / IP для соединения fastcgi между lighttpd и Django.

Я много гуглил для этого, но не смог найти ничего, чтоказалось, что исправление для Django (любая помощь, казалось, была вокруг настройки PHP).

Моя настройка:

  • OSX 10.6.4

  • Python 2.6.1 (система)

  • lighttpd установлен из Macports (1.4.26_1 + ssl)

  • flupустановлен с последней версии Python egg на веб-сайте flup (пробовал стабильную версию 1.0.2 и последнюю версию 1.0.3)

  • Django 1.2.1 установлен из tarball на сайте Django

Блок FastCGI в моей конфигурации lighttpd:

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
                                 )
                               )
                             )

Команда runfcgi, которую я использую для запуска Djangoв настоящее время:

./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, и перспектива перехода на другую конфигурацию веб-сервера я не ожидаю ...

Заранее благодарен за любую помощь.

Редактировать: Дополнительная информация

Я нашел эту страницу на светлых форумах с указаниемчто это может быть вина Джанго ... в этом случае это был тот сбой PHP.Я проверил материал на стороне Django и обнаружил, что даже после усечения поток Python, отправивший усеченный ответ, все равно будет работать после этого и будет обслуживать последующие запросы, поэтому создается впечатление, что поток не прерывается потоком, попавшим в исключениеи вылетает.

Я хотел выяснить, был ли здесь виноват 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 отправляет TCP FIN в Django, который, вероятно, вызывает прерывание соединения, и именно так вы получаете усечение.

На первый взгляд кажется, что это ошибка Lighttpd, поскольку он выглядит так, как будто отключается, прежде чем должен… хотя я не уверен, что он этого не делает, потому что он получил некоторые плохие данные от Django, на которые он реагирует отключением.

Ответы [ 2 ]

1 голос
/ 16 сентября 2010

Что бы это ни стоило, я в конце концов бросил корабль на nginx, и все, кажется, работает нормально, так что мое подозрение, что это была ошибка lighttpd, а не глючный fcgi impl в Django, кажется вполне обоснованным.

На самом деле я обнаружил, что установка nginx намного проще, чем lighttpd, не говоря уже о том, что вы можете установить macport из nginx (port install nginx + ssl), который не содержит ошибку взлома SSL, что lighttpd страдает от здесь .

0 голосов
/ 15 сентября 2010

Вы уверены, что у вас еще ничего не прослушивается на порту 8000. Этот порт обычно используется для HTTP-серверов по соглашению, и было бы плохой идеей запустить на нем процесс FASTCGI. Предлагаем вам использовать другой порт, который не находится рядом с диапазоном 8xxx.

...