Асинхронность и конкурентность

Раздел про asyncio в Python-сервисе: цикл событий и корутины, задачи и отмена, TaskGroup, синхронизация, потоки и блокирующий код, клиенты, таймауты и обратное давление, отладка, ошибки, тесты, GIL и процессы.

Зачем для UCP. Обработчик команды во FastAPI живёт в цикле событий: один блокирующий вызов останавливает все запросы процесса, одна забытая отмена оставляет висящую задачу с открытой транзакцией. Без понимания asyncio невозможно написать обработчик, который держит таймауты, корректно завершается и не теряет работу под нагрузкой.

Двенадцать статей, по одной теме на статью, читать лучше подряд.

Основа

  1. Цикл событий и корутины — что такое корутина, кто её выполняет, что происходит на await и чего не бывает в asyncio.
  2. Задачи и отмена — create_task, gather, что происходит при cancel, почему CancelledError нельзя глотать.
  3. Структурная конкурентность — TaskGroup против gather, ExceptionGroup, границы жизни задач.
  4. Синхронизация — Lock, Semaphore, Event, Queue и когда они нужны в однопоточном коде.

Границы цикла событий

  1. Блокирующий код и потоки — как распознать блокировку, to_thread, пул потоков, вызовы из потока в цикл.
  2. Асинхронные клиенты — httpx, asyncpg и redis: один клиент на процесс, пулы, лимиты и закрытие.
  3. Таймауты и обратное давление — asyncio.timeout, Semaphore на внешние вызовы, ограниченные очереди, деградация под нагрузкой.

Эксплуатация

  1. Отладка асинхронного кода — режим отладки, медленные колбэки, никогда не ожидавшиеся корутины, дамп задач.
  2. Типичные ошибки конкурентности — гонки на await, забытые задачи, общая сессия, бесконечное ожидание, утечки.
  3. Тесты асинхронного кода — pytest-asyncio и anyio, httpx против ASGI, respx, тесты отмены и таймаутов.
  4. Свободные потоки и процессы — GIL и сборка без него, потоки, процессы и подинтерпретаторы для вычислений.
  5. asyncio во FastAPI на практике — сборка всего в обработчике: зависимости, фоновые задачи, завершение, что мерить.