34.PostgreSQL连接池中间件pgbouncer的部署和配置详解

PostgreSQL连接池中间件pgbouncer的部署和配置详解

一、前言

背景

  • ‌起源与历史‌:pgbouncer最初由PostgreSQL社区开发,旨在解决PostgreSQL多进程架构下连接开销大的问题。其设计轻量级,自发布以来已成为PostgreSQL生态中的标准工具之一,拥有较长的使用历史和稳定的版本迭代。例如,在2026年,最近的版本更新是在2025年12月3号,再上次更新是在2025年11月9号。 ‌
  • ‌成熟度与采用‌:pgbouncer支持多种连接池模式(如会话、事务、语句级),具备在线重配置、低内存占用等特性,并被广泛应用于生产环境,尤其在需要高并发连接的场景中。这表明它是一个经过实践验证的成熟工具。 ‌
  • 工作机制:postgresql数据库 是多进程结构,每新增一个会话就会新增一个进程,相对而言对数据库的开销就会比较巨大。

因为在正常业务会话中,有不少session 都有长时间的 idle的状态,而这个状态导致,此时如果需要连接,就需要建立新的进程,来访问数据库,那么连接数就上来了. 而使用pgbouncer的主要原因

PGBrouncer能够缓存和PostgreSQL的连接,当有连接请求进来的时候,直接分配pgbouncer与postgresql之间的空闲连接去执行,而不需要PostgreSQL fork出新进程来建立连接,以节省创建新进程,创建连接的资源消耗。

关键的是pgbouncer是使用libevent进行socket通信,通信效率高。每个连接仅消耗2kB内存。相对pg自身动辄 4MB 的work_mem算是很轻量级了。

如果要用大白话来说,没有使用pgbouncer的连接方式是私家车,如果车子太多,则路就塞满了,而使用了pgbouncer 的方式则类似公交车或小巴, 有人上车有人下车,座位是固定的,所以公交车如果本身有30个座位,但实际上在整个的路途中可不是仅仅支持30个人,至于支持了多少人,那就看连接到数据库的事务执行的快慢,是否能对一个连接进行复用, 这就有点CPU 的分时使用的概念.

因此,用 postgresql数据库而不用连接池,绝对是坑爹的做法…… 哪怕是像 pgbouncer 这样的“轻量级”连接池,有和没有的区别都不是一般的大。虽然这句话说得比较绝对,但从某种角度上来讲,这句话是有一定道理的。

二、pgbouncer的版本问题

下面将就pgboucer这个轻量级别的数据库中间件如何部署,如何正确的使用做一个简单的介绍。
https://github.com/pgbouncer/pgbouncer/releases 该网址是pgbouncer的官方下载地址,从其最新版本更新介绍来看,非常有必要使用最新版,也就是1.25.1版本,选择该版本的理由是此版本修复了一个严重的安全漏洞:CVE-2025-12819
image

顺便说一句,为什么反复提到这个pgbouncer是一个轻量级的数据库中间件?主要是这个中间件源码包实在是太小了,才3 400 KB大小,但该中间件所起的作用却是十分巨大的,对于postgresql数据库而言,如果配置得当,会是对服务器的一个性能非常巨大的优化。

三、pgbouncer的运行机制

前面也提到了,pgbouncer和数据库以及业务层面的通信机制是基于libevent这个类库实现的。

那么,可能有同学就会提出疑问了,为什么不用libuv呢?这个类库更屌啊,但是livuv并不支持ssl协议,ssl层面需要用户自行处理,并且libevent是直接基于openssl的,因此,libevent是相对来说在Linux环境下,是更稳定,可靠的一个类库。

