Python
Junior
a
Какие есть недостатки у асинхронности?
Ответы
Асинхронность в Python (в первую очередь `asyncio`) решает ряд задач, но имеет **системные ограничения и практические недостатки**, которые важно понимать до архитектурных решений. Ниже — структурированный разбор без идеализации.
---
## 1. Асинхронность не ускоряет CPU-bound задачи
### Суть проблемы
`async / await` **не даёт параллелизма по CPU** из-за GIL.
```python
async def calc():
for _ in range(10**8):
pass
```
Такой код:
* блокирует event loop
* тормозит все остальные coroutines
### Вывод
Асинхронность подходит **только для I/O-bound задач**:
* HTTP
* БД
* файловые операции
* сокеты
Для CPU-bound:
* `multiprocessing`
* `concurrent.futures.ProcessPoolExecutor`
* C-extensions / NumPy
---
## 2. GIL + asyncio = ложное ощущение параллелизма
Даже при `await`:
* код исполняется **в одном потоке**
* выполнение строго кооперативное
**Проблема:** один «плохой» coroutine ломает всю систему.
---
## 3. Сложность ментальной модели
### Что усложняется
* порядок выполнения неочевиден
* стек вызовов разорван
* ошибки могут проявляться **не в месте причины**
```python
await a()
await b() # может не выполниться из-за ошибки выше
```
### Итог
Асинхронный код:
* сложнее читать
* сложнее поддерживать
* сложнее обучать команду
---
## 4. Отладка значительно сложнее
### Типовые проблемы
* `Task was destroyed but it is pending`
* `RuntimeError: Event loop is closed`
* зависшие задачи
* race condition без shared memory
Стек-трейсы:
* обрезанные
* с прыжками между coroutine
---
## 5. Ограниченная экосистема
Не все библиотеки:
* поддерживают `async`
* безопасны для event loop
### Примеры проблем
* блокирующий ORM
* синхронный драйвер БД
* старые SDK
Один такой вызов → **блокировка всего event loop**.
---
## 6. Смешивание sync и async — источник багов
### Типичные анти-паттерны
```python
async def handler():
requests.get(url) # ❌ блокирует loop
```
или
```python
asyncio.run() внутри asyncio.run() # ❌
```
### Итог
* deadlock
* падения в runtime
* сложные для диагностики ошибки
---
## 7. Сложная работа с ресурсами
### Проблемы
* утечки соединений
* забытые `await`
* незакрытые task'и
```python
async with session.get(url): # если забыть async
```
Ошибки могут:
* не всплывать
* появляться только под нагрузкой
---
## 8. Ограничения масштабирования
### Вертикально
* один event loop = одно ядро
### Горизонтально
* всё равно нужен multiprocessing / k8s
* async ≠ масштабирование
---
## 9. Производительность ≠ простота
| Сценарий | Async | Sync |
| ----------- | ------ | ------ |
| 10 запросов | хуже | проще |
| 1000 I/O | лучше | хуже |
| CPU задачи | плохо | плохо |
| Отладка | сложно | просто |
---
## 10. Архитектурные риски
Асинхронность:
* **распространяется как вирус**
* вынуждает весь стек быть async-совместимым
```python
async → async → async → async
```
Вернуться к sync:
* дорого
* часто невозможно без переписывания
---
## 11. Когда async — плохой выбор
❌ Не стоит использовать, если:
* мало параллельных I/O
* простая бизнес-логика
* неопытная команда
* сильная зависимость от sync-библиотек
* CPU-нагрузка
---
## 12. Когда async оправдан
✅ Подходит, если:
* тысячи одновременных соединений
* high-load API
* websockets
* прокси / gateway
* event-driven архитектура
---
## 13. Ключевая мысль
> **Асинхронность — это инструмент, а не серебряная пуля.**
> В Python она увеличивает пропускную способность I/O, но платой за это являются сложность, хрупкость и архитектурные ограничения.
---
Если хочешь, следующим шагом могу:
* сравнить `asyncio` vs `threading` vs `multiprocessing`
* разобрать async-антипаттерны на реальном коде
* дать чек-лист «стоит ли тут async»
* разобрать async в FastAPI под нагрузкой
Скажи, что именно полезнее для твоего проекта.