Устранение неполадок, связанных с медленной работой сайта в стеке Nginx + Gunicorn + Django

Проблема, которая у меня была

У меня возникла проблема, когда некоторые сайты загружались долго (под «долгим временем» я имел в виду до 16 секунд). Иногда они могли полностью истечь по таймауту, что приводило к ошибке Nginx 504. Обычно, когда время ожидания сайта истекало, я мог перезагрузить сайт снова, и он загружался быстро. Сайт, с которым у меня возникли проблемы, получает очень низкий объем трафика. Я тестирую сайт, загружая страницу индекса администратора Django, чтобы попытаться устранить любую медлительность, которая может быть вызвана плохим кодом. Также следует отметить, что этот конкретный сайт использует только администратора Django, потому что это сайт интранет-типа только для персонала.

Настройка хостинга

Все сайты, которые я размещаю, находятся на двух облачных серверах Rackspace. Первый сервер - это мой сервер приложений с 1024 МБ ОЗУ, а второй - мой сервер базы данных с 2048 МБ ОЗУ. Сервер приложений обслуживает каждый сайт с помощью Nginx, который обслуживает все статические файлы и передает все остальное рабочим Django Gunicorn для каждого сайта.

Если посмотреть на загрузку ОЗУ и ЦП серверов баз данных, кажется, что на сервере базы данных все в порядке.

$ free -m
             total       used       free     shared    buffers     cached
Mem:          1999       1597        402          0        200       1007
-/+ buffers/cache:        389       1610
Swap:         4094          0       4094


Top shows a CPU load average of: 0.00, 0.01, 0.05

Чтобы попытаться выяснить, что происходит, я написал небольшой скрипт, который распечатывает использование памяти на сервере приложений.

Пример распечатки с анонимными доменами сайта:

Celery:     23 MB
Gunicorn:  566 MB
Nginx:       8 MB
Redis:     684 KB
Other:      73 MB

             total       used       free     shared    buffers     cached
Mem:           993        906         87          0         19         62
-/+ buffers/cache:        824        169
Swap:         2047        828       1218

Gunicorn memory usage by webste:
site01.example.com    31 MB
site02.example.com    19 MB
site03.example.com     7 MB
site04.example.com     9 MB
site05.example.com    47 MB
site06.example.com    25 MB
site07.example.com    14 MB
site08.example.com    18 MB
site09.example.com    27 MB
site10.example.com    15 MB
site11.example.com    14 MB
site12.example.com     7 MB
site13.example.com    18 MB
site14.example.com    18 MB
site15.example.com    10 MB
site16.example.com    25 MB
site17.example.com    13 MB
site18.example.com    18 MB
site19.example.com    37 MB
site20.example.com    30 MB
site21.example.com    23 MB
site22.example.com    28 MB
site23.example.com    80 MB
site24.example.com    15 MB
site25.example.com     5 MB

Пример файла конфигурации Gunicorn:

pidfile = '/var/run/gunicorn_example.com.pid'
proc_name = 'example.com'
workers = 1
bind = 'unix:/tmp/gunicorn_example.com.sock'

Пример конфигурации Nginx:

upstream example_app_server {
    server unix:/tmp/gunicorn_example.com.sock fail_timeout=0;
}

server {

    listen       80;
    server_name  example.com;
    access_log   /var/log/nginx/example.com.access.log;
    error_log    /var/log/nginx/example.com.error.log;

    location = /favicon.ico {
        return  404;
    }

    location  /static/ {
        root  /srv/sites/example/;
    }

    location  /media/ {
        root  /srv/sites/example/;
    }

    location  / {
        proxy_pass            http://example_app_server;
        proxy_redirect        off;
        proxy_set_header      Host             $host;
        proxy_set_header      X-Real-IP        $remote_addr;
        proxy_set_header      X-Forwarded-For  $proxy_add_x_forwarded_for;
        client_max_body_size  10m;
    }

}

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

Вопросы

  1. Как узнать, что медленность сайта на сайте с низким трафиком не вызвана его бездействием, которое приводит к тому, что сайт становится неактивным, что затем заставляет Gunicorn снова загружать сайт после того, как сайт стал неактивным? Есть ли настройка, предотвращающая отключение сайта?
  2. Похоже, у меня есть сайты, которые занимают слишком много памяти. Какие инструменты я могу использовать, чтобы уменьшить объем памяти, используемый сайтом? Стоит ли мне использовать некоторые инструменты профилирования Python?
  3. Какие инструменты и шаги необходимо предпринять, чтобы определить, на каком уровне стека возникает узкое место?
  4. Как лучше всего определить, заменяются ли ваши процессы Gunicorn или другие процессы?
  5. Большинство сайтов, которые я размещаю, не получают большого количества трафика, поэтому я использую только одного работника Gunicorn. Есть ли более научный способ определения и настройки количества рабочих Gunicorn на вашем сайте?
  6. Есть ли способы настроить использование меньшего объема памяти при размещении нескольких сайтов на одном сервере?

person Brent O'Connor    schedule 01.05.2012    source источник
comment
К вашему сведению, я обнаружил, что использование Munin - отличный инструмент для выявления проблем.   -  person Brent O'Connor    schedule 09.05.2012
comment
Мне также приходилось рекомендовать blitz.io, но у меня еще не было возможности им воспользоваться.   -  person Brent O'Connor    schedule 09.05.2012


Ответы (3)


Это очень много сайтов для размещения на сервере с объемом оперативной памяти всего 1 ГБ. Вы используете почти 100% памяти, и цифры, которые у вас есть, вероятно, являются «резервными» числами. Использование ОЗУ каждым процессом может увеличиваться и будет увеличиваться в процессе обслуживания запросов. Сразу же вам нужно добавить больше ОЗУ к этому экземпляру и, что лучше, переместить некоторые сайты на другой сервер.

