这篇文章是关于我最近遇到的一个新的 PostgreSQL 连接池:pgcat,它提供了一些我没有在其他池中看到的有用特性。请注意pgcat连接池处于测试阶段,他们实际上正在寻找测试人员!如果您有兴趣,请阅读pgcat beta 测试公告(https://github.com/levkk/pgcat/issues/35)。
pgcat是一个类似于pgbouncer的连接池,并且共享它工作的部分逻辑方式,但它有一个根本的区别:它允许为单个客户端连接使用多个数据库。pgbouncer只会将客户端连接到单个数据库。应该提到的是,有一种方法可以通过使用pgbouncer so_reuseport 设置来执行负载平衡,以允许多个 pgbouncer 在同一端口上运行。
pgcat似乎非常关注它的分片功能,它允许连接池将查询传播到分片。如果您想使用分片功能,它会执行非常漂亮的事情,例如解释 SQL 以将查询路由到正确的分片。
我的兴趣是因为分布式YugabyteDB数据库。这个 pooler 允许在服务器列表中定义 YugabyteDB 集群的 PostgreSQL 端点(具有“主”/“副本”角色,我不喜欢,因为我们在YugabyteDB中没有这些),然后让传入连接在服务器上保持平衡。当pgcat检测到一个数据库连接已死时,它将与池中的下一个可用连接重新连接!
当然像这样的外部连接池只有在你不能使用应用程序连接池的情况下才应该使用,而对于YugabyteDB的使用,如果你可以使用YugabyteDB驱动程序,比如我们的java jdbc驱动程序,强烈建议这样做!
安装
pgcat的安装并不难,并且在 pgcat 页面上有很好的描述。目前,由于pgcat处于测试阶段,您必须自己构建可执行文件,或使用示例 Docker 部署。
自己构建它非常简单,因为您需要做的就是安装Rust、 git clone pgcat,然后使用以下命令构建它:cargo build --release。
配置使用YugabyteDB
配置其实很简单。请参阅此配置以用于我的小型测试集群:
[general]
prometheus_exporter_port = 9930
admin_username = "admin_user"
admin_password = "admin_pass"
[pools.yugabyte]
pool_mode = "session"
default_role = "any"
query_parser_enabled = false
primary_reads_enabled = true
sharding_function = "pg_bigint_hash"
[pools.yugabyte.users.0]
username = "yugabyte"
password = "yugabyte"
pool_size = 50
statement_timeout = 0
[pools.yugabyte.shards.0]
servers = [
[ "192.168.66.80", 5433, "primary" ],
[ "192.168.66.81", 5433, "replica" ],
[ "192.168.66.82", 5433, "replica" ]
]
database = "yugabyte"
这些是当前版本所需的最少设置。
我创建了一个名为“yugabyte”(pools.yugabyte) 的池,池模式为“会话”,以便会话保持与后端的连接。
我在 pools.yugabyte.shards.0(yugabyte 分片池 0)中创建了一个服务器池,其中包含YugabyteDB集群中的所有三个 YSQL 节点,并赋予其中一个角色“主要”,另外两个角色“复制品”。对于YugabyteDB YSQL 这没有意义。目前,pgcat允许所有角色都是“副本”,但不能有超过一个“主要”角色。
运行pgcat
现在配置已经完成,使用cargo运行pgcat:
RUST_LOG=info cargo run --release
Finished release [optimized] target(s) in 0.11s
Running `target/release/pgcat`
[2022-11-14T13:24:03.175058Z INFO pgcat] Welcome to PgCat! Meow. (Version 0.6.0-alpha1)
[2022-11-14T13:24:03.184314Z INFO pgcat] Running on 0.0.0.0:5432
[2022-11-14T13:24:03.184323Z INFO pgcat::config] Ban time: 60s
[2022-11-14T13:24:03.184325Z INFO pgcat::config] Healthcheck timeout: 1000ms
[2022-11-14T13:24:03.184328Z INFO pgcat::config] Connection timeout: 1000ms
[2022-11-14T13:24:03.184329Z INFO pgcat::config] Shutdown timeout: 60000ms
[2022-11-14T13:24:03.184331Z INFO pgcat::config] Healthcheck delay: 30000ms
[2022-11-14T13:24:03.184333Z INFO pgcat::config] TLS support is disabled
[2022-11-14T13:24:03.184337Z INFO pgcat::config] [pool: yugabyte] Maximum user connections: 50
[2022-11-14T13:24:03.184342Z INFO pgcat::config] [pool: yugabyte] Pool mode: Session
[2022-11-14T13:24:03.184367Z INFO pgcat::config] [pool: yugabyte] Connection timeout: 1000ms
[2022-11-14T13:24:03.184370Z INFO pgcat::config] [pool: yugabyte] Sharding function: pg_bigint_hash
[2022-11-14T13:24:03.184372Z INFO pgcat::config] [pool: yugabyte] Primary reads: true
[2022-11-14T13:24:03.184374Z INFO pgcat::config] [pool: yugabyte] Query router: false
[2022-11-14T13:24:03.184376Z INFO pgcat::config] [pool: yugabyte] Number of shards: 1
[2022-11-14T13:24:03.184378Z INFO pgcat::config] [pool: yugabyte] Number of users: 1
[2022-11-14T13:24:03.184380Z INFO pgcat::config] [pool: yugabyte][user: yugabyte] Pool size: 50
[2022-11-14T13:24:03.184456Z INFO pgcat::config] [pool: yugabyte][user: yugabyte] Statement timeout: 0
[2022-11-14T13:24:03.185020Z INFO pgcat::pool] [pool: yugabyte][user: yugabyte] creating new pool
[2022-11-14T13:24:03.185099Z INFO pgcat::pool] Creating a new server connection Address { id: 0, host: "192.168.66.80", port: 5433, shard: 0, database: "yugabyte", role: Primary, replica_number: 0, address_index: 0, username: "yugabyte", pool_name: "yugabyte" }
[2022-11-14T13:24:03.196798Z INFO pgcat::pool] Creating a new server connection Address { id: 1, host: "192.168.66.81", port: 5433, shard: 0, database: "yugabyte", role: Replica, replica_number: 0, address_index: 1, username: "yugabyte", pool_name: "yugabyte" }
[2022-11-14T13:24:03.209956Z INFO pgcat::pool] Creating a new server connection Address { id: 2, host: "192.168.66.82", port: 5433, shard: 0, database: "yugabyte", role: Replica, replica_number: 1, address_index: 2, username: "yugabyte", pool_name: "yugabyte" }
[2022-11-14T13:24:03.222501Z INFO pgcat] Config autoreloader: false
[2022-11-14T13:24:03.222540Z INFO pgcat::stats] Events reporter started
[2022-11-14T13:24:03.222556Z INFO pgcat] Waiting for clients
上面的日志记录是因为 RUST_LOG=info 在同一行的设置cargo run --release。
请注意,默认设置绑定到所有网络接口上的端口 5432,这可能与本地运行的PostgreSQL数据库冲突。可以使用port = 6432(使用默认pgbouncer端口的示例)设置端口。还要注意YugabyteDB默认绑定到端口 5433。
通过pgcat 使用YugabyteDB进行负载平衡连接
现在pgcat已设置并运行,我们可以使用pgcat连接到YugabyteDB集群,并在连接后获得持久连接:
psql -h localhost -p 5432 -U yugabyte
psql (14.5 (Homebrew), server 11.2-YB-2.15.3.2-b0)
Type "help" for help.
yugabyte=# select inet_server_addr();
inet_server_addr
------------------
192.168.66.81
结论
pgcat项目看起来是一个非常有前途的项目,因为它允许使用具有 pgbouncer 简单性的连接池,但在YugabyteDB YSQL 端点集群上具有连接分布。
另一个优点是它使用Rust,它提供 C/C++ 速度和内存安全。
但是,必须注意该项目处于早期阶段,因此在考虑将其用于生产环境之前应该对其进行很好的测试。
附言。
我已经发现了一个问题:如果没有指定 dbname,pgcat 返回一个错误,而与 YSQL (=PostgreSQL) 的相同连接成功,因为如果没有指定 dbname,它应该使用用户名。
原文标题:pgcat: a PostgreSQL pooler
原文作者:Frits Hoogland
原文链接:https://dev.to/yugabyte/pgcat-a-postgresql-pooler-3a24




