Асинхронность и конкурентность
Раздел про asyncio в Python-сервисе: цикл событий и корутины, задачи и отмена, TaskGroup, синхронизация, потоки и блокирующий код, клиенты, таймауты и обратное давление, отладка, ошибки, тесты, GIL и процессы.
Зачем для UCP. Обработчик команды во FastAPI живёт в цикле событий: один блокирующий вызов останавливает все запросы процесса, одна забытая отмена оставляет висящую задачу с открытой транзакцией. Без понимания asyncio невозможно написать обработчик, который держит таймауты, корректно завершается и не теряет работу под нагрузкой.
Двенадцать статей, по одной теме на статью, читать лучше подряд.
Основа
- Цикл событий и корутины — что такое корутина, кто её выполняет, что происходит на await и чего не бывает в asyncio.
- Задачи и отмена — create_task, gather, что происходит при cancel, почему CancelledError нельзя глотать.
- Структурная конкурентность — TaskGroup против gather, ExceptionGroup, границы жизни задач.
- Синхронизация — Lock, Semaphore, Event, Queue и когда они нужны в однопоточном коде.
Границы цикла событий
- Блокирующий код и потоки — как распознать блокировку, to_thread, пул потоков, вызовы из потока в цикл.
- Асинхронные клиенты — httpx, asyncpg и redis: один клиент на процесс, пулы, лимиты и закрытие.
- Таймауты и обратное давление — asyncio.timeout, Semaphore на внешние вызовы, ограниченные очереди, деградация под нагрузкой.
Эксплуатация
- Отладка асинхронного кода — режим отладки, медленные колбэки, никогда не ожидавшиеся корутины, дамп задач.
- Типичные ошибки конкурентности — гонки на await, забытые задачи, общая сессия, бесконечное ожидание, утечки.
- Тесты асинхронного кода — pytest-asyncio и anyio, httpx против ASGI, respx, тесты отмены и таймаутов.
- Свободные потоки и процессы — GIL и сборка без него, потоки, процессы и подинтерпретаторы для вычислений.
- asyncio во FastAPI на практике — сборка всего в обработчике: зависимости, фоновые задачи, завершение, что мерить.