Asgi что это
Перейти к содержимому

Asgi что это

  • автор:

ASGI-фреймворк Starlette

Starlette — легкий ASGI-фреймворк, который используется при веб-разработке на Python. Он прекрасно подходит для создания высокопроизводительных asyncio-сервисов и может применяться как в роли самостоятельного фреймворка, так и в качестве ASGI-инструментария. Рассмотрим некоторые плюсы:

— поставляется вместе с широким ассортиментом инструментов; — поддерживает текстовый клиент, который построен на Requests Python; — поддерживает WebSockets, причем вебсокеты сразу встроены и готовы к работе; — поддерживает GraphQL — новый подход к разработке клиент-серверных взаимодействий; — поддерживает внутрипроцессовые фоновые задачи; — имеет широкий набор миддлеверов, предназначенных для работы с аутентификацией и авторизацией, CORS; — имеет встроенные асинхронные таски.

1-1801-4b9ecc.png

Также у него есть неплохая примочка под названием FastAPI. Она добавляет еще больше «плюшек», в частности: — возможности по созданию REST API-сервисов + Swagger-документация для методов; — удобные примочки, которые построены на подсказках-типах переменных (те же встроенные валидаторы данных, к примеру); — поддержка JWT и OAuth2; — прочие мелкие радости.

4.1-1801-b30e86.png

Установка Starlette проблем не вызывает:

2-1801-14c729.png

А вот и классический пример с Hello world:

О том, как в питоне без протокола и задеплоить приложение не могут. Смешиваем ASGI с WSGI — вредные советы

Как должны выглядеть современные сервисы на питоне, многие имеют представление. Все они, так или иначе, имеют поддержку асинхронных операций. А вот, как их лучше деплоить? Здесь некоторые руководства (как FastAPI) отвели целый раздел для рекомендаций, а некоторые (как Django) ограничились несколькими абзацами с крайне размытыми формулировками. Мне не посчастливилось следовать именно последнему.

Прочитав эту статью, Вы, возможно, захотите внести изменения в докерфайлы Ваших сервисов. Благодаря протоколам WSGI и ASGI, это можно сделать без особого труда. Именно поэтому все изложенные в статье советы — вредные. Также, Вы узнаете о nginx unit — ещё об одном годном сервере приложений.

Немного предыстории. На одном проекте у нас с командой в очередной раз встала задача деплоя питоновского веб-приложения. Обычно выбор стоит между gunicorn и uwsgi. Но в этот раз я успел услышать про новый сервер nginx unit и очень хотел его попробовать. Предварительно, конечно, нужно было отговорить команду от всех других адекватных вариантов.

Например, возьмём gunicorn — традиционный вариант, асинхронные фреймворки часто рекомендуют именно его. Для него есть асинхронный воркер, наряду с синхронным. Однако, если мы немного почитаем документацию, нас будет ждать разочарование: все воркеры должны быть идентичными. То есть, выбирайте: или все синхронные, или все асинхронные. Хотите тех и других — делайте 2 сервиса и ставьте перед ними nginx. Если всё равно нужен nginx — подумал я, не лучше ли сразу взять nginx unit? Этот аргумент подействовал, и так мы стали использовать nginx unit.

Некоторые читатели, конечно, видят изъян в моих рассуждениях: не обязательно иметь и синхронные, и асинхронные сервисы. Некоторые прекрасно обходятся только последними: заворачивают синхронные операции, если они есть, в асинхронные и горя не знают. Выполняются синхронные операции при этом в отдельном потоке — я говорю сейчас об «адаптерах» вроде sync_to_async. Но лучше я сначала немного расскажу о nginx unit.

Прекрасная документация, удобный API, очень настраиваемый — с nginx unit действительно приятно работать. В интернете пишут, что он хорошо ведёт себя в бенчмарках — я этого не проверял. У nginx unit действительно есть понятие логического «приложения», которое, скорее всего, всегда соответствует отдельному запущенному процессу. Таких приложений может быть запущено множество, и запросы могут роутиться на определённые из них, исходя из каких-то критериев. Я сделал 2 приложения, не оригинально назвав их wsgi и asgi. При этом, они слушают один и тот же порт — чудеса.

