Odyssey 1.5.1 已正式发布。这个版本面向 PostgreSQL 与 Apache Cloudberry 的高并发连接场景,重点重构了扩展查询协议支持,修复多项协议与实现问题,并改善 pipelining 的整体性能。与此同时,简单共享池、pool_pin_on_listen、事务池负载均衡和 CPU 亲和性等功能,也让连接池在复杂生产负载下更容易调优。
扩展查询协议重构为什么重要
PostgreSQL 客户端不只会发送普通文本 SQL。许多驱动、ORM 和数据库框架默认使用扩展查询协议,把一次查询拆成 Parse、Bind、Describe、Execute 和 Sync 等消息。
连接池工作在 session pooling 模式时,一条客户端连接通常长期绑定同一条后端连接,协议状态相对容易维护。切换到 transaction pooling 后,后端连接会在事务边界重新分配,连接池必须准确跟踪 prepared statement、portal、事务状态和消息顺序。任何状态泄漏,都可能表现为难以复现的协议错误或查询结果异常。
Odyssey 1.5.1 对扩展协议支持进行了重构,并修复了大量相关问题。这类改动的价值不只是“支持更多消息”,而是让代理层在处理 ORM、异步驱动以及连续发送的查询时,能够更可靠地维护前后端协议状态。
升级验证时应重点覆盖以下客户端行为:
- 使用参数绑定的 prepared statement;
- 在一个连接上连续执行多条异步查询;
- 显式事务中的
COMMIT与ROLLBACK; - 查询取消、超时和客户端提前断开;
- transaction pooling 下的会话级状态。
Pipelining 改善了什么
Pipelining 允许客户端在等待前一条响应时继续发送后续请求,从而减少网络往返造成的空闲时间。它尤其适合单条语句执行较快、客户端与数据库之间存在明显网络延迟的工作负载。
连接池处在协议链路中间,因此不仅要快速转发消息,还要维持请求与响应的顺序,并正确处理错误后的同步边界。1.5.1 提升了 pipelining 的整体性能,但实际收益仍取决于 SQL 延迟、网络 RTT、流水线深度和后端数据库是否已经达到 CPU 或 I/O 上限。
可以这样实践:在升级前后使用同一套 pgbench 参数测试 Odyssey 入口。下面的命令可直接运行,执行前把主机、端口、用户和数据库名改成测试环境的值,并确保已经安装 PostgreSQL 客户端工具。
export PGHOST=127.0.0.1
export PGPORT=6432
export PGUSER=benchmark
export PGDATABASE=benchmark
# 仅在独立测试库中初始化数据。
pgbench -i -s 20
# 预热连接池和数据库缓存。
pgbench -S -c 32 -j 8 -T 30 -P 10
# 正式采样:固定连接数、线程数和持续时间,便于版本间比较。
pgbench -S -c 128 -j 16 -T 180 -P 10 | tee pgbench-odyssey-1.5.1.log
不要只比较 TPS。还应记录平均延迟、尾延迟、连接失败数、Odyssey CPU 使用率、后端连接数和 PostgreSQL 等待事件。否则,吞吐量上升可能只是用更高的数据库负载换来的。
事务池中的共享、固定与负载均衡
1.5.1 增加了简单共享池支持,并改进了 transaction pooling 的负载均衡。事务池的核心目标,是让大量客户端连接复用较少的数据库连接;共享能力和更合理的调度可以减少连接热点,提高后端连接的利用率。
pool_pin_on_listen 则处理一个典型边界:PostgreSQL 的 LISTEN/NOTIFY 带有会话语义。执行 LISTEN 后,如果客户端的下一次事务被切换到另一条后端连接,它可能无法按预期收到通知。开启该选项后,可以在检测到 LISTEN 时固定对应连接,避免 transaction pooling 破坏通知状态。
代价也很直接:被固定的连接暂时无法供其他客户端复用。若应用创建大量长期监听者,后端连接数量可能接近客户端监听连接数量,从而削弱事务池的复用效果。因此,通知消费者最好使用独立用户、独立路由或单独的池,并设置明确的连接容量。
下面给出一个可改造的配置示意。由于不同安装包的配置布局可能不同,请以实际构建版本附带的示例配置和配置校验结果为准,确认 pool_pin_on_listen 的作用域后再上线:
# 示意配置:根据现有 odyssey.conf 合并,而不是直接覆盖生产配置。
database "app" {
user "app_user" {
storage "postgres_primary"
pool "transaction"
pool_size 64
pool_timeout 1000
pool_pin_on_listen yes
}
}
可以用两个 psql 终端验证通知行为。终端 A 连接 Odyssey 并监听频道:
psql "host=127.0.0.1 port=6432 dbname=app user=app_user" \
-c "LISTEN deployment_events;" \
-c "SELECT pg_sleep(30);"
在终端 A 保持连接期间,从终端 B 发送通知:
psql "host=127.0.0.1 port=6432 dbname=app user=app_user" \
-c "NOTIFY deployment_events, 'release-2025-01';"
生产验证还应覆盖断线重连、UNLISTEN、监听连接空闲超时以及 Odyssey 重启,因为 LISTEN 状态本身不会跨后端连接或进程重启自动恢复。
CPU 亲和性不是越固定越快
新增的 CPU 亲和性能力允许把 Odyssey 工作线程约束到指定 CPU。对于连接数多、消息短且上下文切换频繁的负载,这可能改善缓存局部性,并减少线程在核心之间迁移。
但 CPU 固定策略需要结合容器限额、NUMA 拓扑和 PostgreSQL 的 CPU 分配来设计。盲目把所有线程压到少数核心,反而会形成队列和尾延迟。可以先检查进程当前可用的 CPU,再做小范围压测:
PID=$(pgrep -xo odyssey)
# 查看线程以及线程当前运行的 CPU。
ps -L -p "$PID" -o pid,tid,psr,pcpu,comm
# 查看操作系统允许该进程使用的 CPU 集合。
taskset -cp "$PID"
# 示例:临时限制到 CPU 2-5,仅用于测试环境验证。
sudo taskset -cp 2-5 "$PID"
临时使用 taskset 只能验证方向。正式部署应通过 Odyssey 自身配置、systemd 的 CPUAffinity=,或 Kubernetes 的 CPU Manager 静态策略实现稳定绑定,避免进程重启后设置丢失。
升级时应守住的边界
1.5.1 同时触及协议处理、连接调度和性能路径,不适合只做“能启动、能查询”的冒烟测试。建议先复制生产流量特征,在预发布环境比较错误率、P95/P99 延迟、池等待时间和后端连接利用率。
采用时可以按这份清单推进:
- 确认客户端驱动是否大量使用扩展查询协议和 prepared statement;
- 分别测试 session pooling 与 transaction pooling,不混用测试结论;
- 为使用
LISTEN/NOTIFY的服务设计独立容量,并验证连接固定行为; - 使用相同数据集、并发度和测试时长比较升级前后结果;
- 逐步启用 CPU 亲和性,观察线程分布和尾延迟,而不是只看平均 CPU;
- 保留旧版本二进制和配置,准备可执行的回滚步骤。
Odyssey 1.5.1 的升级价值集中在协议正确性、流水线效率和事务池调度上。对使用异步驱动、ORM 或大量短事务的系统,这些变化值得验证;但是否能转化为生产收益,仍需通过真实连接模式和数据库瓶颈来判断。