pgxpool é o seu pool de conexões. Neste guia, você vai conectar um serviço Go ao ClickHouse Managed Postgres por TLS verificado, criar uma tabela todos com uma migração do golang-migrate e atender a requisições de criação, leitura, atualização e exclusão em um servidor net/http.
Pré-requisitos
- Go 1.25 ou superior. Este guia foi testado com Go 1.27.1, pgx 5.11.0 e golang-migrate 4.20.1.
- 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 fica 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. Mantenha Directly selecionado e ative Use SSL. A URL de conexão na aba url passa a usar a porta5432 e termina com sslmode=verify-full&sslrootcert=<service-name>-ca-certificate.pem. Clique em Download CA certificate. Você também pode baixá-lo mais tarde em Settings → CA Certificate. O certificado é exclusivo da sua instância, o que permite que o pgx o use para verificar se está se comunicando com o seu servidor.
Este guia se conecta diretamente ao Postgres na porta 5432, tanto para as migrações quanto para a aplicação. Um serviço em Go é um processo de longa duração, e o pgxpool já mantém um pool de conexões dentro dele, portanto não é necessário um segundo pooler. Se você executar muitas instâncias do serviço e precisar de mais conexões de cliente do que o Postgres permite, use o PgBouncer incluído (via PgBouncer, porta 6432) na aplicação; consulte Usar o PgBouncer, que exige uma configuração de conexão adicional.
Configure o projeto
Crie um módulo Go, adicione o pgx e instale a CLImigrate com o driver do pgx:
-tags 'pgx5' compila a CLI migrate com o driver pgx v5, que usa o esquema de URL pgx5://. O go install coloca o binary em $GOBIN, ou em $(go env GOPATH)/bin se GOBIN não estiver definido; portanto, verifique se esse diretório está no seu PATH.
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:
guide_go e diferem apenas no esquema da URL: a aplicação lê DATABASE_URL, enquanto a CLI do migrate usa MIGRATE_URL:
libpq. Com sslmode=verify-full, ele carrega o arquivo da CA indicado em sslrootcert e verifica tanto a cadeia de certificados quanto o hostname, então você não precisa escrever nenhum código de TLS. O caminho em sslrootcert é resolvido em relação ao diretório a partir do qual você executa os comandos. Se a sua senha contiver caracteres especiais, como @, / ou #, aplique a codificação de URL a eles.
Crie o schema com uma migração
Crie os arquivos de migração:up:
migrations/000001_create_todos.up.sql
down, que a desfaz:
migrations/000001_create_todos.down.sql
migrate registra a versão atual na tabela schema_migrations e, nas execuções seguintes, aplica apenas as migrações mais recentes. Faça commit do diretório migrations junto com o seu código.
Sempre execute o
migrate pela conexão direta (porta 5432). Durante a execução, ele mantém um bloqueio consultivo (advisory lock) no nível da sessão, para que duas implantações não executem a migração ao mesmo tempo. Pelo PgBouncer, o bloqueio e o desbloqueio podem acontecer em conexões Postgres diferentes. Com isso, o bloqueio permanece ativo, e as execuções posteriores do migrate travam ou falham com timeout: can't acquire database lock.Consultar o banco de dados
Crie o arquivodb.go. Ele cria o pool a partir de DATABASE_URL e verifica a conexão na inicialização, consultando o Postgres sobre qual versão do TLS a sessão está usando:
db.go
todos.go com os handlers HTTP. Cada handler executa uma única consulta parametrizada no pool, e pgx.CollectRows e pgx.CollectExactlyOneRow mapeiam as linhas para a struct Todo com base no nome da coluna:
todos.go
$1), em vez de formatá-los na string SQL, evita injeção de SQL. O pgx os envia separadamente do texto da consulta. Não é preciso verificar separadamente o erro de pool.Query: pgx.CollectRows e pgx.CollectExactlyOneRow já o retornam.
Crie o arquivo main.go. Ele cria um único pool para todo o processo, atende às rotas na porta 3114 e fecha o pool ao pressionar Ctrl+C. Em uma aplicação existente, chame newPool uma única vez na inicialização e, em vez disso, registerTodoRoutes no seu http.ServeMux:
main.go
Executar e verificar
Adicione as dependências restantes dopgxpool ao go.mod e ao go.sum e, em seguida, inicie o servidor:
TLSv1.3 vem de pg_stat_ssl no servidor, o que confirma que a sessão está criptografada. Se você apontar sslrootcert para qualquer outro certificado, o servidor não inicia e registra x509: certificate signed by unknown authority nos logs, o que mostra que o certificado é realmente verificado.
Em um segundo terminal, crie duas tarefas, marque a primeira como concluída e exclua a segunda:
PATCH retorna a linha atualizada:
http://localhost:3114/todos no navegador para listar as tarefas restantes. O pgx retorna valores timestamptz no fuso horário local. A resposta será semelhante a esta:
Shutting down no log e fecha o pool.
Para ver os dados no console, abra o SQL Console na barra lateral esquerda do seu serviço, expanda guide_go e depois public e clique na tabela todos. A tabela schema_migrations, logo ao lado, armazena a versão da migração. A tabela todos contém a linha restante:
Use o PgBouncer
Para enviar as consultas do aplicativo pelo PgBouncer incluído, selecione via PgBouncer no modal Connect, altere a porta emDATABASE_URL para 6432 e adicione default_query_exec_mode=cache_describe. Mantenha a MIGRATE_URL na porta 5432:
default_query_exec_mode da URL e não o envia ao servidor. Nenhuma alteração de código é necessária, e o mesmo certificado CA continua funcionando. O log de inicialização agora mostra TLS: none, porque pg_stat_ssl reporta a conexão do próprio PgBouncer com o Postgres. A conexão da sua aplicação com o PgBouncer continua sendo verificada: um certificado CA incorreto falha da mesma forma.
O PgBouncer opera em modo de pooling de transações, portanto cada transação pode ser executada em uma conexão diferente do Postgres:
- Transações com
pool.Beginoupgx.BeginFuncfuncionam normalmente. - Configurações de sessão definidas com
SETnão permanecem na sua conexão e podem vazar para outros clientes. UseSET LOCALdentro de uma transação. O PgBouncer também rejeitasearch_pathna URL de conexão com o errounsupported startup parameter: search_path; em vez disso, qualifique os nomes de tabela com o schema. PREPAREeEXECUTEem nível de SQL,LISTENe bloqueios consultivos de sessão não funcionam.
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 usando um segundo
pgxpool.Pool - Segurança: listas de acesso por IP e rede privada