Немного о самих протоколах WSGI и ASGI. Нет, особо рассказывать не буду: ну, имеет наше сообщество тягу к использованию протоколов, это же прекрасно. Последний из двух — ASGI — появился вообще случайно, и изначально преследовал другие цели, насколько мне известно. Вебсокеты мы реализовывать не будем — пусть веб-сервер этим занимается, а нам даст вместо соединения корутину, которая умеет читать и писать — примерно такова его идея. Он не является официальным стандартом: для него нет соответствующего PEP. Тем не менее, стандарты вроде WSGI и ASGI существенно облегчают создание веб-серверов вроде nginx unit.

 < "listeners":< "*:8000":< "pass":"routes/proj" >>, "routes": < proj: >, "applications":< "wsgi":< "type":"python 3", "protocol": "wsgi", "path":"/app", "module": "proj.wsgi", "callable": "application" >, "asgi": < "type":"python 3", "protocol": "asgi", "path":"/app", "module": "proj.asgi", "callable": "application" >> >

Вот так выглядел примерный конфиг того, что получилось. Как видите, в нём действительно есть wsgi и asgi приложения. Напомню, что был и альтернативый вариант — иметь только асинхронный сервис (asgi), выполняя все функции с синхронным I/O в отдельном потоке. Итак, мы подошли к довольно интересному вопросу: нужно ли нам вообще WSGI приложение? Давайте сравним эти два варианта. Схеме с wsgi приложением дадим кодовое название «первый вариант», а схеме без него — второй. Насколько я знаю, общепринятым является именно второй вариант — где есть только ASGI-приложение (если я неправ, поправьте меня).

Итак, в чём же разница?

  1. В первом варианте синхронные воркеры значительно снимают нагрузку с асинхронных. Это может быть очень полезно, потому что если в памяти Вашего асинхронного приложения хранится что-то полезное, то это не получится масштабировать за пределы одного потока. Поэтому разгрузить асинхронный поток бывает очень кстати.
  2. Давайте подумаем: насколько асинхронный воркер (второй вариант) подходит для обработки «синхронных» запросов? Что представляет из себя такой воркер? Асинхронный поток и несколько синхронных потоков. Насколько такой воркер знает о своей нагрузке (сколько запросов у него в очереди, может ли он принимать новые) ? Ничего не знает. Можно только надеяться, что нагрузка на воркеры будет более-менее однородной. В первом же случае (синхронные воркеры) всё очень просто: воркер или занят, или свободен. Конечно, новые запросы распределяются на свободные воркеры. Воркеров много, поэтому они хорошо сглаживают неоднородную нагрузку.

Резюмируя: есть веские причины обрабатывать всю синхронную нагрузку вне асинхронных потоков, а последние по максимуму использовать для асинхронной нагрузки — для чего, собственно, они и предназначены. Справедливости ради, иногда при обработке асинхронных запросов мы всё-таки используем функции с синхронным I/O — конечно, для этого приходится их запускать в отдельном потоке. Но чем такой нагрузки меньше — тем лучше.

Именно это я имел в виду, когда говорил, что прочитав статью, Вы, возможно, захотите деплоить Ваше приложение по-другому (захотите добавить WSGI-приложение). Об этом можно проголосовать в конце статьи. Сейчас же давайте остановимся на некоторых практических аспектах. Мы остановились на том, что у нас есть 2 приложения, WSGI и ASGI, которые слушают один и тот же порт. Но как понять, какой запрос обрабатывать в WSGI-приложении, а какой в ASGI? Какой эндпоинт асинхронный, а какой нет? Об этом знает наше питоновское приложение (потому что у асинхронного эндпоинта функция-обработчик асинхронная). Но nginx unit не знает. Можно ли как-то решить этот вопрос, не прибегая к использованию специальных урлов для асинхронных эндпоинтов?

Оказывается, что с nginx unit — можно, и достаточно несложно. Дело в том, что, как я писал, nginx unit очень конфигурируемый, и роутинг запросов — одна из наиболее конфигурируемых его частей. Конфигурационный файл — это json, его можно сгенерировать автоматически — целиком или какие-то его части. Так мы и сделали — сгенерировали config.json, в котором структура routes отражают структуру urls.py в нашем Django приложении.

Если кому-то интересно, как может выглядеть такой генератор для routes — то примерно вот так https://github.com/pwtail/newunit/blob/master/generate_routes.py. Это черновой вариант — более продвинутый, чем тот, что у нас на проде, но менее отлаженный.

В итоге, в нашем django-приложении мы можем сделать вьюшку либо синхронной функцией (что бывает чаще всего), либо — асинхронной, и всё магически будет обработано именно там, где нужно.

