ITPub博客

首页 > 数据库 > PostgreSQL > 数据库教程FGMT60-PostgreSQL连接池管理与代理分发

数据库教程FGMT60-PostgreSQL连接池管理与代理分发

原创 PostgreSQL 作者:mfkqwyc86 时间:2026-10-21 11:16:47 0 删除 编辑

数据库教程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/ ,如需转载,请注明出处,否则将追究法律责任。

请登录后发表评论 登录
全部评论
风哥Oracle,MySQL,PostgreSQL,Linux,大数据,国产数据库,中间件等教程

注册时间:2010-10-26

  • 博文量
    78
  • 访问量
    407503