暂无图片
暂无图片
暂无图片
暂无图片
暂无图片

[译文]将 PGBouncer 与 CockroachDB 结合使用

原创 Artem Ervits 2021-07-05
850

PGBouncer是 PostgreSQL 的轻量级连接池。CockroachDB是一个云原生 SQL 数据库,用于构建可在灾难中幸存的全球可扩展云服务。

CockroachDB 是一个 PostgreSQL 线兼容数据库,这意味着它旨在与 PG 生态系统紧密兼容。今天,我们将连接 PGBouncer 与 CockroachDB 一起工作。这篇文章旨在揭示 PGBouncer 与 CockroachDB 畅通无阻的可能性的表面,而不是深入概述。我们目前正在研究这个主题,并将跟进有关 PGBouncer 和 CockroachDB 的正确架构和大小的官方文档。

首先,让我们回顾一下有人会利用连接池的原因。数据库连接成本高昂,在用户身份验证期间,每个连接都会付出代价。当你有很多连接时,它们都会从集群中占用宝贵的内存资源。超过连接限制会导致上下文切换和长时间等待。有几种方法可以解决有限的资源池。在客户端,您有连接池机制,大多数流行语言都支持连接池。现在,如果您正在使用无服务器架构怎么办?无法使用无服务器应用程序定义客户端连接池。更糟糕的是,可能有成百上千的无服务器函数连接到数据库。这就是像 PGBouncer 这样的中间件的用武之地。

CockroachDB 通过增加虚拟 CPU 内核来扩展。内部测试表明,每个 vCPU 有 4 个活动连接是保持服务质量和避免资源匮乏的最佳点。因此,假设我们需要为 100 个并发活动连接调整集群大小。在 CockroachDB 中,SHOW QUERIES命令可以显示有多少活动连接同时执行。我应该提到,CockroachDB 可以支持的空闲连接数没有惩罚或硬性限制。因此,给定 100 个活动连接,我们需要一个由 3 个 8 个 vCPU 节点组成的集群来支持我们 1:4 的 vCPU 与活动连接的比率。现在,如果我们需要支持数千个并发连接,我们将讨论一个非常大的集群。这无论如何都不划算。在这种情况下嵌入 PGBouncer 可以大大减轻 1:4 的比例。然而,我还没有经验数据,需要进一步研究来证明这一点。

我创建了一个示例应用程序,它启动了一个三节点的 CockroachDB 集群、一个负载均衡器 (HAProxy)、一个客户端容器和一个 PGBouncer 的单个实例。最后一部分是关键,您可以通过启动多个 PGBouncer 实例来扩展连接池,并独立于 CockroachDB vCPU 增加连接池。

PGBouncer 需要一些配置文件才能开始。首先是pgbouncer.ini文件。

#pgbouncer.ini

[databases]
* = host = lb port=26257 dbname=tpcc

[pgbouncer]
listen_addr = *
listen_port = 27000
auth_file = /etc/pgbouncer/userlist.txt
auth_type = cert
pool_mode = session
max_client_conn = 500
default_pool_size = 50
min_pool_size = 10
reserve_pool_size = 10
reserve_pool_timeout = 10
max_db_connections = 50
max_user_connections = 50
server_round_robin = 1
ignore_startup_parameters = extra_float_digits
application_name_add_host = 1

# Log settings
log_connections = 1
log_disconnections = 1
log_pooler_errors = 1
verbose = 0
admin_users = root

# Connection sanity checks, timeouts
server_reset_query = false
server_lifetime = 3600

# TLS settings
client_tls_sslmode = verify-full
client_tls_key_file = /home/postgres/node_certs/node.key
client_tls_cert_file = /home/postgres/node_certs/node.crt
client_tls_ca_file = /home/postgres/certs/ca.crt
client_tls_protocols = secure
client_tls_ciphers = secure
server_tls_sslmode = verify-full
server_tls_ca_file = /shared/node/certs/ca.crt
server_tls_key_file = /shared/node/certs/node.key
server_tls_cert_file = /shared/node/certs/node.crt

# Dangerous timeouts
query_wait_timeout = 300

与退回的连接关联的数据库将是tpcc. 我们将lb在端口 26257 上接受来自负载平衡器主机的连接。这有一些优点,因为通过 HAProxy 对 PGBouncer 连接进行负载平衡将防止死节点的连接问题。HAProxy 会解决这个问题。下面的流程图总结了架构。