Не могу не сказать пару слов об особенностях «поддержки» асинхронности в Django. Этот фреймворк очень заботится о разработчиках, поэтому пытается застраховать их от возможных ошибок. Например, если Вы сделали функцию-обработчик асинхронной, но что-то не сложилось для асинхронной обработки Вашего запроса (например, есть неподходящее middleware), Django молчаливо адаптирует вашу асинхронную функцию в синхронную. Если у Вас асинхронный I/O, но Вы задеплоили WSGI-приложение — тоже адаптирует, если синхронный I/O в ASGI-приложении — аналогично. Это может быть удобно для dev-сервера, но для продакшна подход немного странный, на мой взгляд. Стоит ли говорить, что с нашим автоматическим роутингом запросов в нужное приложение, такая «дружественность к разработчику» ничего полезного, кроме того, что прячет ошибки, не делает. Отключить такое поведение непросто (из коробки — никак).

В остальном же — да, можно сказать, что Django поддерживает асинхронность. А nginx unit — действительно очень настраиваемый. Можно даже разные HTTP-методы для одного урла в разные приложения направлять. Но такое сам Django, увы, не поддерживает: нельзя, чтобы, скажем, метод GET обрабатывался синхронной функцией, а метод POST — асинхронной. С последним фактом я, конечно, мириться не стал, и зафайлил на это баг: https://code.djangoproject.com/ticket/33780. Его закрыли через 5 минут (да, я умею настраивать нужные параметры в баг-трекере) как дубликат: оказывается, 16 лет назад уже предлагали что-то похожее.

Напоследок — как и обещал, опрос.

Как развернуть с помощью ASGI

Помимо WSGI,, Django также поддерживает развертывание на ASGI , новом стандарте Python для асинхронных веб-серверов и приложений.

Команда управления Django startproject настраивает для вас конфигурацию ASGI по умолчанию, которую вы можете настроить по мере необходимости для своего проекта и указать использовать любой сервер приложений, совместимый с ASGI.

Django включает документацию по началу работы для следующих серверов ASGI:

  • Как использовать Django с Дафной
  • Как использовать Django с Hypercorn
  • Как использовать Django с Uvicorn

Объект application

Как и в WSGI,, в ASGI вы предоставляете вызываемый объект application , который сервер приложений использует для связи с вашим кодом. Обычно он предоставляется как объект с именем application в модуле Python, доступном для сервера.

Команда startproject создает файл /asgi.py , содержащий такой вызываемый объект application .

Он не используется сервером разработки ( runserver ), но может использоваться любым сервером ASGI как в разработке, так и в производстве.

Серверы ASGI обычно принимают путь к вызываемому приложению в виде строки; для большинства проектов Django это будет выглядеть как myproject.asgi:application .

Хотя обработчик Django по умолчанию ASGI будет запускать весь ваш код в синхронном потоке, если вы решите запустить свой собственный обработчик async, вы должны знать о безопасности async.

Не вызывайте блокирующие синхронные функции или libraries в любом коде async. Django не позволяет вам сделать это с частями Django, которые не являются безопасными для async, но то же самое может не быть true сторонних приложений или Python libraries.

Настройка модуля настроек

Когда сервер ASGI загружает ваше приложение, Django должен импортировать модуль настроек — именно там определяется все ваше приложение.

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

Если эта переменная не задана, asgi.py по умолчанию задает для нее значение mysite.settings , где mysite — это имя вашего проекта.

Применение промежуточного ПО ASGI

Чтобы применить промежуточное ПО ASGI или встроить Django в другое приложение ASGI, вы можете поместить объект application Django в файл asgi.py . Например:

from some_asgi_library import AmazingMiddleware application = AmazingMiddleware(application)

ASGI — это. Значение слова ASGI

ASGI (английское Asynchronous Server Gateway Interface ) — клиент-серверный протокол взаимодействия веб-сервера и приложения, дальнейшее развитие технологии WSGI. По сравнению с WSGI предоставляет стандарт как для асинхронных, так и для синхронных приложений, с реализацией обратной совместимости WSGI и несколькими серверами и платформами приложений.

Оцените этот блок: �� 0 �� 0

На этой странице вы могли узнать, что такое «ASGI», его лексическое значение. Вы также можете посмотреть: 1. Рифмы.

Поделиться

Толковый словарь (что означает слово на букву): А Б В Г Д Е Ё Ж З И Й К Л М Н О П Р С Т У Ф Х Ц Ч Ш Щ Э Ю Я.

  • Поиск занял 0.02 сек. Вспомните, как часто вы ищете значения слов? Добавьте sinonim.org в закладки, чтобы быстро искать определения (что значит слово), а также синонимы, антонимы, ассоциации и предложения.

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

Ваш адрес email не будет опубликован. Обязательные поля помечены *