← 中文资源

简体中文版本

用舱壁池隔离下游依赖

为每个下游依赖分配独立且有上限的连接或并发池,避免单个慢服务占满共享槽位并拖垮其他请求。

阅读英文原文

概述

所有依赖共用一个大连接池会把故障耦合在一起。报表查询变慢时会持续占用连接,直到池被耗尽,健康的支付请求只能排在后面等待。舱壁模式为每个依赖分配固定容量和有限等待时间,某个分区饱和时调用方快速失败或降级,而不是拖垮整个进程。

步骤

  1. 为每个依赖建立独立连接池,显式设置最大连接数和等待超时:
export const paymentsPool = new pg.Pool({
  connectionString: process.env.PAYMENTS_DATABASE_URL,
  max: 8,
  connectionTimeoutMillis: 500,
});

export const reportsPool = new pg.Pool({
  connectionString: process.env.REPORTS_DATABASE_URL,
  max: 4,
  connectionTimeoutMillis: 500,
});
  1. 导出每个池的 total、idle、waiting 指标,waiting 持续大于 0 超过一分钟即告警。
  2. 用 toxiproxy-cli toxic add reports-db -t latency -a latency=2000 只给报表库注入延迟,再跑混合流量。
  3. 观察支付接口 p95 是否保持不变;若也上升,说明仍有共享的池、HTTP agent 或线程池未隔离。

验证

预期报表请求在 500 毫秒后快速失败或明显变慢,而支付请求延迟曲线平稳。仪表盘上两个池的饱和度应独立变化,日志中能看到池名称,便于定位是哪一个依赖饱和。

注意事项

  • 所有池的 max 之和必须低于数据库 max_connections 的 80%,给管理会话留余量。
  • 连接必须在 finally 中释放,或使用统一的事务封装,否则池会被缓慢泄漏耗尽。
  • 舱壁只改变失败范围,不增加容量;持续饱和应扩容或优化查询。
  • 静态切分在流量结构变化时可能浪费容量,需按季度复核池大小。