Иногда по долгу службы приходится программировать всякое на python, иногда даже какой-то бэкенд. Я обычно использую FastAPI для этого. Кстати, мой сайт devopsoffer написан целиком и полностью на этом фреймворке.
Gunicorn — это синхронный сервер приложений WSGI на Python. Напомню, что WSGI — это стандарт интерфейса между веб-серверами и Python веб-приложениями, созданный для синхронных приложений.
Uvicorn, в свою очередь, — это асинхронный сервер ASGI, который поддерживает приложения на FastAPI и Starlette и позволяет использовать асинхронное выполнение запросов. Как правило, их используют вместе для запуска асинхронных приложений, например, так:
gunicorn src.main:app --workers 5 --worker-class uvicorn.workers.UvicornWorker --bind 127.0.0.1:8085
Эта связка позволяет взять лучшее из обоих решений. Gunicorn создаёт количество воркеров, заданное в параметре --workers, и каждый воркер — это отдельный процесс. Таким образом, каждый воркер получает свой GIL (Global Interpreter Lock), что позволяет обойти его ограничения в плане параллельности. Внутри каждого воркера запускается Uvicorn, который обрабатывает HTTP-запросы асинхронно.
Внутри Uvicorn также можно использовать многопоточность, но это чаще применяется для асинхронной обработки, когда происходит освобождение GIL при I/O-bound операциях, таких как работа с сетью и базой данных.
Как итог, подобная связка дает возможность одновременно обрабатывать множество запросов внутри одного воркера, эффективно сочетая многопроцессность для параллельного выполнения и асинхронность для обработки операций, требующих ожидания.
Для расчёта оптимального количества воркеров Gunicorn часто используют формулу: workers=(кол-во ядер)×2+1.
Эта формула может служить хорошей отправной точкой, но реальные значения зависят от нагрузки и характера приложения, и оптимальные параметры часто выявляются опытным путём.
#python