[databases]
* = host = lb port=26257 dbname=tpcc

图片.png

我正在考虑在多个 PGBouncer 实例前添加负载均衡器是否会消除 PGBouncer 的单点故障,但这是另一天的话题。

更进一步,我们将接受 PGBouncer 端口 27000 上的连接,只是为了使这个概念更容易理解并区分池连接和标准连接。

[pgbouncer]
listen_addr = *
listen_port = 27000

使用 CockroachDB 设置 PGBouncer 的一个特殊问题是安全性。客户端需要对 PGBouncer 进行身份验证,以使用 PGBouncer 发起的证书颁发机构。在 CockroachDB 中,您可以使用cockroach cert create-ca生成 CA 证书。不幸的是,在 PGBouncer 中,您需要使用等效的openssl命令。我们在以下部分记录了步骤。除此之外,PGBouncer 配置了与 PG 类似的 CockroachDB。如果您挂断了电话,请随时检查我用来创建示例应用程序的Dockerfile。

现在回到配置,PGBouncer 工作所需的另一个文件是userlist.txt. 该列表包括所有被授权通过 PGBouncer 访问数据库的用户。这些用户也必须添加到 CockroachDB。

"root" ""
"roach" "roach"

有一种方法可以对密码进行哈希处理,我仍然需要添加该密码,但目前该字段是纯文本格式。

在 CockroachDB 中,添加一个roach将用于通过 PGBouncer 访问数据库的用户可以使用以下命令创建:

CREATE USER IF NOT EXISTS roach WITH PASSWORD 'roach';

最后一步是启动应用程序,因此可以随意访问git clonerepo,导航到cockroach-secure-pgbouncer目录并使用帮助up.sh脚本启动 docker compose 应用程序。

撰写应用程序启动后,我们可以启动工作负载并检查 CockroachDB DBConsole 中的行为。

首先,执行以下命令加载工作负载数据。

docker exec -it client cockroach workload fixtures import tpcc \
 --warehouses=10 'postgresql://roach@pgbouncer:27000/tpcc?sslcert=/shared/client/certs%2Fclient.roach.crt&sslkey=/shared/client/certs%2Fclient.roach.key&sslmode=verify-full&sslrootcert=/shared/client/certs%2Fca.crt'

请注意连接字符串,我们使用的是 user roach,主机名pgbouncer位于 port 27000。我在安装的 volumed 中使用自定义证书/shared。这些证书是使用 PGBouncer CA 生成的。这是使 TLS 与 CockroachDB 和 PGBouncer 一起工作的关键步骤。

一旦工作负载负载完成,我们就可以执行工作负载。

docker exec -it client cockroach workload run tpcc \
--warehouses=10 \
--conns 50 \
--active-warehouses=10 \
--ramp=3m \
--duration=10m \
--workers=100 \
--tolerate-errors \
'postgresql://roach@pgbouncer:27000/tpcc?sslcert=/shared/client/certs%2Fclient.roach.crt&sslkey=/shared/client/certs%2Fclient.roach.key&sslmode=verify-full&sslrootcert=/shared/client/certs%2Fca.crt'

此时,我们可以转到 DBConsole 并检查指标。首先,导航到报表页面并切换App: All下拉菜单以查看所有打开的连接。

图片.png

请注意以 为前缀的大量连接tpcc,这是为了强调连接是通过 PGBouncer 池化的。它通过pgbouncer.iniconfig切换application_name_add_host = 1。不建议在生产中使用它,因为这会使控制台失去数千个连接实例,我仅将其用于演示目的。

下一步是导航到指标页面,特别是 SQL 页面。我们要观察的两个图是 SQL Connections 和 SQL Queries。

图片.png

这些是集群上唯一的活动连接,我们知道它们是通过 PGBouncer 创建的。

最后,让我们查看 PGBouncer 日志,我们可以简单地使用:

docker logs -f pgbouncer

Starting pgbouncer.
2021-05-14 19:46:35.768 UTC [1] LOG kernel file descriptor limit: 1048576 (hard: 1048576); max_client_conn: 500, max expected fd use: 512
2021-05-14 19:46:35.769 UTC [1] LOG listening on 0.0.0.0:27000
2021-05-14 19:46:35.769 UTC [1] LOG listening on [::]:27000
2021-05-14 19:46:35.769 UTC [1] LOG listening on unix:/tmp/.s.PGSQL.27000
2021-05-14 19:46:35.769 UTC [1] LOG process up: PgBouncer 1.15.0, libevent 2.1.8-stable (epoll), adns: c-ares 1.15.0, tls: LibreSSL 2.7.5

