PgBouncer 解决 PostgreSQL 连接数超限 + 可视化监控

写在前面:

在Linux服务器部署PostgreSQL数据库(尤其搭配Dify等高频连接类应用)时,"连接数超限"是最常见且棘手的问题之一------轻则导致应用无法建立新连接、接口报错,重则造成数据库僵死、服务不可用,就像此前遇到的"无法登录PostgreSQL、kill进程权限不足"的困境,本质都是连接管理失控所致。PostgreSQL默认的连接数配置有限,且每一个数据库连接都会占用一定的系统内存和资源,当高并发请求来袭或应用存在连接泄漏时,很容易突破连接上限,引发服务故障。

一、PgBouncer介绍

1、简要介绍

PgBouncer作为一款轻量级、高性能的PostgreSQL连接池中间件,正是解决这一痛点的核心工具。它通过"连接复用"机制,将应用发起的大量连接进行集中管理、动态分配,让有限的PostgreSQL原生连接能够支撑数千甚至上万的客户端请求,从根源上杜绝连接数超限问题,同时降低数据库的资源消耗,提升服务稳定性。相较于单纯调大PostgreSQL的max_connections参数,PgBouncer无需占用过多系统资源,配置灵活且部署便捷,是生产环境中优化PostgreSQL连接管理的首选方案。

官方网址:PgBouncer - lightweight connection pooler for PostgreSQL

性能对比可参考:PgBouncer实战指南:如何优化PostgreSQL连接池性能与稳定性_ss78901-腾讯云开发者社区

2、数据流转工作原理
  • 接入转发: 所有业务程序、项目(Dify、后台服务、接口服务等)不再直连 PG,统一连接PgBouncer 代理端口

  • **连接池收纳:**PgBouncer 接收海量客户端连接,进行统一缓存、排队、管控,限制并发接入量。

  • 连接复用: 按照事务级 / 会话级复用空闲数据库物理连接,客户端断开不销毁 PG 真实连接。

  • **下发执行:**将精简后的有效请求转发至后端 PostgreSQL 执行 SQL。

  • **回收归还:**请求 / 事务结束后,立刻把 PG 物理连接回收至连接池,供其他客户端复用。

3、直连 VS PgBouncer 对比简图

传统直连(易爆连接)

应用1 → PG直连

应用2 → PG直连

应用3 → PG直连

...

连接快速打满 → 报错 too many connections

PgBouncer 代理(稳定限流)

应用1 ──┐

应用2 ──┤

应用3 ──┼──→ PgBouncer ──少量固定连接──→ PostgreSQL

应用4 ──┘

二、前置准备

1、环境说明
  • 数据库:PostgreSQL(默认端口 5432)

  • 连接池:PgBouncer(统一转发连接,收敛连接数)

  • 可视化:PgBouncerHero 网页面板 + Prometheus+Grafana 监控

  • 系统:Linux Ubuntu

2、开放防火墙端口

端口6432为PgBouncer 的代理端口 (应用连接使用),端口8090为可视化/监控端口 (Prometheus/Grafana/Exporter),sudo ufw reload为重载防火墙规则。

复制代码
sudo ufw allow 6432/tcp
sudo ufw allow 8090/tcp
sudo ufw reload

三、安装部署 PgBouncer

1、安装与初始化
复制代码
sudo apt update
sudo apt install -y pgbouncer

创建目录(记录日志文件和pgBouncer 运行的进程号):

复制代码
sudo mkdir -p /var/log/pgbouncer
sudo mkdir -p /var/run/pgbouncer

修改目录所有者(默认为pg数据库的postgre用户):

复制代码
sudo chown -R postgres:postgres /var/log/pgbouncer
sudo chown -R postgres:postgres /var/run/pgbouncer
2、配置 PgBouncer
复制代码
sudo nano /etc/pgbouncer/pgbouncer.ini

打开以后把里面内容全部替换成下面这段:

