数据库教程FGMT60-PostgreSQL连接池管理与代理分发
## 一、前言与内容大纲
PostgreSQL 采用一连接一进程的服务模型,每个客户端连接都要在服务端 fork 出一个独立的 backend 进程,并附带一套专属的内存上下文与会话状态。随着业务并发升高,连接数从几十涨到几千,进程启动、上下文切换与内存占用被成倍放大,最终触碰 `max_connections` 上限,甚至引发"连接风暴"拖垮整个数据库。这类瓶颈无法靠加配置解决,必须在应用与数据库之间引入一层"连接池 + 代理分发"的中间组件,这正是风哥教程本文要讲透的主题。
本套风哥教程以 PostgreSQL 连接池管理与代理分发为核心,技术主线是三件套:**PgBouncer** 做轻量连接复用,**Pgpool-II** 做连接池、读写负载均衡与故障转移,**HAProxy** 做四层代理分发与统一入口。三者可独立部署,也可叠加成完整接入架构。全文实战驱动,从原理到安装、配置、启动、接入、故障演练,逐条给出可复现命令。
环境约定:主机 `fgedu-net-cn1`(主节点/统一接入点)、`fgedu-net-cn2`(备用节点/后端库),均为 **64G 内存、8 核 CPU** 规格;数据库实例名与库名统一为 `fgedudb`,业务用户名为 `fgedu`;安装与数据路径统一使用 `/fgedudb`。全文以 PostgreSQL 为对象,不绑定具体小版本号,命令在主流发行版可直接落地。
全文结构:第 2 章理论,讲连接模型缺陷、连接池本质、三种池化模式与三组件原理选型;第 3 章 PgBouncer 实战;第 4 章 Pgpool-II 实战;第 5 章 HAProxy 实战;第 6 章综合架构与端到端验证;第 7 章风哥针对本文总结。
---
## 二、理论基础
### 2.1 连接模型的三重瓶颈
先把 PostgreSQL 的连接模型讲清楚。服务端是典型的多进程架构,共享内存只存一份缓冲池与 WAL 缓冲,而每个客户端连接都对应一个独立的 backend 进程,通过进程间通道与客户端交换报文。这个模型带来三重瓶颈。
第一是建连成本。每新建一条连接,服务端都要经历进程 fork、私有内存分配、会话参数初始化、权限加载等一连串动作。单次建连成本虽不大,但高并发下会被无限放大。
第二是内存占用。即便 backend 空闲,也会按 `work_mem` 等参数预留内存并与共享缓冲交互,单个 backend 常驻内存常在几十到上百 MB。一千条连接意味着几十 GB 潜在占用,直接封死了 64G 环境下可承载的并发。
第三是连接数上限。`max_connections` 硬性封顶并发总数,运维出于安全不会把它开得过大,因为每个 slot 都对应潜在内存与调度开销。一旦触顶,新连接直接被拒,业务表现为"数据库连不上"。
这三重瓶颈决定了堆硬件无用,必须靠一层能复用连接的中间件来消化海量短连接,这是连接池存在的根本原因。
### 2.2 连接池的本质
连接池思想朴素:在应用与数据库之间维护一组常驻、已建立、可复用的后端连接。应用侧大量涌入的连接先接入池,池按策略从预建立的连接中挑一条租给应用,用完归还,而不是每次到数据库重建。它做到三点:大幅降低建连频率、收敛数据库侧真实连接数、平滑承接并发尖峰。
一个关键认知:连接池管理的是**后端连接的数量与生命周期**,而非 SQL 本身。池不执行 SQL,只做报文中转与连接租借。想清楚这一点,后面理解 PgBouncer 的三种模式就不会混淆。
### 2.3 三种池化模式
按"连接何时归还",连接池分三种模式。
**会话级(Session Pooling)**:客户端连接在整个会话生命周期内独占一条后端连接,客户端断开才归还。复用度最低,但兼容性最好,临时表、会话变量、LISTEN/NOTIFY 等特性全部保留,适合强依赖会话状态、并发不高的场景。
**事务级(Transaction Pooling)**:客户端仅在单个事务执行期间租用后端连接,事务结束立即归还。这是 PgBouncer 默认且生产最推荐的模式,能用很小的后端池支撑非常大的客户端并发,是绝大多数 OLTP 场景的标配。
**语句级(Statement Pooling)**:每条语句执行完即归还。复用度最高,但会话状态几乎不可用,也不支持多语句事务,生产一般不推荐。
三种模式的取舍本质是"连接复用度"与"会话兼容性"的权衡,选哪种取决于业务对会话状态的依赖程度。
### 2.4 PgBouncer
PgBouncer 是 C 语言编写、极其轻量的 PostgreSQL 专用连接池,设计哲学是"小而专":只做连接复用,不做 SQL 解析、读写分离与高可用,内存占用极低、转发延迟微秒级。它支持 SCRAM/SHA-256 认证,单配置文件即可部署,是当前接入层最主流的组件。对一个 64G/8CPU 主库,PgBouncer 能把数据库侧真实连接收敛到几十条,同时把客户端并发支撑到几千上万,代价仅是极小 CPU 占用。
### 2.5 Pgpool-II
Pgpool-II 是功能更重的 PostgreSQL 中间件,除连接池外还内置**读写负载均衡、流复制故障转移、并行查询、查询缓存**。它工作在 SQL 层,能解析前端语句判断读写,把读请求分发到从节点、写请求只发主节点。因为功能重、需维护自身连接与状态,部署调优比 PgBouncer 复杂,但它把连接池、读写分离、高可用整合进一个组件,适合一体化方案。
### 2.6 HAProxy
HAProxy 是成熟的四层/七层负载均衡器。在接入架构里通常放在最前充当**流量入口与分发层**:通过 VIP 对外提供统一地址,把应用连接按负载算法分发到后端多个 PgBouncer 或 Pgpool-II,并用健康检查自动摘除故障节点。HAProxy 不懂 SQL,只做 TCP 层连接转发,稳定可靠,是"代理分发"一词的典型承载者。
### 2.7 选型口径
选型建议:只解决连接数瓶颈、追求轻量,优先 PgBouncer;要读写分离与一体化故障转移,选 Pgpool-II;要多实例横向扩展与统一入口,前端加 HAProxy。实践最常见的成熟组合是 HAProxy(分发)+ PgBouncer(连接池)+ PostgreSQL 主从(数据层),这也是风哥教程本文综合架构要落地的形态。
---
## 三、PgBouncer 实战
### 3.1 环境与依赖
本章在 `fgedu-net-cn1` 操作,规格 64G/8CPU。先确认环境并装编译依赖:
```
cat /etc/os-release
free -g
nproc
yum -y install gcc make openssl-devel libevent-devel pam-devel
# Debian/Ubuntu 系用:
# apt-get install -y build-essential libevent-dev libssl-dev libpam0g-dev
```
安装目录统一规划到 `/fgedudb` 下并建运行用户:
```
useradd -s /bin/bash pgbouncer
mkdir -p /fgedudb/app/pgbouncer/{bin,etc,log,run}
chown -R pgbouncer:pgbouncer /fgedudb/app/pgbouncer
```
### 3.2 编译安装
源码编译保证版本可控,标准三连安装:
```
cd /fgedudb/soft
curl -O [https://www.pgbouncer.org/downloads/pgbouncer-1.24.0.tar.gz](https://www.pgbouncer.org/downloads/pgbouncer-1.24.0.tar.gz)
tar -zxvf pgbouncer-1.24.0.tar.gz
cd pgbouncer-1.24.0
./configure --prefix=/fgedudb/app/pgbouncer --with-openssl
make -j 8
make install
/fgedudb/app/pgbouncer/bin/pgbouncer --version
```
风哥 itpux-com
### 3.3 用户列表
PgBouncer 用 `userlist.txt` 做登录校验,用户 `fgedu` 密码需与数据库一致:
```
echo '"fgedu" "fgedu@2026"' > /fgedudb/app/pgbouncer/etc/userlist.txt
chown pgbouncer:pgbouncer /fgedudb/app/pgbouncer/etc/userlist.txt
chmod 600 /fgedudb/app/pgbouncer/etc/userlist.txt
```
### 3.4 主配置
主配置 `/fgedudb/app/pgbouncer/etc/pgbouncer.ini`,针对 64G/8CPU 给出实践参数:
```
[databases]
fgedudb = host=/fgedudb/pgdata port=5432
* = host=/fgedudb/pgdata port=5432
[pgbouncer]
listen_addr = 0.0.0.0
listen_port = 6432
auth_type = md5
auth_file = /fgedudb/app/pgbouncer/etc/userlist.txt
admin_users = pgbouncer
unix_socket_dir = /fgedudb/app/pgbouncer/run
pool_mode = transaction
default_pool_size = 200
max_client_conn = 10000
max_user_connections = 10000
reserve_pool_size = 40
reserve_pool_timeout = 3
server_idle_timeout = 300
server_lifetime = 3600
query_timeout = 30
logfile = /fgedudb/app/pgbouncer/log/pgbouncer.log
pidfile = /fgedudb/app/pgbouncer/run/pgbouncer.pid
```
风哥 itpux-com
要点:`default_pool_size` 200 对应 8 核下可支撑的活跃并发;`max_client_conn` 10000 是接入客户端总上限;`reserve_pool_size` 40 在默认池打满时临时扩容,避免突发流量直接报错。
### 3.5 启动与管理
```
/fgedudb/app/pgbouncer/bin/pgbouncer -d /fgedudb/app/pgbouncer/etc/pgbouncer.ini
sleep 2
ps -ef | grep pgbouncer | grep -v grep
psql -h 127.0.0.1 -p 6432 -U pgbouncer pgbouncer
```
管理控制台内执行:
```
SHOW POOLS;
SHOW CLIENTS;
SHOW SERVERS;
SHOW CONFIG;
```
`SHOW POOLS` 中 `cl_active` 表示正在执行事务的连接,`cl_waiting` 表示排队等待的客户端,`sv_active` 表示后端在用连接,`sv_idle` 表示空闲后端连接,这四项是判断池健康的核心指标。
### 3.6 事务级复用验证
用业务账号 `fgedu` 连接 6432 执行事务:
```
psql -h fgedu-net-cn1 -p 6432 -U fgedu -d fgedudb
BEGIN;
SELECT count(*) FROM pg_stat_activity WHERE datname='fgedudb';
COMMIT;
```
风哥教程 113257174
开两个终端对比观察:一个持续执行事务,一个反复 `SHOW POOLS`。会发现客户端连接数持续增长,而后端 `sv_active + sv_idle` 稳定在较小范围——这就是连接池核心价值:把大量客户端收敛到少量后端连接。
### 3.7 模式切换与调优
切换为会话级验证语义差异:
```
# admin 控制台重载
RELOAD;
# 或信号重载
kill -HUP $(cat /fgedudb/app/pgbouncer/run/pgbouncer.pid)
```
会话级下只要客户端不断开,后端连接就被独占,`sv_active` 随客户端数同步增长。事务级"事务结束即归还",会话级"会话结束才归还",对比即懂。
风哥教程 113257174
调优三条经验:后端真实连接数建议控制在 150~300,过大增加调度开销;`query_timeout` 结合最慢 SQL 时长设定,太短误杀慢查询、太长堆积挂起;用 `SHOW STATS` 观察 `total_client_conn` 与 `total_server_conn` 比值,比值越高复用越好。
---
## 四、Pgpool-II 实战
### 4.1 安装
在 `fgedu-net-cn1` 与 `fgedu-net-cn2` 搭建 Pgpool-II:
```
yum -y install gcc make openssl-devel pam-devel
cd /fgedudb/soft
curl -O [https://www.pgpool.net/downloads/pgpool-II-4.5.tar.gz](https://www.pgpool.net/downloads/pgpool-II-4.5.tar.gz)
tar -zxvf pgpool-II-4.5.tar.gz
cd pgpool-II-4.5
./configure --prefix=/fgedudb/app/pgpool --with-openssl
make -j 8
make install
```
核心配置位于 `/fgedudb/app/pgpool/etc`,文件为 `pgpool.conf` 与 `pcp.conf`。
### 4.2 后端节点
`pgpool.conf` 定义后端节点,两节点按权重分配读流量:
```
backend_hostname0 = 'fgedu-net-cn1'
backend_port0 = 5432
backend_weight0 = 0.7
backend_hostname1 = 'fgedu-net-cn2'
backend_port1 = 5432
backend_weight1 = 0.3
```
风哥数据库教程 itpux-com
主节点承担 70% 读请求,从节点承担 30%,写请求永远只发主节点。
### 4.3 连接池与负载均衡
```
connection_cache = on
num_init_children = 64
max_pool = 8
load_balance_mode = on
ignore_leading_white_space = on
```
8 核下 `num_init_children` 设为 64,即预建 64 个后端连接作为池;`max_pool` 为 8,表示每个后端连接的最大复用规模。
### 4.4 健康检查与故障转移
```
health_check_period = 10
health_check_timeout = 20
health_check_user = 'fgedu'
health_check_password = 'fgedu@2026'
health_check_max_retries = 3
health_check_retry_delay = 1
failover_command = '/fgedudb/app/pgpool/bin/failover.sh %d %h %H'
```
创建故障转移脚本:
```
#!/bin/bash
OLD_PRIMARY_ID=$1
OLD_PRIMARY_HOST=$2
NEW_PRIMARY_HOST=$3
echo "$(date) failover: old=$OLD_PRIMARY_HOST new=$NEW_PRIMARY_HOST" >> /fgedudb/app/pgpool/log/failover.log
chmod +x /fgedudb/app/pgpool/bin/failover.sh
```
### 4.5 启动与负载均衡验证
初始化 PCP 用户并启动:
```
echo 'pgpool:$(echo -n "pgpool@2026" | md5sum | awk "{print \$1}")' > /fgedudb/app/pgpool/etc/pcp.conf
/fgedudb/app/pgpool/bin/pgpool -f /fgedudb/app/pgpool/etc/pgpool.conf
/fgedudb/app/pgpool/bin/pcp_node_info 1 localhost 9898 pgpool pgpool@2026
```
客户端经 9999 端口连接,观察读请求是否按 0.7/0.3 分发:
```
psql -h fgedu-net-cn1 -p 9999 -U fgedu -d fgedudb
```
网上搜索风哥教程可以学习全套数据库教程
连接后执行只读查询,再到主、从库分别查活跃会话,即可确认读写分离是否生效。
### 4.6 故障转移演练
停掉从节点 `fgedu-net-cn2` 的数据库,观察自动摘除:
```
pg_ctl -D /fgedudb/pgdata stop -m fast
# cn1 查看节点状态
/fgedudb/app/pgpool/bin/pcp_node_info 1 localhost 9898 pgpool pgpool@2026
```
健康检查周期 10 秒、失败重试 3 次后节点被标记 `down`,流量自动集中主节点。恢复后重新挂回:
```
/fgedudb/app/pgpool/bin/pcp_attach_node 1 localhost 9898 pgpool pgpool@2026
```
---
## 五、HAProxy 实战
### 5.1 安装
在 `fgedu-net-cn1` 安装 HAProxy 作为最前分发层:
```
yum -y install haproxy
# 或源码安装
cd /fgedudb/soft
curl -O [https://www.haproxy.org/download/2.9/src/haproxy-2.9.0.tar.gz](https://www.haproxy.org/download/2.9/src/haproxy-2.9.0.tar.gz)
tar -zxvf haproxy-2.9.0.tar.gz
cd haproxy-2.9.0
make TARGET=linux-glibc USE_OPENSSL=1 USE_PCRE2=1 USE_SYSTEMD=1
make install
```
### 5.2 四层代理配置
配置 `/etc/haproxy/haproxy.cfg`,把两个 PgBouncer(6432)作为分发目标:
```
global
maxconn 20000
log 127.0.0.1 local0
ulimit-n 65535
defaults
mode tcp
timeout connect 5s
timeout client 30s
timeout server 30s
frontend pg_in
bind *:5432
default_backend pg_pool
backend pg_pool
balance roundrobin
option httpc-h-k GET /health
server pool1 fgedu-net-cn1:6432 check inter 5s fall 3 rise 2
server pool2 fgedu-net-cn2:6432 check inter 5s fall 3 rise 2
```
`roundrobin` 轮询分发,每 5 秒健康检查,连失 3 次摘除、恢复 2 次挂回;`maxconn 20000` 匹配 8 核承载。
风哥数据库教程 itpux-com
### 5.3 启动与验证
```
haproxy -f /etc/haproxy/haproxy.cfg -c
systemctl start haproxy
ss -lntp | grep 5432
psql -h fgedu-net-cn1 -p 5432 -U fgedu -d fgedudb
```
上51CTO搜索风哥可以学习全套数据库教程
### 5.4 分发与摘除
并发连接后查 HAProxy 统计页确认轮询分发到 `pool1`、`pool2`。手动停掉 `pool2`,下一轮健康检查自动摘除,新连接全导向 `pool1`;恢复后自动挂回。这套机制保证接入层高可用。
---
## 六、综合架构与端到端验证
### 6.1 三层接入架构
最终落地三层接入架构:
```
应用客户端
│ 连接 fgedu-net-cn1:5432 统一入口
▼
HAProxy 代理分发 / 四层负载均衡
│ roundrobin 分发
▼
PgBouncer 连接池(6432) × 2
│ 事务级复用
▼
PostgreSQL 主(fgedu-net-cn1) / 从(fgedu-net-cn2)
```
应用只认 HAProxy 单一地址,HAProxy 分发给两个 PgBouncer,PgBouncer 把海量客户端收敛为少量后端连接,数据库并发被牢牢控制。
### 6.2 端到端压测脚本
```
cat > /fgedudb/soft/loadtest.sh <<'EOF'
#!/bin/bash
for i in $(seq 1 2000); do
psql -h fgedu-net-cn1 -p 5432 -U fgedu -d fgedudb \
-c "SELECT count(*) FROM pg_stat_activity;" >/dev/null 2>&1 &
done
wait
EOF
chmod +x /fgedudb/soft/loadtest.sh
/fgedudb/soft/loadtest.sh
```
压测期间分别观察三层连接状态:客户端并发 2000,PgBouncer 侧 `max_client_conn` 正常承接,数据库侧活跃连接被收敛到几百以内,无 `too many connections` 报错。
网上搜索风哥教程可以学习全套数据库教程
### 6.3 故障场景演练
依次演练:停一个 PgBouncer,HAProxy 自动摘除、连接仍可从另一入口进入;停从节点 PostgreSQL,健康检查摘除、读流量集中主节点;停主节点数据库,配合数据库层流复制提升与故障转移脚本完成切换。每次演练在业务侧确认连接可重连、不断线。
上51CTO搜索风哥可以学习全套数据库教程
---
## 七、风哥针对本文总结
本套风哥教程围绕 PostgreSQL 连接池管理与代理分发,完整落地三件套:PgBouncer 用最小代价解决连接数瓶颈,事务级池化把数千客户端收敛为数百后端连接;Pgpool-II 在连接池上叠加读写负载均衡与故障转移,读流量按权重分发、故障自动摘除;HAProxy 提供统一入口与四层代理分发,用健康检查保证接入层高可用。三者职责清晰、互为补充,组合即生产可用的数据库接入架构。
风哥针对本文总结三点要点。第一,选型看规模与诉求:只求连接复用、追求轻量选 PgBouncer;要一体化读写分离与高可用选 Pgpool-II;要横向扩展与统一入口前端加 HAProxy。第二,连接池参数贴合硬件规格:本文全部配置按 64G 内存、8 核 CPU 给出,后端连接数、并发上限、健康检查周期须随资源与业务重新评估,切忌生搬硬套。第三,任何接入层必须做故障演练,健康检查、摘除、重挂、切换只有真实演练才能验证可靠,生产才可放心依赖。
最后,整套部署、配置与验证方法可在 `/fgedudb` 路径体系下按章节顺序复现。记住核心结论:连接池解决连接数的"数量"问题,代理分发解决流量的"流向"问题,两者结合既能管得住并发、又分得清读写,让 PostgreSQL 在高并发下稳定运行。
来自 “ ITPUB博客 ” ,链接:https://blog.itpub.net/9664900/viewspace-3186254/ ,如需转载,请注明出处,否则将追究法律责任。