«Aiohttp от автора» (PyCon Russia 2018)

«Aiohttp от автора» (PyCon Russia 2018)

Art of DWH, @bryzgaloff
Доклад Андрея Светлова, мейнтейнера aiohttp и куратора aio-libs

7:16 asyncio.Future необходимы только для создателей библиотек, использование их «простыми» пользователями не предполагается.

8:45 aiohttp не предназначен для ускорения синхронных веб-фреймворков (Django, Flask), т.к. смешение синхронного и асинхронного кода неочевидно и сопряжено с дополнительной ручной работой: например, по умолчанию Event Loop создается только в главном потоке, во второстепенных потребуется создавать самостоятельно.

Частые ошибки

11:37 Fire-and-forget

Проблемы:

  • Никак не обработаны исключения.
  • Непонятно, как остановить выполнение. Правильно: добавлять в список и по завершению выполнять graceful shutdown.
  • Нет контроля за количеством выполняемых задач.

Сейчас можно использовать aio-libs/aiojobs. В следующем Python станет удобнее: появится Task Group.

15:00 Создание асинхронных ресурсов в конструкторе

Ключевая проблема: __init__ синхронный. (Можно сделать асинхронным, но не стоит.)

Решение: асинхронный фабричный метод.

17:54 Незакрытые ресурсы

Проблема: __del__ синхронный.

Правильно: асинхронный метод close или async with. Пример — aiohttp.ClientSession.

21:51 Таймауты

Важно понимать, какие есть типы таймаутов (aiohttp.ClientTimeout):

  • total — общий таймаут с учетом ожидания свободного соединения из пула.
  • connect — таймаут на ожидание свободного соединения + время на установку соединения.
  • sock_connect — таймаут на установку соединения (без учета ожидания свободного соединения).
  • sock_read — таймаут на чтение данных после установки соединения.

25:42 Вебсокеты

Проблема: закрытие, например, вкладки браузера не всегда приводит к закрытию TCP-сокета, поэтому сообщение о разрыве соединения может прийти с задержкой.

Решение: пинговать клиента. Сопутствующая проблема: потребуются доработки на фронтенде.

28:52 Защита задачи от отмены

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

Проблема: aiohttp прервет любой запрос при разрыве соединения.

Решение: использовать asyncio.shield.

31:16 Глобальное хранилище (синглтоны)

Паттерн: создается глобальный объект (например, коннект к БД), он импортируется в других модулях для асинхронных операций.

Проблемы:

  • Время жизни объекта может отличаться от времени жизни связанного с ним Event Loop.
  • Неудобно следить за закрытием ресурса.
  • Сложно конфигурировать и тестировать.

Решение: использовать контекст приложения aiohttp.

37:36 Наследование от классов aiohttp

Проблема: пользовательские классы наследуют «внутренности» aiohttp.

Решение: хранить объекты aiohttp в полях объекта.

38:52 Эпилог

Андрей сравнил производительность aiohttp с другими асинхронными серверами и упомянул о планах по ускорению библиотеки, поддержке HTTP2, SOCKS, аутентификационных плагинов.

Report Page