Относительно ваших вопросов:

  1. Откуда вы взяли, что сайты становятся "неактивными", и Gunicorn затем снова загружает сайт? Это мусор. Пока процесс Gunicorn запущен (т.е.не завершен вручную или из-за ошибки на сайте), он остается полностью инициализированным и готовым к работе, будь то час или месяц.

  2. Здесь вы рубите листья, оставляя корень нетронутым. Нет ничего необычного в использовании памяти каждым процессом Gunicorn. Для работы ему требуется оперативная память. Ваша проблема заключается в том, что вы пытаетесь слишком много работать на сервере с недостаточной производительностью. Никакая оптимизация здесь вас не спасет. Вам нужно больше оперативной памяти или больше серверов. Наверное, и то, и другое.

  3. Нет нужды. Опять же, проблема уже выявлена. По цифрам, которые вы разместили, довольно ясно.

  4. Невозможно достоверно узнать, какие процессы меняются местами. Он меняется каждую секунду и зависит от того, какие из них активно работают и требуют больше ОЗУ, а какие неактивны или просто не так активны. Когда вашему серверу не хватает ресурсов, он тратит половину времени на то, чтобы выяснить, каким процессом манипулировать следующим, особенно если все они активны и соперничают за ресурсы.

  5. да. Gunicorn рекомендует 2 * ядра + 1. Итак, в двухъядерной системе это 5; на четырехъядерном - 9. Однако невозможно запустить даже 5 воркеров для каждого из этих сайтов в одной системе. Вы не можете даже запустить по одному рабочему для каждого надежно.

  6. Это зависит от «вещей». Но когда несколько сайтов размещаются на одном сервере, эти серверы становятся звериными по своим характеристикам. На небольшом, вероятно, экземпляре VPS, как у вас, особенно с 1 ГБ ОЗУ, один сайт в значительной степени ваш предел. Может, два.

person Chris Pratt    schedule 01.05.2012
comment
Я предполагаю, что вы пропустили это ... "Even though I was able to fix the issue, it took me a lot longer than I would like and I still feel like I was basically guessing at what was causing the site slowness. All this leads me to my questions..." В общем, мои вопросы были попыткой получить список шагов и инструментов, которые люди используют при устранении проблем с медленностью в стеке Django. Что касается вашего ответа на 5, я считаю, что то, что рекомендует Gunicorn, является излишним. Сайты, которые я размещаю, работают нормально с одним работником, это зависит от вашего трафика. Я искал что-то более научное. - person Brent O'Connor; 04.05.2012

1) Не знаете, что вы подразумеваете под неактивным? Как в отключенном nginx? Или просто слишком медленно, чтобы работать?

2 и 3) django-debug-toolbar и django-debug-logging будут хорошим местом для начала. Если это не помогает, пора перейти к профилированию на уровне сервера, чтобы увидеть, какие процессы вызывают проблему.

4) Используйте top: Как узнать, какие процессы подкачки в linux?

5) Да - бенчмаркинг. Выберите инструмент для тестирования производительности (например, apachebench) и запустите тесты для вашей текущей конфигурации. Подправьте что-нибудь. Снова запустите тесты. Повторяйте, пока проблемы с производительностью не исчезнут! Для достижения наилучших результатов используйте трафик, аналогичный вашему живому трафику (с точки зрения распределения URL-адресов, GET / POST и т. Д.).

6) Да, как на уровне nginx, так и на уровне приложения. Вы, вероятно, получите наибольшую пользу, профилировав каждый сайт и улучшив использование памяти (см. 2).

person Mike Ryan    schedule 08.05.2012
comment
1) Медленный ответ. В моем случае это произошло из-за того, что работника меняли местами. - person Brent O'Connor; 09.05.2012
comment
2) Я так и делаю, но на живом сервере это непрактично? - person Brent O'Connor; 09.05.2012

Касательно:

Что касается вашего ответа на 5, я считаю, что то, что рекомендует Gunicorn, является излишним.

Недавно я провел специальное тестирование с количеством рабочих и обнаружил, что, если у вас достаточно оперативной памяти, это правило 2 * ядра + 1 является довольно точным. Я обнаружил, что количество запросов в секунду увеличивалось почти линейно, пока я не приблизился к этому числу, а затем снижалось, когда ОС начала работать с ошибками.

Поскольку результаты сильно зависят от рабочей нагрузки, попробуйте разные значения и посмотрите, где ваша производительность достигает пиков.

person Scovetta    schedule 09.05.2012
comment
Это то, о чем я говорю, если ваш сайт не получает много трафика, это перебор. У меня есть один работник на всех моих сайтах, и у них быстрое время отклика. Использование того, что рекомендует Gunicorn, потребует в 3 или 4 раза больше Барана. Если у вашего сайта нет трафика, зачем тратить Ram. Я просто хотел бы, чтобы был более научный способ настройки ваших рабочих (т.е. если вы получаете X просмотров страниц, используйте X рабочих). - person Brent O'Connor; 09.05.2012
comment
@Brent Зачем тратить оперативную память не имеет особого смысла. Если у вас есть запущенный сервер, получите от него максимальную производительность (очевидно, с безопасными границами)! - person glarrain; 24.02.2013
comment
@Brent if you get X pageviews use X workers - это противоположность научного. Наука включает в себя эксперименты / измерения, а не упрощенные практические правила. - person ron rothman; 25.03.2017
comment
@glarrain да, НЕ использование ОЗУ тратит ОЗУ. - person EralpB; 18.01.2018