PgDoorman: 多线程 PostgreSQL 连接池

John Doe 五月 11, 2026

PgDoorman 是一款基于 Rust 开发的多线程 PostgreSQL 连接池。可无缝替代 PgBouncerOdyssey,同时也是 PgCat 的替代方案。已在电商平台 Ozon 稳定生产运行三年,承载 Go(pgx)、.NET(Npgsql)、Python(asyncpg、SQLAlchemy)及 Node.js 各类业务负载。

image

核心亮点功能

内置运维监控面板

诊断控制台内嵌于 pg_doorman 二进制程序中,与 /metrics 监控指标共用同一端口。面板可展示:连接池饱和度概览、各连接池延迟 P95/P99 迷你趋势线、按 SQLSTATE 分类的各连接池错误统计、Top-N 阻塞慢查询;

内存精细化拆分统计:活跃内存分配 / 内存碎片 / 内部缓存 / 程序与依赖库 / 调用栈 / 交换分区

展示 /proc/self/status 中的进程状态字段,每项数值附带单行文字说明;

每条 Tokio 工作线程 CPU 占用、预编译缓存归属、查询常量池内容、实时日志滚动输出。

支持连接池 / 客户端 / 应用 / 缓存多维度表格排序与筛选;可查看每个应用、每个客户端的实时 QPS 与每秒事务数。

PgBouncer、PgCat、Odyssey、PgPool-II、RDS 代理、Cloud SQL 认证代理虽都提供 /metrics 指标和 psql 管理控制台,但如需搭建完整监控大盘,需额外部署 Prometheus + Grafana + 内存指标导出器 + 自定义面板;而这套能力已内置在 PgDoorman 中。

可在同一页面执行暂停 / 恢复 / 重连 / 重载配置操作,支持单连接池范围或全局生效,其余操作均为只读。

仅当配置开启 [web].ui = truegeneral.admin_password 不为默认值时,监控控制台才会启用;全新安装若保留默认占位密码,仅开放 /metrics 监控端口,并输出警告日志。

连接池协调器

PgDoorman 可限制单个数据库的后端总连接数。当达到 max_db_connections 最大数据库连接上限时,协调器会从空闲连接冗余最多的用户中驱逐空闲连接,并按事务耗时 P95 排序,优先让业务延迟更高的连接池让出连接。

预留缓冲连接池可承接短期流量突发;为每个用户单独配置 min_guaranteed_pool_size 最小保底连接数,保障核心业务不会被纳入连接驱逐列表。

PgBouncer 的 max_db_connections 仅做连接数量上限限制,无连接驱逐机制、无公平调度:达到上限后,新客户端只能排队等待现有连接空闲超时自动关闭。Odyssey 则无同类配置项。

基于 Patroni 联动故障降级

当 PgDoorman 与 PostgreSQL 部署在同一服务器,若 Patroni 主从切换导致本地后端节点下线,PgDoorman 会主动轮询 Patroni REST API(接口:GET /cluster),自动挑选集群内健康节点(优先级:同步备库 → 普通副本),将新连接路由至可用节点。

原故障本地节点进入冷却期;降级转接的连接会设置较短生命周期,待本地节点恢复后,连接池可自动切回本地节点。

只需在 [general] 配置段设置 patroni_api_urlsfallback_cooldown 冷却时间,即可对所有连接池全局生效,无需在连接池前端额外部署 HAProxy 或 consul-template。

优雅的二进制平滑升级

可在业务高峰时段升级 PgDoorman,无需停机维护窗口。业务应用不会出现重连报错,PostgreSQL 不会因批量同时重连引发认证 / SCRAM 握手风暴,正在执行中的事务也不会中断失败。

向进程发送 SIGUSR2 信号后,旧进程通过 SCM_RIGHTS 机制,将所有空闲客户端的 TCP 套接字、查询取消密钥、预编译语句缓存完整移交至新进程 ——套接字保持不变,无需客户端重连

处于事务中的客户端会在旧进程完成当前事务,空闲后自动迁移至新进程。

Linux 平台可选开启 tls-migration 编译特性,可同步迁移 OpenSSL 加密会话状态,实现 TLS 会话无缝续连,无需重新握手。

PgBouncer 的在线重启(-R 参数,1.20 版本起已废弃)及基于 so_reuseport 的滚动重启、Odyssey 的在线重启(SIGUSR2 + bindwith_reuseport)原理相近:

新进程只接管新建连接,旧进程持续服务存量客户端,直至客户端主动断开后才退出。进程之间无法迁移会话、预编译语句与 TLS 会话状态

匿名解析语句缓存

在 PostgreSQL 扩展协议中,多数数据库驱动会将简短参数化查询,以空语句名Parse 请求方式发送。若不做重映射优化,这类高频请求每次复用都将重复消耗 PostgreSQL 优化器 CPU,后端也会反复执行解析操作。

PgDoorman 会将空语句名重写为内部标识 DOORMAN_<编号> 下发至后端,并在连接池中维护映射关系。PostgreSQL 会将其识别为命名预编译语句,后续同结构查询的 Bind 绑定请求,可在同一客户端、以及共享连接池的不同客户端之间,复用后端已生成的预编译执行状态。

核心收益为性能提升:大幅减少高频 OLTP 业务查询的优化器计算开销,降低后端重复解析次数。