ok,那么,pgbouncer是如何工作的呢?其实也非常的简单,业务应用层面如果不使用中间件,那么,就是直连postgresql数据库,可想而知,如果业务应用层面有突发的高并发密集计算,对于postgresql数据库的冲击将可能是一个灾难性的事情;如果使用pgbouncer中间件来统一管理postgresql数据库的连接,也就是pgbouncer一端连接数据库,这个在pgbouncer叫server层,pgbouncer另一端连接业务应用层,这个在pgbouncer叫client 层,那么,pgbouncer将会是一个非常好的缓冲层,可以简单理解为redis这样的中间件。

  • 连接池管理:PgBouncer 在启动后会与后端的 PostgreSQL 数据库(Server 层)建立并维护一个固定数量的稳定连接池。当前端的应用程序(Client 层)发起连接请求时,PgBouncer 不会立即向数据库创建新连接,而是尝试从池中分配一个空闲的现有连接给它使用 。这极大地减少了数据库因频繁创建和销毁连接而产生的性能开销。

  • 三种池化模式:这是 PgBouncer 的精髓,它决定了连接何时被回收到池中供其他客户端复用 :

    • 会话模式(Session):连接在客户端整个会话期间被占用,直到客户端断开连接才释放。这是最保守的模式,兼容性最好。
    • 事务模式(Transaction):这是最常用且高效的模式。连接仅在事务期间被占用,一旦事务提交(Commit)或回滚(Rollback),连接立即释放回池中。这实现了连接的最大化复用,完美应对高并发短事务场景 。
    • 语句模式(Statement):连接在执行完一条 SQL 语句后立即释放。此模式兼容性限制最多,较少使用。
  • 轻量级与高效性:PgBouncer 本身是一个非常轻量级的进程,采用 Libevent 进行高性能的 Socket 通信 。它主要负责转发数据包,而不解析或修改 SQL 内容,因此自身资源消耗极低,每个连接仅消耗约 2KB 内存 ,却能管理上百个数据库连接

这里有一个小问题,如果我们业务应用层面是使用的微服务,那么,微服务的连接池和pgbouncer这个连接池会不会冲突呢?
微服务连接池(如 HikariCP, Druid):
作用层级:管理从微服务应用到 PgBouncer​ 之间的TCP连接。
核心职责:为应用程序提供高效的、可复用的数据库连接。它负责连接的创建、验证、健康检查、归还等。它关注的是如何让应用快速拿到一个“可用连接”,这个连接的目的地是 PgBouncer。

PgBouncer 连接池:
作用层级:管理从 PgBouncer​ 到 PostgreSQL 数据库​ 之间的TCP连接。
核心职责:作为数据库的“缓冲门卫”,它建立并维护一个到真实 PostgreSQL 的固定大小的连接池。它的目标是防止过多的应用连接直接压垮数据库,通过复用数量较少的数据库连接来服务大量的应用请求。

为了让两者协同达到最佳效果,建议如下:
超时时间设置:
将微服务连接池的最大生命周期(如 maxLifetime)​ 设置为略小于 PgBouncer 的连接生命周期(server_lifetime)。
例如:微服务设置 maxLifetime = 25分钟,PgBouncer 设置 server_lifetime = 30分钟。
好处:这样微服务连接池会主动地、有计划地重建连接,避免应用尝试使用一个已经被 PgBouncer 关闭的数据库连接,从而产生错误。

连接池大小设置:
微服务连接池大小:可以根据每个微服务实例的并发需求来设置(例如 maximum-pool-size = 20)。
PgBouncer 连接池大小:应该根据后端 PostgreSQL 数据库能承受的最大并发连接数来设置(例如 max_db_connections = 200)。所有微服务实例的连接总数不应超过这个限制。

启用健康检查:
务必开启微服务连接池的心跳检测(如 connection-test-query)。这样连接池能及时发现并替换掉已经失效的连接(比如由于网络闪断或 PgBouncer 重启导致的连接关闭)。
因此,可以明确的一个结论是,微服务连接池和 PgBouncer 不仅不冲突,反而是现代微服务架构中保护数据库、提升系统扩展性和稳定性的标准最佳实践。它们构成了一个高效的二级缓冲系统,正确配置后能极大地提升应用的性能和韧性。

四、pgbouncer的安装和使用

1. 安装 PgBouncer

Ubuntu/Debian 系统:

