Микросервис для управления задачами (tasks) с использованием FastAPI, SQLAlchemy и Redis.
Этот проект представляет собой RESTful API для управления задачами. Основные возможности:
- Создание задач.
- Получение списка задач с поддержкой кэширования.
- Обновление статуса задачи (перевод из статуса "pending" в статус "completed").
Этот документ описывает структуру каталогов проекта и назначение каждого файла и директории.
Dockerfile
: Файл для сборки Docker-образа приложения.README.md
: Основная документация проекта с описанием, инструкциями по запуску и использованием.ROADMAP.md
: Дорожная карта проекта с перечнем задач и планов на будущее.docker-compose.yml
: Конфигурация Docker Compose для запуска приложения, PostgreSQL и Redis.example.env
: Пример файла.env
с переменными окружения. Используется как шаблон для настройки окружения.pytest.ini
: Конфигурационный файл для настройки тестов с использованиемpytest
.requirements.txt
: Список зависимостей Python, необходимых для работы приложения.
Основная директория с исходным кодом приложения.
Директория для хранения дампов базы данных.
dump_10000.sql
: Дамп базы данных с 10,000 записями.dump_1000000.sql
: Дамп базы данных с 1,000,000 записями.
Директория для хранения полезных скриптов.
generate_tasks.sh
: Скрипт для генерации тестовых задач с использованиемcurl
.
-
Настройка окружения:
- Скопируйте
example.env
в.env
и заполните переменные окружения.
- Скопируйте
-
Генерация тестовых данных:
- Запустите скрипт
sh scripts/generate_tasks.sh
для создания тестовых задач.
- Запустите скрипт
- Python: Высокоуровневый язык программирования общего назначения.
- FastAPI: Веб-фреймворк для создания API.
- SQLAlchemy: ORM для работы с базой данных.
- PostgreSQL: Реляционная база данных для хранения задач.
- Redis: Кэширование данных для повышения производительности.
- Uvicorn: ASGI-сервер для запуска FastAPI.
- Docker-compose: Инструмент для управления многоконтейнерными приложениями в Docker.
- Docker: Платформа для разработки, доставки и запуска приложений в изолированных средах
Приложение построено по принципу многослойной архитектуры (Layered Architecture), что обеспечивает четкое разделение ответственности между компонентами. Основные слои:
- FastAPI: Используется для создания RESTful API. FastAPI обеспечивает высокую производительность за счет асинхронной обработки запросов.
- Эндпоинты: Определяют маршруты API (например,
/tasks
) и обрабатывают HTTP-запросы. - Pydantic: Используется для валидации входных данных и сериализации ответов.
- CRUD-операции: Логика создания, чтения, обновления и удаления задач реализована в модуле
crud
. - Валидация статусов: Проверка, что задача не может быть переведена из статуса "завершено" в другой статус.
- Кэширование: Логика работы с кэшем (Redis) для повышения производительности.
- SQLAlchemy: ORM для работы с базой данных. Позволяет абстрагироваться от конкретной СУБД.
- Модели данных: Определены в модуле
DataBaseModel
. Например, модельBaseTask
описывает структуру задачи. - Асинхронные запросы: Используются для взаимодействия с базой данных, чтобы не блокировать основной поток выполнения.
- Redis: Используется для хранения кэшированных данных. Кэш обновляется при изменении данных в базе.
- Блокировки: Для предотвращения race conditions при обновлении кэша используются асинхронные блокировки (
AsyncRedisLock
). Это особенно важно, когда несколько запросов одновременно пытаются обновить кэш.- Как это работает:
- При первом запросе, если данные отсутствуют в кэше, захватывается блокировка.
- Другие запросы, пришедшие в это же время, ожидают освобождения блокировки.
- Если блокировка не освобождается в течение заданного таймаута (настраивается в
settings.CACHE_LOCK_TIMEOUT
), запрос завершается с ошибкой429 Too Many Requests
, чтобы предотвратить долгое ожидание. - После обновления кэша блокировка освобождается, и следующие запросы используют обновленные данные.
- Преимущества:
- Исключается ситуация, когда несколько процессов одновременно обновляют кэш.
- Повышается согласованность данных.
- Таймаут предотвращает бесконечное ожидание и обеспечивает отказоустойчивость.
- Как это работает:
- Настройки: Конфигурация приложения (например: включение/выключение кэширования) управляется через модуль
settings
. - Логирование: Используется модуль
logger
для записи логов выполнения операций. - Обработка ошибок: Централизованная обработка ошибок (например, ошибки подключения к Redis или базе данных).
-
Запрос поступает в FastAPI:
- Эндпоинт обрабатывает HTTP-запрос (например,
GET /tasks
). - Данные валидируются с помощью Pydantic.
- Эндпоинт обрабатывает HTTP-запрос (например,
-
Обращение к бизнес-логике:
- Если кэширование включено, данные сначала запрашиваются из Redis.
- Если данных в кэше нет, выполняется запрос к базе данных через SQLAlchemy.
-
Работа с базой данных:
- SQLAlchemy выполняет запросы к базе данных (например,
SELECT * FROM tasks
). - Данные возвращаются в виде объектов Python.
- SQLAlchemy выполняет запросы к базе данных (например,
-
Кэширование:
- Если данные были получены из базы, они сохраняются в Redis для последующих запросов.
- При изменении данных (например, создании новой задачи) кэш инвалидируется.
-
Формирование ответа:
- Данные сериализуются в JSON с помощью Pydantic.
- Ответ возвращается клиенту.
Сравнительный анализ Nest.js и FastAPI показал, что обе технологии обладают схожими возможностями. Однако Nest.js чаще используется для приложений, где требуется интеграция с пользовательским интерфейсом (UI). В нашем случае проект представляет собой сервис без пользовательского интерфейса.
-
Простота и скорость разработки:
- FastAPI предоставляет удобный и интуитивно понятный синтаксис, что ускоряет разработку.
- Встроенная поддержка асинхронности позволяет эффективно обрабатывать запросы.
-
Отсутствие необходимости в UI:
- FastAPI идеально подходит для создания API-сервисов, где не требуется пользовательский интерфейс.
-
Производительность:
- FastAPI основан на Starlette и Pydantic, что обеспечивает высокую производительность и минимальные задержки.
-
Документация и сообщество:
- FastAPI автоматически генерирует документацию (Swagger и ReDoc), что упрощает взаимодействие с API.
- Активное сообщество и множество готовых решений для типичных задач.
-
Ориентация на UI:
- Nest.js чаще используется в проектах, где требуется интеграция с фронтендом (например, Angular или React).
-
Сложность для простых API:
- Для сервисов без UI использование Nest.js может быть избыточным, так как он требует больше настроек и boilerplate-кода.
-
Производительность:
- Хотя Nest.js также поддерживает асинхронность, FastAPI показывает лучшую производительность в тестах.
Выбор FastAPI обусловлен его простотой, производительностью и ориентированностью на создание API-сервисов без необходимости интеграции с пользовательским интерфейсом. Это делает его идеальным решением для нашего проекта.
Это руководство поможет вам запустить приложение с использованием Docker и Docker Compose.
Убедитесь, что у вас установлены Docker и Docker Compose. Проверьте их версии:
docker --version
docker-compose --version
Для корректной работы приложения необходимо настроить переменные окружения в файле .env
. Этот файл необходимо создать в корне проекта.
Пример конфигурации example.env
:
# Настройки приложения
APP_PORT=8080
CACHE_TIMEOUT=300
CACHE_TURNED_ON=true
# Настройки PostgreSQL
POSTGRES_USER=user
POSTGRES_PASSWORD=password
POSTGRES_DB=tasks_db
POSTGRES_HOST=postgres
POSTGRES_PORT=5432
# Настройки Redis
REDIS_HOST=redis
REDIS_PORT=6379
- APP_PORT: Порт, на котором будет доступно приложение.
- CACHE_TIMEOUT: Время (в секундах), в течение которого данные хранятся в кэше.
- CACHE_TURNED_ON: Включение или выключение кэширования. Возможные значения:
true
(включено) илиfalse
(выключено).
- POSTGRES_USER: Имя пользователя для подключения к базе данных PostgreSQL.
- POSTGRES_PASSWORD: Пароль для подключения к базе данных PostgreSQL.
- POSTGRES_DB: Название базы данных PostgreSQL.
- POSTGRES_HOST: Хост для подключения к PostgreSQL (обычно
postgres
при использовании Docker). - POSTGRES_PORT: Порт для подключения к PostgreSQL (по умолчанию
5432
).
- REDIS_HOST: Хост для подключения к Redis (обычно
redis
при использовании Docker). - REDIS_PORT: Порт для подключения к Redis (по умолчанию
6379
).
-
Корректность заполнения переменных: Убедитесь, что все переменные окружения заполнены корректно. В противном случае приложение может не запуститься или работать некорректно.
-
Использование с Docker: Если вы используете Docker, переменные окружения будут автоматически подхвачены из файла
.env
. Убедитесь, что файл.env
находится в корневой директории проекта. -
Безопасность: Не передавайте файл
.env
с чувствительными данными (например, паролями) в публичные репозитории. Используйте.gitignore
, чтобы исключить его из коммитов.
- Перейдите в корневую директорию проекта.
- Выполните следующую команду:
docker-compose up --build
После успешного запуска приложение будет доступно по адресу: http://localhost:8080
Вы можете проверить доступность API, например, с помощью команды curl:
curl http://localhost:8080/tasks
Чтобы остановить контейнеры, выполните:
docker-compose down
Если вы хотите удалить контейнеры и тома (включая данные PostgreSQL и Redis), выполните:
docker-compose down -v
Чтобы просмотреть логи конкретного сервиса (например, app), выполните:
docker-compose logs app
Вы можете подключиться к PostgreSQL с помощью команды:
docker exec -it tasks_postgres_db psql -U postgres -d tasks_db
Вы можете подключиться к Redis с помощью команды:
docker exec -it tasks_redis_cache redis-cli