Возьмем за пример стек Nginx + Gunicorn + Django.
Бывает, что при наплыве трафика, Nginx отвечает ошибкой 5хх, а в логе Django ошибок нет.
Вы также можете увидеть, что Nginx говорит: "not enough workers". Это фиксится очень просто и уже есть довольно старая статья на Хабре, которая всё ещё актуальна: Ускоряем Nginx за 5 минут / Хабр (habr.com).
Единственное, что в новых версиях worker_processes
лучше оставить auto
.
Но Вы также можете всё ещё видеть upstream response error (timedout).
В таком случае мы обращаем внимание на Gunicorn.
Есть разные виды воркеров: Sync, Async, Gthread, Tornado, AsyncIO.
Самая распространённая конфигурация из мануалов по настройке:gunicorn --workers 3 wsgi:app
В данном случае используются Sync воркеры, для нашего примера, а также для большинства это наиболее подходящий и универсальный вариант.
Какое количество воркеров оптимально?
Считается формулой: (Количество ядер процессора)*2+1
Итого, конфигурация выше подходит для серверов с одним ядром, если ядер больше, то можно смело увеличивать количество воркеров по формуле, но если нет, увеличение количества воркеров приведет к принудительной перезагрузке Gunicorn'a системой, т.к. тот начнет утилизировать весь процессор:
gunicorn.service: A process of this unit has been killed by the OOM killer
То есть, для сервера с 2 ядрами, лучшая конфигурация будет такая:gunicorn --workers 5 wsgi:app
А также, у Sync воркеров есть Gthread класс:gunicorn --workers 5 --threads 2 wsgi:app
Указывая параметр тредов, воркеры автоматически становятся класса Gthread.
Треды помогут увеличить производительность, если количество воркеров уже не увеличить.
Такая настройка подходит для не слишком требовательных к CPU, быстрых запросов, I/O операций, SQL. В общем и целом, использование тредов помогает уменьшить утилизацию памяти Gunicorn'ом.
Такая вот небольшая шпаргалка по оптимизации Gunicorn, надеюсь, кому-то будет полезно!
UPDATE:
В новых версиях Gunicorn улучшен параллелизм, можете попробовать умножить количество воркеров на 4.
Чтобы не гадать, а найти для своего проекта лучшую конфигурацию, используйте Hey HTTP load generator.
Таким нехитрым путем, я обнаружил, что производительность моего бэкэнда стала лучше без тредов, просто оптимизировав количество воркеров.
IvanZaycev0717
А почему бы нам не автоматизировать использование данной формулы для автоопределения количества дотсупных логических ядер на виртуальной машине. Например, с помощью такого скрипта gunicorn.conf.py
Ну а дальше все очень просто:
Ryav
Крайне не рекомендую множить на 2 виртуальные ядра (в моём случае с EC2), поскольку виртуальная машина перестаёт вывозить.