我正在尝试扩展我的基础设施。
有一个使用持久连接的 Php 7.4 应用程序。
有一个应用程序使用默认参数连接到的 PgBouncer。
/pgbouncer.ini
[databases]
XXXXXXX
[pgbouncer]
listen_addr = 0.0.0.0
listen_port = 4040
unix_socket_dir =
user = postgres
auth_file = /etc/pgbouncer/userlist.txt
auth_type = md5
ignore_startup_parameters = extra_float_digits
logfile = /var/log/pgbouncer/pgbouncer.log
# Log settings
admin_users = postgres
以及云环境中的标准 PostgreSQL。
我面临一个奇怪的问题,当我用 50 个用户对应用程序进行负载测试时(我目前正在开发环境中的小型服务器上进行测试)很多人都面临这个错误:
pg_query(): Query failed: ERROR: query_wait_timeout server closed the connection unexpectedly
事实上,当我在 PgBouncer 中使用
SHOW POOLS
时,它显示的是:
database | user | cl_active | cl_waiting | sv_active | sv_idle | sv_used | sv_tested | sv_login | maxwait | maxwait_us | pool_mode
----------------------+----------------------+-----------+------------+-----------+---------+---------+-----------+----------+---------+------------+-----------
XXXXXXXXXXXXXXXXXXXX | XXXXXXXXXXXXXXXXXXXX | 20 | 31 | 20 | 0 | 0 | 0 | 0 | 120 | 106966 | session
pgbouncer | pgbouncer | 1 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | statement
这解释了错误,因为有太多等待的客户。但有趣的是,我在同一时间(事实上是多次)在目标 PostgreSQL 上运行了以下查询:
SELECT *
FROM pg_stat_activity
ORDER BY pid desc;
我看到的是一堆空闲的客户端,有时其中一个/两个/三个显示为活跃的处理查询......!我希望所有 20 个客户都能为所有等待的 PgBouncer 客户提供服务..
(空闲的在激活之前保持空闲 10 到 20 秒)
此外,重要的是要提到所有服务器都处于 30% CPU 和 20% RAM,所以,这似乎(?)这不是资源问题。
有什么问题吗?我觉得有些不正常。
问题已解决,看来 php 的持久连接不能很好地与 PgBouncer 配合使用。只需关闭持久连接,一切都会顺利进行。 :)
问题是会话pooling模式。 如果是transaction或statement,它不会有问题。
如果会话模式打开,每个新的客户端连接到 pgbouncer 都需要它自己的从 pgbouncer 到数据库的连接。 持久连接是持久连接,所以如果有 50 个 php-fpm worker,并且每个 worker 都持久连接到 pgbouncer,那么一直会有 50 个连接的客户端。
当连接的客户端超过会话模式池中最大可能的服务器连接时,一切都会卡住。
您需要增加服务器连接池或切换到事务/语句模式。 就个人而言,我建议打开持久性,因为它减少了应用程序到数据库的连接时间。