复制代码
[databases]
my_db = host=127.0.0.1 port=5432 dbname=production_db

[pgbouncer]
listen_addr = 0.0.0.0
listen_port = 6432

auth_type = md5
auth_file = /etc/pgbouncer/userlist.txt
admin_users = postgres

pool_mode = transaction

max_client_conn = 1000
default_pool_size = 50
min_pool_size = 10
server_idle_timeout = 600

logfile = /var/log/pgbouncer/pgbouncer.log
pidfile = /var/run/pgbouncer/pgbouncer.pid
stats_users = postgres

点击Ctrl+O保存,回车,点击Ctrl+X退出。

3、配置文件解释说明

(1)[databases]:第一后端目标

这部分告诉 PgBouncer:"当有人连接我时,你应该把这些流量转发到哪里"。

  • my_db (别名) :这是你在连接数据库时使用的名称。例如,你提供的连接字符串是 ...:6432/my_db,PgBouncer 会解析到后面定义的参数。

  • host=127.0.0.1 port=5432:这是真实的数据库服务地址。

  • dbname=production_db :这是数据库内部的真实库名。通过别名映射,你甚至可以实现"应用连接的是库A,实际存取的是库B"的隐藏效果。

(2)[pgbouncer]:核心运行逻辑

监听与认证

  • listen_addr & listen_port:0.0.0.0 表示允许任意 IP 连接(生产环境建议限制 IP),6432 是对外提供的服务入口。

  • auth_type = md5:强制使用 MD5 密码加密校验,确保安全性。

  • auth_file:指向用户列表文件,PgBouncer 在这里匹配用户名和加密后的密码。

  • admin_users = postgres:拥有管理权限的用户,通过 psql -p 6432 -U postgres -d pgbouncer 登录后,可以使用如 SHOW POOLS; 或 RELOAD; 等管理指令。

池化逻辑 (核心)

  • pool_mode = transaction:这是 PgBouncer 的精髓。

  • 在 transaction 模式下,连接池只在事务级别复用。这意味着一个客户端连接执行完一条 SQL(或一个事务)后,该数据库连接就会被释放,迅速给其他客户端使用。

  • 区别:如果设置成 session,一个客户端会占用一个连接直到断开,这样依然会很快耗尽后端连接。

连接池调优参数

  • max_client_conn = 1000:这是你系统能承受的应用并发上限。如果第 1001 个连接请求进来,PgBouncer 会拒绝它,保护数据库不被压垮。

  • default_pool_size = 50:这是对数据库真实的"负载阀门"。不管前面有 1000 个请求,后端只会建立 50 个物理长连接,这 50 个连接在 1000 个请求间快速切换。

  • min_pool_size = 10:预热池。系统启动时会保持 10 个连接,避免流量突然到来时频繁创建新连接带来的 TCP 握手开销。

  • server_idle_timeout = 600:如果后端连接闲置超过 600 秒(10分钟),PgBouncer 会主动断开它们,释放数据库端的资源。

系统维护与监控配置

  • logfile & pidfile:这是运行期的轨迹追踪。pidfile 确保同一时间只有一个 PgBouncer 进程在运行,防止配置冲突或资源竞争。

  • stats_users = postgres:这非常重要。只有在这里指定的账号,登录 pgbouncer 数据库后,才能查看当前的连接状态、等待数(cl_waiting)等信息。

4、配置数据库账号密码
复制代码
sudo nano /etc/pgbouncer/userlist.txt

在这里写的用户名,必须是前面填写的dbname=production_db数据库中实际存在的数据库角色(Role/User),但当你需要通过 PgBouncer 以数据库超级管理员身份进行某些维护操作,或者进行监控采集时还可以填写postgres用户,postgres用户拥有最高权限,如果泄露,风险极高。写入的示例如下:

复制代码
"postgres" "你的密码"

点击Ctrl+O保存,回车,点击Ctrl+X退出。