PgBouncer(1.21 及以上版本)与 Odyssey 仅在事务模式下支持命名预编译语句;对于匿名 Parse 请求直接透传原样转发,每次调用都要重新生成执行计划。只有 PgDoorman 会自动对匿名语句做重映射缓存。

为保障生产运维安全,该缓存设有容量上限且完全可观测:

匿名缓存条目空闲超时自动过期清理,命名缓存条目无引用时自动回收;

通过 SHOW INTERNER 命令搭配 Prometheus 监控指标,可直观查看缓存容量、命中数、未命中数与缓存淘汰数量。

为什么选择 PgDoorman

  • 高频查询路径解析语句缓存:共享连接池内客户端可复用后端预编译状态,包含绝大多数驱动发送的匿名参数化解析请求。显著降低 PostgreSQL 高频 OLTP 查询的优化器 CPU 消耗;可通过 SHOW INTERNER 命令和监控指标查看缓存容量、命中、未命中与淘汰统计。
  • 多线程架构 + 全局共享连接池:所有工作线程共用同一个连接池。PgBouncer 为单线程架构,横向扩展需部署多实例并借助 so_reuseport,各实例独立维护连接池,同数据库跨进程空闲连接数量易出现偏差。
  • 惊群效应抑制:当 200 个客户端争抢 4 个空闲后端连接时,PgDoorman 通过 scaling_max_parallel_creates 限制后端并发新建连接数,释放的后端连接直接通过进程内一次性通道分配给等待最久的客户端,无需重新进入空闲连接池排队。
  • 尾延迟可控:客户端严格遵循先进先出调度,避免晚到客户端插队抢占资源。在后端连接生命周期 server_lifetime 达到 95% 时提前预创建替换连接(最多并行 3 个),保持连接池常备可用,避免批量连接轮换时出现请求尖峰。
  • 事务内后端故障实时检测:若事务中途后端节点宕机(故障切换、内存溢出、网络分区),PgDoorman 每 100 毫秒轮询客户端与后端读写状态,立即返回 SQLSTATE 08006 错误。若无该能力,客户端会一直阻塞直至 TCP 保活超时;Linux 默认配置下需等待约两小时外加 9 轮 75 秒探测。
  • 面向生产运维设计:支持 YAML/TOML 配置文件,时长配置可读性强(如 30秒5分钟)。执行 pg_doorman generate --host … 可自动解析现有 PostgreSQL 实例,生成初始配置模板。执行 pg_doorman -t 可仅校验配置、不启动服务。内置 Prometheus /metrics 监控接口。

功能对比表

功能特性 PgDoorman PgBouncer Odyssey
多线程架构 + 全局共享连接池 支持 不支持(单线程) 多工作线程、独立连接池
事务模式预编译语句 支持 支持(1.21 及以上) 支持(pool_reserve_prepared_statement
高频参数化查询匿名解析缓存、跨客户端复用 支持 不支持,仅命名语句生效 不支持,仅命名语句生效
连接池协调器(单库连接上限、优先级驱逐) 支持 不支持 不支持
内置 Patroni 联动故障降级 支持 不支持 不支持
连接生命周期到期提前预替换 支持 不支持 不支持
事务内后端僵死节点检测 支持(立即返回 08006) 不支持(依赖 TCP 保活超时) 不支持(依赖 TCP 保活超时)
会话无损二进制平滑升级 支持(SCM_RIGHTS 移交、可选 TLS 状态迁移) 不支持(会话保留在旧进程) 不支持(会话保留在旧进程)
后端 TLS 加密连接 PostgreSQL 支持(5 种模式,SIGHUP 热重载) 支持(server_tls_配置,RELOAD 热重载) 不支持
认证:SCRAM 透传(无明文密码) 支持(从认证报文提取 ClientKey) 支持(1.14 及以上,通过 auth_query / 用户列表加密存储) 支持
认证:JWT(RSA-SHA256) 支持 不支持 不支持
认证:PAM /pg_hba.conf/ 自定义查询认证 支持 支持 支持
认证:LDAP 不支持 支持(1.25 及以上) 支持
配置文件格式 YAML / TOML INI 自定义格式
JSON 结构化日志 支持 不支持 支持(log_format 设为 json)
延迟分位统计(P50/P90/P95/P99) 内置 /metrics 自带 仅平均值,无分位 需独立 Go 导出器
配置校验模式(-t 参数) 支持 不支持 不支持
从现有 PostgreSQL 自动生成配置 支持 不支持 不支持
Prometheus 监控接口 内置 /metrics 需独立导出器 需独立 Go 侧边车导出器

性能基准测试

测试环境:AWS Fargate(16 核 vCPU),连接池大小 40,每项 pgbench 压测时长 30 秒:

测试场景 相对 PgBouncer 性能 相对 Odyssey 性能
扩展协议、500 客户端 + SSL 加密 提升 3.5 倍 提升 61%
预编译语句、500 客户端 + SSL 加密 提升 4.0 倍 提升 5%
简单协议、10000 客户端 提升 2.8 倍 提升 20%
扩展协议 + SSL + 频繁重连、500 客户端 提升 96% 基本持平

参考

PostgreSQL Pooler | PgDoorman:https://github.com/ozontech/pg_doorman