一旦我们开始连接,我们将看到许多身份验证尝试

2021-05-14 19:47:50.855 UTC [1] LOG C-0x558a07bf66d0: tpcc/roach@172.23.0.8:43920 login attempt: db=tpcc user=roach tls=TLSv1.2/ECDHE-RSA-AES256-GCM-SHA384
2021-05-14 19:47:50.985 UTC [1] LOG C-0x558a07bf66d0: tpcc/roach@172.23.0.8:43920 closing because: client close request (age=0s)
2021-05-14 19:47:53.392 UTC [1] LOG C-0x558a07bf71c0: tpcc/roach@172.23.0.8:43834 closing because: client unexpected eof (age=16s)
2021-05-14 19:47:53.393 UTC [1] LOG C-0x558a07bf6f90: tpcc/roach@172.23.0.8:43784 closing because: client unexpected eof (age=16s)
2021-05-14 19:48:35.630 UTC [1] LOG stats: 1 xacts/s, 1 queries/s, in 477 B/s, out 257 B/s, xact 917435 us, query 744086 us, wait 19202 us

我们可以看到 PGBouncer 会终止已完成的连接并在以下尝试中重用它们

2021-05-14 19:44:13.167 UTC [1] LOG C-0x55da4e7d94e0: tpcc/roach@172.22.0.8:50112 login attempt: db=tpcc user=roach tls=TLSv1.2/ECDHE-RSA-AES256-GCM-SHA384
2021-05-14 19:44:13.167 UTC [1] LOG C-0x55da4e7d8c20: tpcc/roach@172.22.0.8:50110 login attempt: db=tpcc user=roach tls=TLSv1.2/ECDHE-RSA-AES256-GCM-SHA384
2021-05-14 19:44:13.373 UTC [1] LOG C-0x55da4e7d9940: tpcc/roach@172.22.0.8:50278 login attempt: db=tpcc user=roach tls=TLSv1.2/ECDHE-RSA-AES256-GCM-SHA384
2021-05-14 19:44:14.697 UTC [1] LOG C-0
...
2021-05-14 19:49:06.421 UTC [1] LOG S-0x558a07c5ec60: tpcc/roach@172.23.0.6:26257 SSL established: TLSv1.2/ECDHE-RSA-AES128-GCM-SHA256/ECDH=X25519
2021-05-14 19:49:06.438 UTC [1] LOG S-0x558a07c5ee90: tpcc/roach@172.23.0.6:26257 new connection to server (from 172.23.0.7:48364)
2021-05-14 19:49:06.446 UTC [1] LOG S-0x558a07c5ee90: tpcc/roach@172.23.0.6:26257 SSL established: TLSv1.2/ECDHE-RSA-AES128-GCM-SHA256/ECDH=X25519
2021-05-14 19:49:06.456 UTC [1] LOG S-0x558a07c5f0c0: tpcc/roach@172.23.0.6:26257 new connection to server (from 172.23.0.7:48368)
2021-05-14 19:49:06.464 UTC [1] LOG S-0x558a07c5f0c0: tpcc/roach@172.23.0.6:26257 SSL established: TLSv1.2/ECDHE-RSA-AES128-GCM-SHA256/ECDH=X25519

我们可以观察到tpcc用户roach使用 TLS对数据库进行了登录尝试。PGBouncer 创建一个任意端口,在该端口上创建反弹连接。

我应该提到的最后一件事是 PGBouncer 在三种不同的池模式下运行。到目前为止,我只能评估session模式。准备好的语句在这种模式下不起作用,这将可用性限制为仅显式查询。也就是说,如果您想创建一个可以使用数据库的用户池,而不需要从集群中获取宝贵的资源,至少用于身份验证,PGBouncer 是一个可行的选择。

文章来源:https://dzone.com/articles/using-pgbouncer-with-cockroachdb

「喜欢这篇文章,您的关注和赞赏是给作者最好的鼓励」
关注作者
【版权声明】本文为墨天轮用户原创内容,转载时必须标注文章的来源(墨天轮),文章链接,文章作者等基本信息,否则作者和墨天轮有权追究责任。如果您发现墨天轮中有涉嫌抄袭或者侵权的内容,欢迎发送邮件至:contact@modb.pro进行举报,并提供相关证据,一经查实,墨天轮将立刻删除相关内容。

评论