5、启动 PgBouncer
复制代码
sudo systemctl restart pgbouncer
sudo systemctl enable pgbouncer
sudo systemctl status pgbouncer

看到 active (running) 就是成功运行。

6、测试连接

所有人不再直连 5432,统一连接:

  • IP:数据库服务器 IP

  • 端口:6432

  • 账号密码库名不变

输入以下指令测试:

复制代码
psql -h 127.0.0.1 -p 6432 -U postgres -d postgres

注意:这里的-U postgres表示以"哪个账号"身份来发起连接的,-d postgres告诉 PostgreSQL,你想进入哪一个具体的数据库。psql -U 用户名 -d 数据库名中的这两个参数,必须在你的 PgBouncer 配置文件 ( /etc/pgbouncer/pgbouncer.ini**)** 和 用户认证文件 ( /etc/pgbouncer/userlist.txt**)** 中都能找到对应的记录。

如果这个测试通过了,说明你的 PgBouncer 通道完全通畅。

四、PgBouncer 自带命令行管理

1、连接管理控制台
复制代码
psql -h 127.0.0.1 -p 6432 -U postgres pgbouncer
2、常用的查询命令

(1)监控与状态查询

复制代码
SHOW POOLS;         -- 查看连接池概况(观察 cl_waiting 是否有积压)
SHOW CLIENTS;       -- 查看所有接入的客户端连接(含IP、连接时长)
SHOW SERVERS;       -- 查看 PgBouncer 与后端 PG 的连接状态
SHOW STATS;         -- 查看流量、查询吞吐量及平均延迟统计
SHOW LISTS;         -- 查看当前系统分配的各种资源列表(如池、客户端、服务器数)

SHOW POOLS;

作用:查看当前所有连接池的概况。

关键指标:

  • cl_active:当前正在执行 SQL 的客户端连接数。

  • cl_waiting:正在排队等待数据库连接的客户端数(如果数值长期大于 0,说明连接池不够用了)。

  • sv_active:当前正在与后端数据库通信的连接数。

  • sv_idle:后端数据库中处于空闲状态的连接数。

SHOW STATS;

作用:查看全局统计数据(自启动以来的累计值)。

  • 关注点:avg_query_time(平均查询耗时)和 total_xact_time(事务总耗时),这能帮你评估性能瓶颈。

SHOW CLIENTS;

作用:查看所有当前连接到 PgBouncer 的客户端详情(包括 IP、连接时间、请求状态)。

SHOW SERVERS;

作用:查看 PgBouncer 连接到后端数据库的连接状态(可以看到哪些连接是空闲的、哪些正在处理事务)。

(2)配置管理

复制代码
SHOW CONFIG;        -- 查看当前生效的全部配置参数
RELOAD;             -- 热加载配置文件(无需重启服务,修改 .ini 后执行)

SHOW CONFIG;

作用:列出当前 PgBouncer 正在使用的所有配置参数及其当前值。当你修改了 pgbouncer.ini 后,可以用此命令确认配置是否生效。

SHOW VERSION;

作用:查看当前运行的 PgBouncer 版本。

(3)维护与控制

复制代码
PAUSE;              -- 暂停所有连接池(断开后端连接,挂起客户端请求,用于维护)
RESUME;             -- 恢复暂停的连接池
KILL <数据库名>;    -- 强制断开并关闭与指定数据库的所有后端连接
SHUTDOWN;           -- 关闭 PgBouncer 服务进程

RELOAD;

作用:重新加载配置文件 (pgbouncer.ini)。如果你修改了配置,无需重启进程,执行该命令即可热加载。

PAUSE;

作用:暂停所有连接池。PgBouncer 会尝试断开与后端数据库的连接,并将后续进来的客户端连接挂起。常用于数据库维护操作前。

RESUME;

作用:恢复被 PAUSE 挂起的连接池。