sudo apt-get update
sudo apt-get install pgbouncer

CentOS/RHEL 系统:

sudo yum install pgbouncer

2. 基本配置

编辑主配置文件(通常位于/etc/pgbouncer/pgbouncer.ini):

[databases]
yourdb = host=127.0.0.1 port=5432 dbname=yourdb user=youruser password=yourpass

[pgbouncer]
; 基本设置
listen_addr = 127.0.0.1
listen_port = 6432
auth_type = md5
auth_file = /etc/pgbouncer/userlist.txt

; 连接池设置
pool_mode = transaction
max_client_conn = 1000
default_pool_size = 20
reserve_pool_size = 5

; 日志设置
log_connections = 1
log_disconnections = 1
log_pooler_errors = 1

eg:
 test= host=192.168.201.51 port=5432 dbname=test user=postgres password=postgres

[pgbouncer]
; 基本设置
listen_addr = 192.168.201.51
listen_port = 6432
auth_type = md5
auth_file = /etc/pgbouncer/userlist.txt

; 连接池设置
pool_mode = transaction
max_client_conn = 1000
default_pool_size = 20
reserve_pool_size = 5

; 日志设置
log_connections = 1
log_disconnections = 1
log_pooler_errors = 1

test可以随便,可以看作是数据库别名,业务层连接的时候就用这个别名,connect_query='SELECT 1' 可以根据业务需求,修改为connect_query='set search_path to shema名称'

3. 创建认证文件

创建用户列表文件/etc/pgbouncer/userlist.txt:

查询MD5密码:
SELECT * FROM pg_shadow
SELECT usename, passwd FROM pg_shadow 

echo '"postgres" "SCRAM-SHA-256$4096:IFrgAlfuN7OPchSdRDRFOw==$hve67cGWKsDkzTv7JLUz/rMcIt5cMZ2cWK/YPFENxc0=:HJ8qqq4h4Qw/poJD7NXHLAbGkYP/ERictkAH+UxRlBc="' | sudo tee /etc/pgbouncer/userlist.txt

echo '"youruser" "md5yourpasswordhash"' | sudo tee /etc/pgbouncer/userlist.txt

4. 启动 PgBouncer

启动服务:
sudo systemctl start pgbouncer

设置开机自启:
sudo systemctl enable pgbouncer

检查状态:
sudo systemctl status pgbouncer

5. 验证连接

使用 psql 测试连接:

psql -p 6432 -U postgres -h 127.0.0.1 test

6. 高级配置建议

1.连接池模式选择:

  • session:客户端连接期间保持一个数据库连接
  • transaction:每个事务结束后释放连接(推荐)
  • statement:每条语句后释放连接(限制最多

2.调整池大小:

; 根据你的PostgreSQL max_connections设置
max_client_conn = 1000     ; 客户端最大连接数
default_pool_size = 50     ; 每数据库常规池大小
reserve_pool_size = 10     ; 备用连接池大小

3.监控配置:

stats_period = 60          ; 统计信息收集间隔(秒)
log_stats = 1              ; 记录统计信息
admin_users = adminuser    ; 管理员用户
  1. 常用管理命令
    (1).查看连接池状态:
psql -p 6432 -U pgbouncer pgbouncer -c "SHOW pools;"

(2).重新加载配置(不中断连接):

sudo systemctl reload pgbouncer

(3).查看统计信息:

psql -p 6432 -U pgbouncer pgbouncer -c "SHOW stats;"

注意事项

  • 确保 PostgreSQL 的 max_connections 设置足够大(至少是 PgBouncer 的 default_pool_size 乘以数据库数量)
  • 对于生产环境,建议将 PgBouncer 和 PostgreSQL 安装在不同的服务器上
  • 定期检查日志(通常位于/var/log/postgresql/pgbouncer.log)
  • 如果使用 PgBouncer 管理界面,请确保设置强密码并限制访问 IP
posted @ 2026-05-19 13:51  数据库小白(专注)  阅读(84)  评论(0)    收藏  举报