Cómo ClickHouse Managed Postgres escala PgBouncer con flotas de procesos y so_reuseport

Fuentes: How we scale PgBouncer in ClickHouse Managed Postgres

PgBouncer, el pooler de conexiones más usado para PostgreSQL, es monohilo: un único proceso gestiona todo el tráfico, lo que en una máquina de 16 vCPU desaprovecha 15 núcleos y limita el rendimiento mucho antes de que Postgres se sature. Para resolverlo, ClickHouse Managed Postgres despliega una flota de procesos PgBouncer dimensionada según los núcleos disponibles, todos ellos enlazados al mismo puerto gracias a la opción de kernel so_reuseport. El kernel del sistema reparte las conexiones entrantes entre los procesos, de modo que los clientes siguen conectándose a un único endpoint sin percibir la arquitectura interna.

El reto principal es la cancelación de consultas: una cancelación llega en una conexión nueva con una clave distinta y, sin coordinación, podría caer en un proceso que no conoce la consulta. Para evitarlo, los procesos se comunican entre sí (peering) y reenvían la cancelación al proceso que gestiona la sesión. El pooling opera en modo transacción, lo que libera conexiones al confirmar cada transacción, y los parámetros max_client_conn y max_db_connections se reparten entre los procesos para no sobrepasar los límites de Postgres.

Las pruebas, realizadas en instancias EC2 c7i.4xlarge con pgbench en modo select-only y transaction pooling, muestran que la configuración de un solo proceso rinde unas 87.000 transacciones por segundo y cae a 77.000 con 256 clientes, con la CPU de la caja por debajo del 10%. La flota de 16 procesos alcanza cerca de 336.000 transacciones por segundo (casi 4 veces más) y ocupa unos 8 núcleos, limitada por Postgres y el generador de carga. Además, repartir el presupuesto de conexiones permite elevar el techo agregado sin saturar ningún proceso ni el servidor de base de datos. Todo ClickHouse Managed Postgres incluye esta configuración por defecto.