KILL <数据库名>;

作用:强制断开与指定数据库相关的所有服务器连接。注意:这是强力操作,会丢弃当前正在进行的未提交事务。

(4)异常处理

复制代码
-- 1. 先查找异常连接的 PID(在 SHOW CLIENTS 的输出结果中查看)
SHOW CLIENTS;

-- 2. 使用 KILL 命令踢出(注意:PgBouncer 中 KILL 后接的是连接地址或特定标识,非系统进程ID)
KILL <连接ID或数据库名>;

五、部署可视化网页面板 PgBouncerHero

说明:

这一部分实现

Linux 上的 PgBouncer → Windows 上部署 PgBouncerHero 网页面板 → 远程连接监控

PgBouncerHero 本质上是:一个连接 PgBouncer Admin Console 的 Rails Web UI

它会执行:SHOW STATS;SHOW POOLS;SHOW CLIENTS;SHOW SERVERS;然后可视化展示。

1、准备工作

(1)改 pgbouncer.ini(Linux)

复制代码
[pgbouncer]
listen_addr = 0.0.0.0          ; 允许所有IP连,不要只写 localhost
listen_port = 6432
auth_type = md5
auth_file = /etc/pgbouncer/userlist.txt
admin_users = postgres          ; 后面网页要用这个账号登录管理

(2)防火墙开放 6432 端口(Linux)

复制代码
sudo ufw allow 6432/tcp

(3)userlist.txt 确保有管理员密码(Linux)

复制代码
# 格式:"用户名" "密码"
"postgres" "你的postgres密码"

(4)重启pgbouncer

复制代码
sudo systemctl restart pgbouncer

(5)需要的环境

  • Windows 11

  • WSL2(Ubuntu)

  • Docker(用于 PgBouncer)

2、WSL 安装 Ruby + PgBouncerHero

(1)安装 Ruby环境

在WSL或者Ubuntu内执行:

复制代码
sudo apt update
sudo apt install -y \
  git \
  curl \
  build-essential \
  libssl-dev \
  zlib1g-dev \
  libyaml-dev \
  libreadline-dev \
  libpq-dev

安装rbenv:

复制代码
curl -fsSL https://github.com/rbenv/rbenv-installer/raw/main/bin/rbenv-installer | bash

如果失败尝试以下方法:

复制代码
git clone https://ghfast.top/https://github.com/rbenv/ruby-build.git ~/.rbenv/plugins/ruby-build

git clone https://mirror.ghproxy.com/https://github.com/rbenv/ruby-build.git ~/.rbenv/plugins/ruby-build

然后配置环境变量:

复制代码
echo 'export PATH="$HOME/.rbenv/bin:$PATH"' >> ~/.bashrc
echo 'eval "$(rbenv init - bash)"' >> ~/.bashrc
source ~/.bashrc

rbenv安装验证:

复制代码
rbenv --version

查看可以安装的Ruby版本:

复制代码
rbenv install -l

这里选择安装3.4.9版本:

复制代码
rbenv install 3.4.9

需要等待一会,安装完成后:

复制代码
rbenv global 3.4.9

验证安装:

复制代码
ruby -v

(3)安装pgbouncerhero

转移到pgbouncerhero所在的文件夹,运行以下命令:

复制代码
cd /mnt/e/pgbouncer/pgbouncerhero
bundle install

看到Bundle complete!即为安装依赖成功。

验证安装:

复制代码
bundle list | grep pgbouncerhero

说明 gem 已安装成功。

(4)测试连接

在WSL中运行(换成你的服务器IP):

复制代码
psql -h 172.xx.xx.xxx -p 6432 -U postgres pgbouncer

执行:

复制代码
SHOW DATABASES;

若看到你之前在pgbouncer中配置的数据库名称,则说明PgBouncer正常。

3、启动PgBouncerHero

(1)设置环境变量

