HTTP Interface Connection Pooling: Transitioning to Distributed Load Balancing
0 reputation · 05 Aug 2023, 21:16 UTC
0 reputation · 05 Aug 2023, 21:16 UTC
ClickHouse manages server-side connection limits through the max_connections setting, while the HTTP interface relies on the Connection: keep-alive header and keep_alive_timeout to maintain persistent sessions. In single-node environments, this mechanism handles basic connection reuse effectively.
As deployments scale to distributed clusters, relying on internal server-side pooling becomes problematic. High traffic spikes can lead to connection exhaustion or memory overhead due to the thread-per-connection model, necessitating a transition toward external load balancers like Nginx or HAProxy to manage traffic distribution and socket persistence.
There is uncertainty regarding the optimal alignment of keep_alive_timeout between the ClickHouse server and an external load balancer to prevent premature socket closure or "broken pipe" errors.
keep_alive_timeout when using an external load balancer to ensure connection stability?max_connections limit interact with the concurrent connection pools maintained by a distributed load balancer?For stable HTTP connections through an external load balancer, align timeouts as follows:
The max_connections setting governs the maximum concurrent TCP connections ClickHouse accepts. When using a load balancer:
max_connections, ClickHouse will reject excess connections with ECONNREFUSED, resulting in 503 errors.system.events for ConnectionRejected events to detect pool misalignment.keep_alive_timeout = 120
# Nginx example
proxy_read_timeout 100s;
proxy_send_timeout 100s;
# Nginx upstream example
upstream clickhouse {
server ch-node1:8123;
server ch-node2:8123;
keepalive 32; # Must be <= max_connections across cluster
}
proxy_http_version 1.1;
proxy_set_header Connection "";
# Check for connection issues
SELECT * FROM system.events WHERE Event LIKE '%Connection%';
# Monitor broken pipes
grep "Broken pipe" /var/log/clickhouse-server/clickhouse-server.log
After deployment, validate the configuration:
wrk or ab to simulate traffic and observe connection stability.ss -s on ClickHouse nodes to confirm socket count stays within max_connections.query_log for ConnectionAborted or ConnectionTimeout events.Be aware that:
keep_alive_timeout values increase memory usage due to per-connection overhead.Use comments to ask for clarification. Post a solution as an answer.
32,275 reputation · 06 Aug 2023, 00:21 UTC
The prior answer suggests ClickHouse keep_alive_timeout should be 10–20% longer than the load balancer's idle timeout. In practice, the load balancer must close idle connections before ClickHouse does. Set the LB idle timeout (Nginx proxy_read_timeout/keepalive_timeout, HAProxy timeout server) 5–10 seconds shorter than ClickHouse's keep_alive_timeout (default 10 s). If the LB holds connections longer, ClickHouse closes them first, causing "broken pipe" errors when the LB reuses a stale socket.
max_connections (default 4096) is a global server limit shared across HTTP, native, MySQL, and PostgreSQL interfaces. Each LB worker process maintains its own upstream keepalive pool (Nginx upstream keepalive N; HAProxy server … maxconn). The sum of all workers' pool sizes across every LB instance must stay below max_connections. For example, with 4 Nginx workers and keepalive 32, that's 128 connections per LB node—scale the per-worker value down as you add LB nodes.
SELECT name, value FROM system.settings WHERE name IN ('max_connections','keep_alive_timeout');nginx -T | grep -E 'keepalive_timeout|proxy_read_timeout|upstream.*keepalive'system.metrics (Connection, HTTPConnection) and LB active-connection gauges; alert above 80% utilization.