Pré-requisitos
- uv e Python 3.11 ou superior. Este guia foi testado com Python 3.13, FastAPI 0.142, SQLAlchemy 2.1, asyncpg 0.31, Alembic 1.20 e Uvicorn 0.54.
- Uma conta no ClickHouse Cloud
psql, para criar o banco de dados. Você também pode executar a instruçãoCREATE DATABASEno SQL Console.
Crie um serviço ClickHouse Managed Postgres
No console do ClickHouse Cloud, clique em New service e selecione Postgres. A instância fica pronta em poucos minutos. Para um passo a passo, consulte o guia de início rápido.Obtenha os detalhes de conexão
Clique em Connect na barra lateral esquerda do seu serviço. O modal exibe seu nome de usuário, senha, servidor e porta, além de um seletor Directly / via PgBouncer. Este guia usa as duas conexões:- PgBouncer (porta
6432) para a aplicação. O SQLAlchemy mantém um pool de conexões em cada worker do Uvicorn, e o PgBouncer incluído permite que vários workers e réplicas compartilhem um número reduzido de conexões com o Postgres. Ele opera no modo de pooling de transações. - Direta (porta
5432) para o Alembic. As migrations executam DDL, podem demorar bastante e podem depender do estado da sessão, por isso devem se comunicar diretamente com o Postgres.
sslmode=verify-full&sslrootcert=.... O asyncpg não lê esses parâmetros, então copie do modal apenas a senha e o host. Em vez disso, a aplicação passa o certificado da CA no próprio código (consulte Configure a conexão).
Configure o projeto
Crie um projeto e instale FastAPI, Uvicorn, SQLAlchemy com o extra asyncio, asyncpg e Alembic:Configure a conexão
Mova o certificado da CA que você baixou para o diretório do projeto e renomeie-o paraca-certificate.pem.
Crie um banco de dados para a aplicação. Substitua <PASSWORD> e o host pelos valores exibidos no modal Connect:
.env na raiz do projeto ou adicione estas variáveis ao arquivo que você já tem. As duas URLs diferem apenas na porta, usam o esquema postgresql+asyncpg e não incluem parâmetros de SSL:
.env
DATABASE_CA_CERT é resolvido em relação ao diretório a partir do qual você executa os comandos. Se sua senha contiver caracteres especiais como @, / ou #, aplique a codificação de URL a eles. Mantenha o .env fora do controle de versão.
Crie app/db.py. Esse arquivo monta as configurações de TLS, o motor e uma fábrica de sessões compartilhada pelo restante da aplicação:
app/db.py
ssl.SSLContext criado com PROTOCOL_TLS_CLIENT exige um certificado válido e verifica o hostname, o que equivale a sslmode=verify-full. O SQLAlchemy o repassa ao asyncpg por meio de connect_args.
Se preferir manter as configurações de TLS na URL, ou se sua aplicação usa sessões síncronas do SQLAlchemy, use o driver psycopg em vez do asyncpg. Ele é baseado na libpq e aceita os parâmetros do modal Connect, por exemplo,
postgresql+psycopg://...:5432/guide_fastapi?sslmode=verify-full&sslrootcert=ca-certificate.pem, tanto com create_engine quanto com create_async_engine.Defina o model
Crie o arquivoapp/models.py com um model SQLAlchemy tipado:
app/models.py
Executar as migrations
Crie um ambiente do Alembic a partir do template async:migrations/env.py gerado. A nova versão carrega seus models para o autogenerate e se conecta diretamente ao Postgres usando as mesmas configurações de TLS da aplicação:
migrations/env.py
sqlalchemy.url em alembic.ini, pois o env.py cria o motor por conta própria.
Gere uma migração a partir do model e, em seguida, aplique-a:
migrations/versions e faça o commit dele junto com o seu código. O Alembic registra a revisão aplicada na tabela alembic_version. Sempre que alterar um model, execute novamente revision --autogenerate e upgrade head.
Adicione os endpoints da API
Crieapp/main.py. Cada requisição recebe sua própria AsyncSession por meio de uma dependência do FastAPI, e o pool do motor é fechado quando a aplicação é encerrada:
app/main.py
session.commit. Quando a sessão é fechada, todo trabalho não confirmado é revertido. Em um INSERT, o SQLAlchemy recupera o id e o created_at gerados por meio de RETURNING, de modo que create_todo não precisa de uma consulta adicional.
Executar e verificar
Inicie o aplicativo:DELETE retorna 204 No Content. Requisitar um todo que não existe retorna 404:
pg_stat_ssl com as mesmas configurações de TLS usadas pelo aplicativo:
guide_fastapi e depois public e clique na tabela todos. A tabela alembic_version, logo ao lado, armazena o histórico de migrations. A tabela todos contém a linha restante:
Encerre a aplicação com Ctrl+C.
Usando o PgBouncer
A aplicação funciona por meio do PgBouncer com as configurações padrão do asyncpg e do SQLAlchemy:- O asyncpg executa cada consulta como um prepared statement nomeado, no nível do protocolo, e o SQLAlchemy armazena em cache até 100 deles por conexão. O PgBouncer incluído oferece suporte a essas instruções no modo de pooling de transações, e o asyncpg as libera com uma mensagem
Closeno nível do protocolo, em vez de usar oDEALLOCATEdo SQL. Você não precisa destatement_cache_size=0nem de umaprepared_statement_name_funcpersonalizada. Se, ainda assim, você desativar o cache de instruções do asyncpg, adicione tambémprepared_statement_cache_size=0à URL para desativar o cache do SQLAlchemy. - As configurações de sessão definidas com
SET, comosearch_path, não são mantidas na transação seguinte e podem vazar para outros clientes. Em vez disso, useSET LOCALdentro de uma transação. pg_stat_sslreporta a conexão entre o PgBouncer e o Postgres, portanto a verificação de TLS acima retorna(False, None)pela porta6432. A conexão da aplicação com o PgBouncer continua sendo verificada: um certificado de CA incorreto falha da mesma forma.- O Alembic não adquire advisory locks e executa cada
upgradeem uma única transação, por isso também funciona por meio do PgBouncer. Ainda assim, a conexão direta é a melhor opção para migrations longas.
Próximos passos
- Conexão: strings de conexão, PgBouncer e TLS
- Configurações: parâmetros do Postgres e do PgBouncer, como
max_connections - Réplicas de leitura: envie consultas read-only para uma réplica com um segundo motor
- Segurança: listas de acesso por IP e rede privada