«Aiohttp от автора» (PyCon Russia 2018)
Art of DWH, @bryzgaloff7: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, аутентификационных плагинов.