todos com uma migration e atender a requisições de criação, leitura, atualização e exclusão a partir de uma pequena view JSON. Todas as conexões usam TLS com verificação completa de certificados.
Pré-requisitos
- Python 3.12 ou superior, conforme exigido pelo Django 6. Este guia foi testado com Python 3.13, Django 6.1.1 e psycopg 3.3.6.
- Uma conta do 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 estará pronta em poucos minutos. Para um passo a passo completo, 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 conecta o Django por meio do PgBouncer incluído, na porta6432. Uma aplicação Django em produção geralmente executa vários processos worker em várias máquinas, e cada um deles abre as próprias conexões. O PgBouncer opera no modo de pooling de transações e permite que todos esses processos compartilhem um pequeno número de conexões com o Postgres. O Django exige algumas configurações para funcionar com pooling de transações; este guia as inclui e as explica em Configurações do PgBouncer para Django.
Selecione via PgBouncer para ver os detalhes de conexão com pooling. A porta muda para 6432, e a string de conexão inclui sslmode=verify-full.
No modal, clique em Download CA certificate. Você também pode baixá-lo em Settings → CA Certificate. O certificado é exclusivo da sua instância, permitindo que o driver o use para confirmar que está se comunicando com o seu servidor.
Configure o projeto
Crie um diretório para o projeto com um ambiente virtual, instale o Django e o psycopg 3 e crie um projeto Django com um apptodos:
psycopg[binary] já inclui uma versão recente da libpq, então você não precisa ter o PostgreSQL instalado localmente.
Configure a conexão
Mova o certificado da CA que você baixou para o diretório do projeto, ao lado demanage.py, e renomeie-o para ca-certificate.pem.
Crie um banco de dados para a aplicação. Substitua <PASSWORD> e o host pelos valores exibidos no modal Connect:
mysite/settings.py, adicione import os abaixo de from pathlib import Path e substitua a configuração DATABASES por:
mysite/settings.py
OPTIONS ao psycopg, que as encaminha ao libpq. Com sslmode definido como verify-full, o libpq verifica se o certificado do servidor foi assinado pela CA do seu serviço e se corresponde ao hostname. BASE_DIR torna absoluto o caminho do certificado, de modo que a configuração funciona independentemente do diretório em que você inicia o Django.
Se
sslrootcert apontar para a CA errada, a conexão falha com SSL error: certificate verify failed. Sem sslrootcert, ela falha com root certificate file ".../.postgresql/root.crt" does not exist, porque o libpq recorre ao local padrão da CA. Se você se conectar pelo endereço IP em vez do hostname, a conexão falha com server certificate for "..." does not match host name.Crie um model e execute as migrations
Adicione o apptodos a INSTALLED_APPS em mysite/settings.py:
mysite/settings.py
Todo em todos/models.py:
todos/models.py
todos_todo, o migrate cria as tabelas dos aplicativos nativos do Django, como auth_user e django_session, e registra as migrations aplicadas em django_migrations. Em um aplicativo existente, pule o model todos e execute apenas python manage.py migrate, que cria todas as tabelas do seu aplicativo no novo banco de dados.
O migrate não adquire um advisory lock no nível da sessão, então funciona com o PgBouncer. Ele também não impede execuções simultâneas; por isso, execute as migrations de um único ponto, como uma etapa de implantação.
Adicione um endpoint JSON
Substituatodos/views.py por duas views que criam, listam, atualizam e excluem tarefas usando o ORM do Django:
todos/views.py
mysite/urls.py para rotear /todos e /todos/<id> para as views:
mysite/urls.py
Executar e verificar
Inicie o servidor de desenvolvimento:PATCH retorna a linha atualizada:
http://localhost:3111/todos no navegador para listar as tarefas pendentes. A resposta será semelhante a esta:
guide_django e, em seguida, public e clique na tabela todos_todo. A tabela contém a linha restante:
Configurações do PgBouncer para Django
O PgBouncer opera no modo de pooling de transações: cada transação, ou cada instrução fora de uma transação, pode ser executada em uma conexão Postgres diferente. Veja como isso afeta as configurações acima e outros recursos do Django:DISABLE_SERVER_SIDE_CURSORS:QuerySet.iteratorlê linhas em fragmentos por meio de um cursor do lado do servidor. Fora de uma transação, o Django declara o cursorWITH HOLDe busca cada fragmento separadamente; assim, via PgBouncer, uma busca pode cair em uma conexão Postgres que não tem o cursor e falhar comcursor "_django_curs_..." does not exist. Isso só acontece quando outros clientes usam o pool ao mesmo tempo, por isso muitas vezes não aparece em desenvolvimento. Com a configuração ativada,.iterator()usa um cursor comum, e o psycopg carrega todo o resultado na memória. Para fazer streaming de uma tabela muito grande, execute esse código pela conexão direta na porta5432, com a configuração desativada.CONN_MAX_AGE: por padrão (0), o Django abre uma nova conexão para cada requisição. Abrir uma conexão TLS exige várias idas e voltas na rede, tanto via PgBouncer quanto diretamente, então reutilizar conexões deixa as requisições muito mais rápidas. Em um teste feito a partir de um laptop com quatro workers do Gunicorn, definirCONN_MAX_AGEcomo600reduziu o tempo mediano de requisição de cerca de 670 ms para 95 ms. Via PgBouncer, uma conexão Django aberta não ocupa uma conexão Postgres entre transações, portanto conexões persistentes não esgotammax_connections.CONN_HEALTH_CHECKSfaz o Django verificar uma conexão reutilizada no início de cada requisição e reconectar caso ela tenha sido fechada.- Pool de conexões: o pool integrado do Django (
"pool": TrueemOPTIONS, que requerpip install "psycopg[binary,pool]") oferece um ganho de desempenho semelhante e também funciona via PgBouncer. Ele exigeCONN_MAX_AGEdefinido como0e mantém pelo menos quatro conexões abertas por processo. Com o PgBouncer,CONN_MAX_AGEbasta para a maioria das aplicações; considere o pool para servidores com threads ou ASGI. - Prepared statements: nenhuma configuração é necessária. Por padrão, o Django define o
prepare_thresholddo psycopg comoNonee vincula os parâmetros de consulta no cliente, portanto não cria prepared statements do lado do servidor. Se você ativar"server_side_binding": Truee definir"prepare_threshold"emOPTIONS, os prepared statements também funcionam via PgBouncer, porque opsycopg[binary]inclui alibpq18 e libera as instruções com uma mensagemCloseno nível do protocolo. Com o psycopg compilado com alibpq16 ou anterior, liberar uma instrução dentro de uma transação falha comprepared statement "_pg3_0" does not exist. Para verificar sua versão, executepython -c "import psycopg; print(psycopg.pq.version())". É necessário170000ou superior. - Estado de sessão: uma instrução
SET, comoSET search_path, só se aplica à conexão Postgres que a executou; assim, consultas posteriores podem não enxergá-la, enquanto outros clientes podem. O PgBouncer rejeita a configuração"options": "-c search_path=..."do Django comunsupported startup parameter in options: search_path. Em vez disso, defina os valores padrão no banco de dados, por exemplo comALTER DATABASE guide_django SET search_path = myschema, public;. Não use a opçãoassume_role, que executaSET ROLE. O tratamento deTIME_ZONEdo próprio Django e a opçãoisolation_levelfuncionam via PgBouncer.
PORT como 5432 e remova DISABLE_SERVER_SIDE_CURSORS. Nesse caso, cada worker do Django mantém sua própria conexão Postgres, portanto mantenha o número total de workers abaixo de max_connections.
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: direcione leituras para uma réplica usando o suporte do Django a múltiplos bancos de dados
- Segurança: listas de acesso por IP e rede privada