Apache/wsgi “Скрипт превысил время ожидания перед возвратом заголовков”

Вопрос или проблема

У меня есть кастомное приложение на Django, которое становится неотзывчивым примерно после каждых 5000 запросов. В логах apache я вижу следующее:

Apr 13 11:45:07 www3 apache2[27590]: **успешный рендер вида здесь**
...
Apr 13 11:47:11 www3 apache2[24032]: [ошибка] сервер находится в пределах MinSpareThreads MaxClients, рассмотрите возможность увеличения настройки MaxClients
Apr 13 11:47:43 www3 apache2[24032]: [ошибка] сервер достиг настройки MaxClients, рассмотрите возможность увеличения настройки MaxClients
...
Apr 13 11:50:34 www3 apache2[27617]: [ошибка] [клиент 10.177.0.204] Скрипт завершился с таймаутом до возврата заголовков: django.wsgi
(повторяется 100 раз, точно)

Я полагаю, что я использую WSGI 2.6 (/usr/lib/apache2/modules/mod_wsgi.so-2.6) со следующей конфигурацией:

конфигурация apache

WSGIDaemonProcess site-1 user=django group=django threads=50
WSGIProcessGroup site-1
WSGIScriptAlias / /somepath/django.wsgi

/somepath/django.wsgi

import os, sys
sys.path.append('/home/django')
os.environ['DJANGO_SETTINGS_MODULE'] = 'myapp.settings'    
import django.core.handlers.wsgi    
application = django.core.handlers.wsgi.WSGIHandler()

Когда это происходит, я могу убить процесс wsgi, и сервер восстанавливается.

>ps aux|grep django # процесс работает от имени пользователя "django"
django   27590  5.3 17.4 908024 178760 ?       Sl   Apr12  76:09 /usr/sbin/apache2 -k start
>kill -9 27590

Это заставляет меня думать, что проблема является известной проблемой:

deadlock-timeout=sss (2.0+)

Определяет максимальное количество секунд,
которые могут пройти прежде, чем демон
процесс будет отключен и перезапущен
после обнаружения потенциального взаимного
блокирования (deadlock) на
GIL Python. Значение по умолчанию — 300 секунд. Эта опция
существует, чтобы бороться с проблемой
замораживания демона
процесса в результате неправильного
освобождения GIL Python модулем
C-расширения Python при выполнении
блокирующей или длительной операции.

Тем не менее, я не уверен, почему это условие не очищается автоматически. Я вижу, что тайм-аут скрипта возникает ровно через 5 минут после последнего успешного рендеринга страницы, так что тайм-аут взаимной блокировки срабатывает. Но он фактически не убивает процесс.

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

  • версия apache 2.2, используется worker MPM
  • версия wsgi 2.8
  • SELinux НЕ установлен
  • пакет xml используется, нечасто
  • Ubuntu 10.04

Вы можете попробовать добавить лимит запросов, после которого процессы демонов будут перезагружаться (до того, как сделает это внешний процесс).
Это делается путем добавления параметра maximum-requests для WSGIDaemonProcess.

Смотрите https://code.google.com/p/modwsgi/wiki/ConfigurationGuidelines#Defining_Process_Groups

В качестве альтернативы вы можете узнать, сколько процессов может иметь ваш пользователь ‘django’.
Вы можете это проверить, открыв оболочку от имени этого пользователя su - django -s /bin/bash и проверив вывод команды ulimit -a.

Ответ или решение

Проблема, с которой вы столкнулись, в значительной степени связана с ограничениями настроек Apache и модуля mod_wsgi, и она может возникать по нескольким причинам, включая недостаточный размер пула процессов, зависание запросов, а также потенциальные проблемы с блокировкой GIL в Python. Вот несколько шагов, которые могут помочь вам решить эту проблему.

1. Увеличение параметров MaxClients и Threads

В вашем случае вы видите сообщения о том, что сервер достиг максимального числа клиентов (MaxClients). Чтобы это исправить, рассмотрите возможность увеличения параметров:

  • MaxClients: Установите его в большее значение в конфигурации Apache. Например:

    MaxClients 150

    Проверьте соответствие этому параметру с доступной памятью и ресурсами вашего сервера.

  • Threads: Увеличьте количество потоков для вашего процесса WSGI, если ваша система поддерживает это. Вы можете изменить определение вашей WSGIDaemonProcess, добавив больше потоков:

    WSGIDaemonProcess site-1 user=django group=django threads=75

2. Параметр максимального числа запросов

Рекомендуется добавить параметр maximum-requests в вашу конфигурацию WSGIDaemonProcess. Это позволит ваши демоны WSGI перезапускаться после обработки определённого количества запросов, что может помочь "освободить" потенциальные проблемы с зависанием и утечкой памяти:

WSGIDaemonProcess site-1 user=django group=django threads=50 maximum-requests=1000

3. Настройка параметра deadlock-timeout

Как вы упомянули, параметр deadlock-timeout может быть полезен, если у вас происходят зависания. Попробуйте уменьшить время, чтобы быстрее перезапускать процессы, когда выявляется потенциальная блокировка:

WSGIDaemonProcess site-1 user=django group=django threads=50 deadlock-timeout=60

4. Проверка ulimit для пользователя Django

Важно также проверить настройки ulimit для пользователя django, чтобы убедиться, что ему разрешено достаточно процессов. Используйте следующую команду:

su - django -s /bin/bash -c "ulimit -a"

Если значение max user processes низкое, вы можете увеличить его в файле /etc/security/limits.conf.

5. Мониторинг и логгирование

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

6. Обновление модулей

Проверьте, используете ли вы актуальные версии Apache, mod_wsgi и Django. Обновление до последней стабильной версии может устранить ряд известных ошибок, связанных с производительностью и стабильностью.

Заключение

Если выполнение этих шагов не решит вашу проблему, возможно, стоит исследовать конкретные запросы к вашему Django-приложению, которые могут тормозиться или зависать. Это могут быть сложные запросы к базе данных, внешние API или длинные вычисления. Используйте профилирование производительности, чтобы выявить узкие места в вашем коде. Если после всех изменений поведение приложения не станет лучше, возможно, придется рассмотреть более масштабные архитектурные изменения, такие как переход на более высокопроизводительные серверы или использование альтернативных подходов к обработке запросов (например, с использованием Celery для долгих задач).

Если у вас останутся вопросы или проблемы, не стесняйтесь обращаться за помощью!

Оцените материал
Добавить комментарий

Капча загружается...