Как остановить WSGI от зависания apache - PullRequest
9 голосов
/ 03 августа 2009

У меня Django работает через WSGI, как это:

<VirtualHost *:80>
    WSGIScriptAlias / /home/ptarjan/django/django.wsgi
    WSGIDaemonProcess ptarjan processes=2 threads=15 display-name=%{GROUP}
    WSGIProcessGroup ptarjan
    Alias /media /home/ptarjan/django/mysite/media/
</VirtualHost>

Но если в Python я делаю:

def handler(request) :
    data = urllib2.urlopen("http://example.com/really/unresponsive/url").read()

весь сервер apache зависает и не отвечает на эту обратную трассировку

#0  0x00007ffe3602a570 in __read_nocancel () from /lib/libpthread.so.0
#1  0x00007ffe36251d1c in apr_file_read () from /usr/lib/libapr-1.so.0
#2  0x00007ffe364778b5 in ?? () from /usr/lib/libaprutil-1.so.0
#3  0x0000000000440ec2 in ?? ()
#4  0x00000000004412ae in ap_scan_script_header_err_core ()
#5  0x00007ffe2a2fe512 in ?? () from /usr/lib/apache2/modules/mod_wsgi.so
#6  0x00007ffe2a2f9bdd in ?? () from /usr/lib/apache2/modules/mod_wsgi.so
#7  0x000000000043b623 in ap_run_handler ()
#8  0x000000000043eb4f in ap_invoke_handler ()
#9  0x000000000044bbd8 in ap_process_request ()
#10 0x0000000000448cd8 in ?? ()
#11 0x0000000000442a13 in ap_run_process_connection ()
#12 0x000000000045017d in ?? ()
#13 0x00000000004504d4 in ?? ()
#14 0x00000000004510f6 in ap_mpm_run ()
#15 0x0000000000428425 in main ()

в Debian Apache 2.2.11-7.

Точно так же можем ли мы быть защищены от:

def handler(request) :
    while (1) :
        pass

В PHP я бы установил ограничения по времени и памяти.

Ответы [ 2 ]

13 голосов
/ 04 августа 2009

Это не «тайм-аут тупика», который вы хотите, как указано другим, это для особой цели, которая не поможет в этом случае.

Что касается попыток использовать функции mod_wsgi, то вместо этого вам нужна опция 'inactivity-timeout' для директивы WSGIDaemonProcess.

Даже тогда это не полное решение. Это связано с тем, что опция 'inactivity-timeout' предназначена специально для определения того, прекратилась ли вся обработка запроса процессом-демоном, это не тайм-аут на запрос. Он равняется тайм-ауту на запрос, только если процессы демона являются однопоточными. Помимо помощи в откреплении процесса, опция также будет иметь побочный эффект перезапуска процесса-демона, если в это время вообще не поступают запросы.

Короче говоря, на уровне mod_wsgi нет способа иметь время ожидания для каждого запроса, это потому, что в Python нет реального способа прерывания запроса или потока.

Что вам действительно нужно реализовать, так это время ожидания HTTP-запроса в коде вашего приложения. Я не уверен, где он находится и доступен ли он, но выполните поиск в Google по запросу "urllib2 socket timeout".

3 голосов
/ 03 августа 2009

Если я хорошо понимаю вопрос, вы хотите защитить apache от блокировки при запуске случайных сценариев от людей. Что ж, если вы используете ненадежный код, я думаю, у вас есть другие поводы для беспокойства, которые хуже, чем apache.

Тем не менее, вы можете использовать некоторые директивы конфигурации для настройки более безопасной среды. Эти два ниже очень полезны:

  • WSGIApplicationGroup - Устанавливает, к какой группе приложений относится приложение WSGI. Это позволяет разделить настройки для каждого пользователя - все приложения WSGI в пределах одной группы приложений будут выполняться в контексте одного и того же суб-интерпретатора Python процесса, обрабатывающего запрос.

  • WSGIDaemonProcess - Настраивает отдельный процесс-демон для запуска приложений. Процессы демона можно запускать как пользователь, отличный от того, кем обычно запускаются дочерние процессы Apache. Эта директива принимает много полезных опций, я перечислю некоторые из них:

    • user=name | user=#uid, group=name | group=#gid:

      Определяет имя пользователя и группы UNIX, числовой идентификатор пользователя или групповой идентификатор пользователя / группы, для которых должны выполняться процессы демона.

    • stack-size=nnn

      Объем виртуальной памяти в байтах, выделяемый для стека, соответствующего каждому потоку, созданному mod_wsgi в процессе демона.

    • deadlock-timeout=sss

      Определяет максимальное количество секунд, которое может пройти, прежде чем процесс демона будет остановлен и перезапущен после обнаружения потенциальной тупиковой ситуации в Python GIL. Значение по умолчанию составляет 300 секунд.

Подробнее о директивах конфигурации можно прочитать здесь .

...