Игра Яндекс Практикума
Игра Яндекс Практикума
Игра Яндекс Практикума

Почему не стоит выбирать FastAPI — самый быстрый фреймворк на Python

Отредактировано

Рассказываем о минусах фреймворка FastAPI для Python, несмотря на его скорость, и о достоинствах Django по сравнению с FastAPI.

17К открытий19К показов

FastAPI позиционируют как быстрый и легкий фреймворк для создания REST API.

Django представляет из себя довольно громоздкий многофункциональный MVT (MVC) фреймворк. Сам по себе он не совсем предназначен для создания API. Но в совокупности с DRF хорошо справляется со этой задачей.

Изучение нескольких статей о скорости FastAPI натолкнуkо на мысль, что не так все просто.

Я решил разобраться, так ли быстр FastAPI, и стоит ли его выбирать, особенно если пишешь преимущественно на Django.

Для сравнения выбрал критерии:

  1. Скорость работы
  2. Удобство работы с базой
  3. Безопасность
  4. Сложность написания приложения
  5. Сложность поддержки

Скорость

Для сравнения были подготовлены 2 приложения на FastAPI и Django с максимально близкой логикой.

1. Простой ответ. В ответе json с одним ключом и значением.

			{"text": "Text"}
		

2. Асинхронный запрос к другому АПИ, который быстро отвечает. Быстро — это, например, 1 — 5 мс.

3. Асинхронный запрос к другому АПИ, который медленно отвечает. Медленно – это, например, 5 секунд.

Привычные асинхронные запросы aiohttp для обоих фреймворков:

			async def request(session):
    async with session.get(URL) as response:
        return await response.text()


async def task(count):
    async with aiohttp.ClientSession() as session:
        tasks = [request(session) for i in range(count)]
        result = await asyncio.gather(*tasks)
		

Для большей гибкости, количество параллельных запросов передавалось в аргументах.

4. Выполнение простой логики. Генерация списка с последующей сортировкой. Количество элементов списка так же передается в аргументах. Эта логика не зависит от фреймворка, но работа фреймворка во время расчета может отличаться.

			items = [randrange(100) for i in range(count)]
items.sort()
		

5. Ответ с синхронным ожиданием. Простой requests:

			response = requests.get(URL)
		

6. Запрос в базу синхронный.

Для Django через простую модель:

			items = MyModel.objects.values()
		

FastAPI:

			def get_items(db: Session, skip: int = 0, limit: int = 100):
    return db.query(models.MyModel).offset(skip).limit(limit).all()

items = crud.get_items(db, skip=skip, limit=limit)
		

7. Запрос в базу асинхронный (только FastAPI).

			async def get_items(db: Session, skip: int = 0, limit: int = 100):
    res = await db.query(models.MyModel).offset(skip).limit(limit)
    return res.all()

items = await crud.get_items(db, skip=skip, limit=limit)
		

Проведение экспериментов

Для проверки использовал обычный ab по 10 вызовов с расчетом среднего. Делал как последовательные запросы, так и параллельные.

Оба приложения были запущены через ASGI.

В результате, как и ожидалось, FastAPI везде отвечал быстрее.

Так как запуски были на ноутбуке, то какого-то объективного абсолютного результата я не ожидал, но сравнение в равных условиях неплохо себя показало.

Почему не стоит выбирать FastAPI — самый быстрый фреймворк на Python 1

В таблицах выделены 2 части:

  1. 100 запросов без конкуренции — просто идущие один за другим
  2. 100 параллельных запросов

Последовательные запросы генерировались командой:

			ab -n 100 http://127.0.0.1:8000/method
		

Параллельные:

			ab -n 100 -c 100 http://127.0.0.1:8000/method
		

При параллельных запроса я брал 80-й процентиль для оценки.

В синхронном режиме работа с базой через ОРМ Django оказалась немного быстрее SQLAlchemy, подключенной к FastAPI. А вот асинхронный режим SQLAlchemy показал себя лучше синхронного Django ORM. Подключать Django в асинхронном режиме не пробовал.

FastAPI выдержала больше одновременных подключений, особенно, при работе с базой. При увеличении количества параллельных запросов FastAPI справлялся лучше, чем Django. Django при количестве параллельных запросов больше 150 уже захлебывался и отбивал ответы.

В итоге FastAPI действительно работает заметно быстрее. По крайней мере, на синтетических запросах.

Многие сравнивают преимущественно скорость, производительность и подобные технические характеристики. Но python чаще используют не там, где нужна высокая скорость и производительность. Его предназначение не в этом. Основные плюсы языка – это хорошая читабельность кода, высокая скорость разработки, широкий выбор инструментов и достаточная производительность. В общем, это не быстрый язык, а удобный. И разница между производительностью фреймворков на реальном коде может быть не такая значительная, чтобы это имело значение. Поэтому сравнение фреймворков по критериям производительности не так сильно влияет на их выбор.

Сложность кода

В Django из коробки уже есть все необходимые инструменты для работы с базой: ORM, миграции, средства отладки. Просто установить, настроить за несколько минут и можно работать. Расширение сервиса на Django вполне понятное и логичное. Можно добавлять модели без особых усилий. В FastAPI нужно подключать внешний ORM и миграции. При разрастании сервиса становится сложнее ориентироваться в нем.

DRF — довольно удобная библиотека, которая умеет работать с моделями Django. Она не совсем из коробки, но подключается достаточно легко.

В FastAPI работа с АПИ встроена по умолчанию. Ничего подключать не надо. Это – плюс. Но работа с сериализаторами, на мой взгляд, чуть более запутана. Хотя это субъективно, а разница – не кардинальна.

Так же в Django есть встроенная удобная админка. Что иногда является плюсом.

Безопасность

Еще должен отметить безопасность фреймворков. В Django из коробки реализована защита от типичных уязвимостей типа CSRF, SQL injection. А вот в FastAPI придется самому решать некоторые вопросы с безопасностью. Как вариант, подключать fastapi.security. Но все равно Django безопаснее.

Вывод

Конечно, создавая небольшие простые приложения и не имея опыта работы с Django, лучше отдать предпочтение FastAPI. Это достаточно небольшой фреймворк, который не придется долго изучать. Но всю необходимую обвязку, не относящуюся непосредственно к фреймворку, изучать все равно придется.

Django же достаточно сложный фреймворк, у него сложнее порог входа, но в нем есть все необходимое. И если вы уже пишите на Django, то FastAPI может показаться сложнее из-за того, что не содержит всех нужных инструментов.

Конечно, вопрос не только в скорости, но и в предпочтениях. В результате оценок я пришел к выводу, что FastAPI на небольшом приложении действительно имеет преимущества перед Django. И для разработки микросервисов точно подойдет. Он немного сложнее в написании кода и поддержке. А вот если нужно писать сложный сервис с большим количеством связей, базой, то я бы выбрал Django. Да он медленнее, но его безопасность, структурированность и большое комьюнити перевешивают производительность FastAPI.

Если же нужно действительно производительное приложение, и скорость важна, то рекомендую обратить внимание на Golang или даже C++, а не Python.

Следите за новыми постами
Следите за новыми постами по любимым темам
17К открытий19К показов