Предварительные требования
- uv и Python 3.11 или новее. Это руководство проверено на Python 3.13, FastAPI 0.142, SQLAlchemy 2.1, asyncpg 0.31, Alembic 1.20 и Uvicorn 0.54.
- Аккаунт ClickHouse Cloud
psqlдля создания базы данных. ОператорCREATE DATABASEтакже можно выполнить в консоли SQL.
Создание сервиса ClickHouse Managed Postgres
В консоли ClickHouse Cloud нажмите New service и выберите Postgres. Инстанс будет готов через несколько минут. Пошаговое описание процесса см. в кратком руководстве.Получение сведений о подключении
Нажмите Подключение на левой боковой панели вашего сервиса. В открывшемся окне отображаются имя пользователя, пароль, сервер и порт, а также переключатель Directly / via PgBouncer. В этом руководстве используются оба типа соединений:- PgBouncer (порт
6432) — для приложения. SQLAlchemy держит пул соединений в каждом воркере Uvicorn, а встроенный PgBouncer позволяет множеству воркеров и реплик совместно использовать небольшое число соединений с Postgres. PgBouncer работает в режиме пулинга транзакций (transaction pooling). - Прямое соединение (порт
5432) — для Alembic. Миграции выполняют DDL, могут работать долго и зависеть от состояния сеанса, поэтому они должны подключаться к Postgres напрямую.
sslmode=verify-full&sslrootcert=.... asyncpg не читает эти параметры, поэтому скопируйте из окна только пароль и хост. CA‑сертификат приложение передаёт непосредственно в коде (см. Настройка соединения).
Настройка проекта
Создайте проект и установите FastAPI, Uvicorn, SQLAlchemy с дополнительным модулем asyncio, asyncpg и Alembic:Настройка соединения
Переместите скачанный CA‑сертификат в каталог проекта и переименуйте его вca-certificate.pem.
Создайте базу данных для приложения. Замените <PASSWORD> и хост значениями из модального окна Подключение:
.env в корне проекта или добавьте эти переменные в существующий. Оба URL различаются только портом, используют схему postgresql+asyncpg и не содержат параметров SSL:
.env
DATABASE_CA_CERT вычисляется относительно каталога, из которого вы запускаете команды. Если пароль содержит специальные символы, например @, / или #, примените к ним URL-кодирование. Не добавляйте .env в систему контроля версий.
Создайте app/db.py. В этом файле настраиваются параметры TLS, создаются движок и фабрика сеансов, общая для всего приложения:
app/db.py
ssl.SSLContext, созданный с PROTOCOL_TLS_CLIENT, требует действительный сертификат и проверяет имя хоста, что эквивалентно sslmode=verify-full. SQLAlchemy передаёт его в asyncpg через connect_args.
Если вы предпочитаете хранить настройки TLS в URL или ваше приложение использует синхронные сеансы SQLAlchemy, используйте вместо asyncpg драйвер psycopg. Он основан на libpq и принимает параметры из модального окна Подключение, например
postgresql+psycopg://...:5432/guide_fastapi?sslmode=verify-full&sslrootcert=ca-certificate.pem, причём как с create_engine, так и с create_async_engine.Определение модели
Создайте файлapp/models.py с типизированной моделью SQLAlchemy:
app/models.py
Выполнение миграций
Создайте окружение Alembic на основе асинхронного шаблона:migrations/env.py. Новая версия загружает ваши модели для autogenerate и подключается напрямую к Postgres с теми же настройками TLS, что и приложение:
migrations/env.py
sqlalchemy.url в alembic.ini, так как env.py создаёт движок самостоятельно.
Сгенерируйте миграцию на основе модели и примените её:
migrations/versions и закоммитьте его вместе с кодом. Alembic записывает применённую ревизию в таблицу alembic_version. При каждом изменении модели заново выполняйте revision --autogenerate и upgrade head.
Добавьте конечные точки API
Создайтеapp/main.py. Каждый запрос получает собственный объект AsyncSession через зависимость FastAPI, а пул движка закрывается при завершении работы приложения:
app/main.py
session.commit. При закрытии сеанса все незакоммиченные изменения откатываются. При выполнении INSERT SQLAlchemy получает сгенерированные значения id и created_at через RETURNING, поэтому функции create_todo не требуется дополнительный запрос.
Запуск и проверка
Запустите приложение:DELETE возвращает 204 No Content. При запросе несуществующей задачи возвращается 404:
pg_stat_ssl с теми же настройками TLS, что и в приложении:
guide_fastapi, затем public и выберите таблицу todos. В соседней таблице alembic_version хранится история миграций. В таблице todos осталась одна строка:
Чтобы остановить приложение, нажмите Ctrl+C.
Использование PgBouncer
Приложение работает через PgBouncer с настройками asyncpg и SQLAlchemy по умолчанию:- asyncpg выполняет каждый запрос как именованный подготовленный оператор на уровне протокола, а SQLAlchemy кэширует до 100 таких операторов для каждого соединения. Встроенный PgBouncer поддерживает эти операторы в режиме пулинга транзакций, а asyncpg освобождает их сообщением
Closeна уровне протокола, а не SQL-командойDEALLOCATE. Указыватьstatement_cache_size=0или собственную функциюprepared_statement_name_funcне нужно. Если вы всё же отключаете кэш операторов asyncpg, добавьте также в URLprepared_statement_cache_size=0, чтобы отключить кэш SQLAlchemy. - Настройки сеанса, заданные через
SET, напримерsearch_path, не сохраняются в следующей транзакции и могут «утечь» к другим клиентам. Вместо этого используйтеSET LOCALвнутри транзакции. pg_stat_sslпоказывает соединение между PgBouncer и Postgres, поэтому описанная выше проверка TLS через порт6432возвращает(False, None). При этом соединение приложения с PgBouncer всё равно проверяется: с неверным CA‑сертификатом подключение завершится такой же ошибкой.- Alembic не использует рекомендательные блокировки и выполняет каждый
upgradeв одной транзакции, поэтому тоже работает через PgBouncer. Тем не менее для длительных миграций лучше использовать прямое соединение.
Дальнейшие шаги
- Подключение: строки подключения, PgBouncer и TLS
- Настройки: параметры Postgres и PgBouncer, например
max_connections - Реплики для чтения: направление запросов только на чтение на реплику со вторым движком
- Безопасность: списки IP Access List и частное сетевое подключение