复制代码
export PGBOUNCERHERO_DATABASE_URL="postgres://postgres:password@172.XX.XX.XX:6432/pgbouncer"

(2)启动Hero

复制代码
bundle exec rackup test/dummy/config.ru -p 3000 -o 0.0.0.0

(3)访问UI

浏览器打开:http://localhost:3000/pgbouncerhero

4、PgBouncerHero可视化界面介绍

(1)Databases (数据库概览)

含义:显示了当前配置的哪些数据库名(数据库别名)被允许访问,以及它们分别映射到哪个物理后端数据库。

关键列:

  • Name: 数据库的逻辑名称。

  • Host/Port: 实际指向的后端 PostgreSQL 服务器地址和端口。

  • Database: 后端实际的物理数据库名。

  • Force_user: 是否强制使用特定用户连接后端,忽略客户端传入的用户名(常用于连接池共享)。

  • 作用:用于核对连接的路由配置是否正确,确保流量被导向了预期的数据库。

(2)Pools (连接池状态 - 最重要)

含义:描述了"客户端到 PgBouncer"与"PgBouncer 到 PostgreSQL"之间的连接桥梁状态。

关键列(参考上一条回复的指标):

  • Cl_active / Cl_waiting: 客户端的流量压力。

  • Sv_active / Sv_idle: 后端数据库的承载负载。

(3)Clients (客户端连接)

含义:列出所有已连接到 PgBouncer 的应用端(如 Web 服务、后台任务)的连接信息。

关键列:

  • Caddr: 客户端的 IP 地址和端口。

  • User: 连接使用的数据库用户名。

  • Database: 正在访问的数据库。

  • State: 客户端状态(如 active 表示正在执行查询,idle 表示等待中)。

  • Wait_time: 该连接进入等待状态的时间(如果是 0 表示正在处理中)。

(4)Stats (统计信息)

含义:展示了系统级别的流量处理能力和性能开销。

关键指标:

  • Total_requests: 累计处理的 SQL 请求总数。

  • Total_query_time: 所有查询累计耗时(微秒)。

  • Avg_query_time: 平均每个查询的耗时(评估数据库性能的关键指标)。

  • Total_received / Total_sent: 累计流量统计。

(5)Configuration (配置参数)

含义:列出了 pgbouncer.ini 文件中设置的所有运行参数,以及运行时生效的配置。

关键参数:

  • pool_mode: 运行模式(transaction, session, 或 statement)。

  • max_client_conn: 允许的最大客户端连接数。

  • default_pool_size: 每个连接池默认的后端连接上限。

  • server_idle_timeout: 空闲服务器连接的回收时间。

欢迎交流!!🌹🌹


参考内容:

PgBouncer实战指南:如何优化PostgreSQL连接池性能与稳定性_ss78901-腾讯云开发者社区

相关推荐
雨辰AI3 小时前
SpringBoot3 + 人大金仓读写分离 + 分库分表 + 集群高可用 全栈实战
java·数据库·mysql·政务
长城20243 小时前
关于MySql的ONLY_FULL_GROUP_BY问题
数据库·mysql·聚合列
常常有4 小时前
MySQL 底层执行原理:输入SQL语句到两阶段提交
数据库·sql·mysql
Mr. zhihao4 小时前
深入解析redis基本数据结构
数据结构·数据库·redis
m0_748839494 小时前
利用天正暖通CAD快速掌握风管数量统计的方法
数据库
随身数智备忘录4 小时前
什么是设备管理体系?设备管理体系包含哪些核心模块?
网络·数据库·人工智能
海市公约5 小时前
MySQL更新语句执行全流程:从Buffer Pool修改到二阶段提交
数据库·mysql·binlog·innodb·undo log·二阶段提交·update执行原理
颂love5 小时前
MySQL的执行流程
android·数据库·mysql
程序leo源6 小时前
Qt窗口详解
开发语言·数据库·c++·qt·青少年编程·c#