todos mediante una migración y atenderá solicitudes de creación, lectura, actualización y eliminación desde una pequeña vista JSON. Todas las conexiones usan TLS con verificación completa de certificados.
Requisitos previos
- Python 3.12 o posterior, tal como requiere Django 6. Esta guía se probó con Python 3.13, Django 6.1.1 y psycopg 3.3.6.
- Una cuenta de ClickHouse Cloud
psql, para crear la base de datos. También puede ejecutar la sentenciaCREATE DATABASEen la consola SQL.
Crear un servicio de ClickHouse Managed Postgres
En la consola de ClickHouse Cloud, haga clic en New service y seleccione Postgres. La instancia estará lista en unos minutos. Consulte la guía de inicio rápido para ver las instrucciones paso a paso.Obtenga los detalles de conexión
Haga clic en Conectar en la barra lateral izquierda de su servicio. El cuadro modal muestra su nombre de usuario, contraseña, servidor y puerto, e incluye un toggle Directly / via PgBouncer. En esta guía, Django se conecta a través del PgBouncer incluido, en el puerto6432. Una aplicación Django en producción suele ejecutar varios procesos worker en varias máquinas, y cada uno abre sus propias conexiones. PgBouncer funciona en modo de agrupación por transacción y permite que todos ellos compartan un número reducido de conexiones de Postgres. Django requiere algunos ajustes para la agrupación por transacción; esta guía los incluye y los explica en Configuración de PgBouncer para Django.
Seleccione via PgBouncer para ver los detalles de la conexión agrupada. El puerto cambia a 6432 y la cadena de conexión incluye sslmode=verify-full.
En el cuadro modal, haga clic en Download CA certificate. También puede descargarlo desde Settings → CA Certificate. El certificado es exclusivo de su instancia, por lo que el controlador puede usarlo para verificar que se está comunicando con su servidor.
Configurar el proyecto
Cree un directorio para el proyecto con un entorno virtual, instale Django y psycopg 3 y cree un proyecto de Django con una aplicacióntodos:
psycopg[binary] incluye una versión reciente de libpq, por lo que no necesita tener PostgreSQL instalado localmente.
Configurar la conexión
Mueva el certificado de CA que descargó al directorio del proyecto, junto amanage.py, y cámbiele el nombre a ca-certificate.pem.
Cree una base de datos para la aplicación. Sustituya <PASSWORD> y el host por los valores del cuadro modal Conectar:
mysite/settings.py, agregue import os debajo de from pathlib import Path y reemplace la configuración DATABASES por:
mysite/settings.py
OPTIONS a psycopg, que a su vez las entrega a libpq. Con sslmode establecido en verify-full, libpq comprueba que el certificado del servidor esté firmado por la CA de su servicio y que coincida con el nombre del host. BASE_DIR convierte la ruta del certificado en absoluta, de modo que la configuración funciona independientemente del directorio desde el que inicie Django.
Si
sslrootcert apunta a una CA incorrecta, la conexión falla con SSL error: certificate verify failed. Sin sslrootcert, falla con root certificate file ".../.postgresql/root.crt" does not exist, porque libpq recurre a su ubicación de CA predeterminada. Si se conecta mediante la dirección IP en lugar del nombre del host, falla con server certificate for "..." does not match host name.Crear un modelo y ejecutar las migraciones
Agregue la aplicacióntodos a INSTALLED_APPS en mysite/settings.py:
mysite/settings.py
Todo en todos/models.py:
todos/models.py
todos_todo, migrate crea las tablas de las aplicaciones integradas de Django, como auth_user y django_session, y registra las migraciones aplicadas en django_migrations. Si ya tienes una aplicación, omite el modelo todos y ejecuta solo python manage.py migrate, que crea todas las tablas de tu aplicación en la nueva base de datos.
migrate no adquiere un bloqueo consultivo a nivel de sesión, por lo que funciona a través de PgBouncer. Sin embargo, tampoco impide ejecuciones concurrentes, así que ejecuta las migraciones desde un único lugar, por ejemplo, un solo paso de despliegue.
Añadir un endpoint JSON
Sustituya el contenido detodos/views.py por dos vistas que crean, listan, actualizan y eliminan tareas mediante el ORM de Django:
todos/views.py
mysite/urls.py para enrutar /todos y /todos/<id> a las vistas:
mysite/urls.py
Ejecutar y verificar
Inicie el servidor de desarrollo:PATCH devuelve la fila actualizada:
http://localhost:3111/todos en su navegador para ver la lista de tareas pendientes. La respuesta tiene este aspecto:
guide_django y después public, y haz clic en la tabla todos_todo. La tabla contiene la fila restante:
Configuración de PgBouncer para Django
PgBouncer se ejecuta en modo de agrupación por transacción: cada transacción, o cada sentencia fuera de una transacción, puede ejecutarse en una conexión de Postgres distinta. A continuación se explica cómo afecta esto a la configuración anterior y a otras funcionalidades de Django:DISABLE_SERVER_SIDE_CURSORS:QuerySet.iteratorlee las filas por fragmentos mediante un cursor del lado del servidor. Fuera de una transacción, Django declara el cursorWITH HOLDy recupera cada fragmento por separado, por lo que, a través de PgBouncer, una recuperación puede acabar en una conexión de Postgres que no tiene el cursor y fallar concursor "_django_curs_..." does not exist. Esto solo ocurre cuando otros clientes usan el grupo al mismo tiempo, así que a menudo no se manifiesta en desarrollo. Con esta opción activada,.iterator()usa un cursor normal y psycopg carga todo el resultado en memoria. Para leer una tabla muy grande en streaming, ejecute ese código a través de la conexión directa en el puerto5432con la opción desactivada.CONN_MAX_AGE: de forma predeterminada (0), Django abre una nueva conexión para cada solicitud. Abrir una conexión TLS requiere varios viajes de ida y vuelta por la red, tanto a través de PgBouncer como directamente, por lo que reutilizar conexiones acelera mucho las solicitudes. En una prueba desde un portátil con cuatro workers de Gunicorn, establecerCONN_MAX_AGEen600redujo la mediana del tiempo de solicitud de unos 670 ms a 95 ms. A través de PgBouncer, una conexión abierta de Django no retiene una conexión de Postgres entre transacciones, por lo que las conexiones persistentes no agotanmax_connections.CONN_HEALTH_CHECKShace que Django compruebe la conexión reutilizada al inicio de cada solicitud y vuelva a conectarse si se ha cerrado.- Grupo de conexiones: el grupo integrado de Django (
"pool": TrueenOPTIONS, que requierepip install "psycopg[binary,pool]") ofrece una mejora de velocidad similar y también funciona a través de PgBouncer. Requiere queCONN_MAX_AGEesté establecido en0y mantiene al menos cuatro conexiones abiertas por proceso. Con PgBouncer,CONN_MAX_AGEes suficiente para la mayoría de las aplicaciones; considere usar el grupo en servidores multihilo o ASGI. - Sentencias preparadas: no hace falta ninguna configuración. De forma predeterminada, Django establece
prepare_thresholdde psycopg enNoney vincula los parámetros de consulta en el cliente, por lo que no crea sentencias preparadas del lado del servidor. Si activa"server_side_binding": Truey establece"prepare_threshold"enOPTIONS, las sentencias preparadas también funcionan a través de PgBouncer, porquepsycopg[binary]incluyelibpq18 y libera las sentencias con un mensajeClosea nivel de protocolo. Con psycopg compilado contralibpq16 o anterior, liberar una sentencia dentro de una transacción falla conprepared statement "_pg3_0" does not exist. Para comprobar su versión, ejecutepython -c "import psycopg; print(psycopg.pq.version())". Necesita170000o posterior. - Estado de sesión: una sentencia
SET, comoSET search_path, solo se aplica a la conexión de Postgres que la ejecutó, por lo que es posible que las consultas posteriores no la vean y que otros clientes sí. PgBouncer rechaza la opción"options": "-c search_path=..."de Django conunsupported startup parameter in options: search_path. En su lugar, defina los valores predeterminados en la base de datos, por ejemplo conALTER DATABASE guide_django SET search_path = myschema, public;. No use la opciónassume_role, que ejecutaSET ROLE. La gestión deTIME_ZONEpropia de Django y la opciónisolation_levelfuncionan a través de PgBouncer.
PORT en 5432 y elimine DISABLE_SERVER_SIDE_CURSORS. En ese caso, cada worker de Django mantiene su propia conexión de Postgres, así que procure que el número total de workers no supere max_connections.
Próximos pasos
- Conexión: cadenas de conexión, PgBouncer y TLS
- Configuración: parámetros de Postgres y PgBouncer, como
max_connections - Réplicas de lectura: envíe las lecturas a una réplica mediante la compatibilidad de Django con múltiples bases de datos
- Seguridad: listas de acceso por IP y redes privadas