在 Cloud Run 中,如何设置 SQL 连接池大小以避免“too many connections”?

解读

面试官真正想考察的是:

  1. 你是否理解 Cloud Run 实例的并发模型(单实例可并发 1~1000 请求,且实例数可秒级横向伸缩)。
  2. 你是否能把 Cloud SQL 的 max_connections 上限(与 CPU 核数挂钩,国内常见 MySQL 2 vCPU 仅约 500 个)与 Cloud Run 的弹性伸缩结合起来做 容量估算
  3. 你是否能在代码层、代理层、数据库层 闭环治理连接池,而不是只改一行配置。
  4. 你是否熟悉 国内云原生合规场景(如金融客户要求私网访问、Terraform 必须落库审计)下的落地细节。

一句话:不是简单“调小 pool size”,而是让 “池大小 × 最大实例数” ≤ “数据库安全余量”,并具备 动态逃生机制

知识点

  1. Cloud SQL 连接上限

    • MySQL:≈ 1000 × vCPU 数(国内 4 vCPU 默认 ≈ 4000,但系统保留 10%,实际 3600)。
    • PostgreSQL:受 max_connections 参数控制,默认 100,可改到 6000,但内存线性增加。
    • SQL Server:受 USER_CONNECTIONS实例规格 共同限制,国内 8 vCPU 约 6000。
  2. Cloud Run 并发模型

    • 单实例并发度 concurrency(默认 80,最大 1000)。
    • 冷启动时 minInstances=0 场景下,突发流量可瞬间拉起 N 个实例,连接数 = pool_size × N
  3. 连接池四大参数

    • initialSize / minIdle:预热连接,建议 0 或 1,避免冷启动浪费。
    • maxPoolSize:核心考点,必须 ≤ max_connections × 安全比例 / 最大可能实例数
    • idleTimeout / maxLifetime:国内金融监管要求 ≤ 5 min,防止长连接被防火墙掐掉。
    • connectionTimeout:Cloud Run 请求超时上限 60 min,但池等待建议 ≤ 5 s,快速失败转熔断。
  4. 国内网络环境

    • Private Service Connect + VPC-SC 必须走 RFC 1918 私网,Cloud SQL Auth Proxy sidecar 模式需加 -ip_address_types=PRIVATE
    • 北京/上海双可用区合规客户,常把 Cloud SQL 实例放在 VPC 对等只读地域,此时 RTT 增加 3 ms,池超时需 +1 s 缓冲。
  5. 观测与治理

    • Cloud Monitoring 指标:cloudsql.googleapis.com/database/mysql/connections、cloudsql.googleapis.com/database/postgresql/num_backends。
    • Cloud Run 自定义指标:通过 OpenTelemetry 暴露 pool_active_connections,对接 阿里云 Grafana 托管版(国内多云战略常见)。
    • Terraform 代码审计:必须显式写出 max_connections = var.db_max_conn,并在 MR 阶段触发 Policy Validator 规则,防止实习生一键改大。

答案

分五步闭环落地:

  1. 先算 数据库安全余量
    以国内 4 vCPU MySQL 为例,max_connections ≈ 3600,取 50% 作为安全水位 = 1800

  2. 再算 Cloud Run 最大实例数
    业务峰值 QPS ÷ (concurrency ÷ avg_latency) = 10000 ÷ (80 ÷ 0.1) ≈ 125 实例

  3. 推导 单实例池上限
    maxPoolSize ≤ 1800 ÷ 125 = 14.4 → 取整 10(留 30% 缓冲给后台运维、健康检查)。

  4. 代码层配置(Spring Boot 2.7 + HikariCP 示例,国内用得最多)

    spring.datasource.hikari.minimum-idle=0
    spring.datasource.hikari.maximum-pool-size=10
    spring.datasource.hikari.idle-timeout=300000
    spring.datasource.hikari.max-lifetime=300000
    spring.datasource.hikari.connection-timeout=5000
    

    同时把 spring.datasource.hikari.leak-detection-threshold=60000,对接 Sentry 国内版,慢连接 1 min 即报警。

  5. 代理层兜底
    Cloud SQL Auth Proxy 1.33+ 支持 -max-connections 参数,强制代理侧限流 12 个连接,即使代码 bug 调大池,代理也会返回 “too many connections” 本地错误,不会打到数据库。

最后把五步写进 Terraform 模块变量

variable "cloud_run_max_instances" { default = 125 }
variable "db_max_conn" { default = 3600 }
locals {
  safe_pool_size = floor(var.db_max_conn * 0.5 / var.cloud_run_max_instances)
}

MR 阶段 Policy Validator 规则强制 local.safe_pool_size ≤ 15,否则拒绝合并,国内金融客户审计直接通过

拓展思考

  1. 如果业务突然做 直播秒杀,需要 minInstances=500 预热,如何不改代码就保证安全?
    答案:利用 Cloud SQL 的 Connection Pooler (PgBouncer) 开启 transaction pool 模式,把 max_client_conn 调到 5000default_pool_size=20,让 Pooler 实例承担连接聚合,数据库真实连接仅 200,代码层池大小保持 10 不变

  2. 国内 跨云灾备场景,阿里云 RDS 作为只读,Cloud Run 通过 Private Service Connect + VPN 访问,RTT 从 2 ms 升到 35 ms,池参数如何调?
    答案:

    • connectionTimeout 升到 10 s
    • idleTimeout 降到 120 s,防止防火墙 NAT 表老化
    • maxLifetime 降到 240 s,并开启 testOnBorrow=true + 轻量级 SELECT 1
  3. 面试官可能追问 “如果连接池已经 5 但还是被打爆”,如何 1 分钟止血?
    答案:

    • Cloud Run Traffic Split 立即把 100% 流量切到保留版本(版本号带 -safe 后缀,池大小=1)。
    • Cloud SQL 控制台一键重启(释放全部连接),重启耗时 30 s。
    • Terraform 临时把 max_instances 改成 10,合并后 30 s 生效。
      全程 SLO 降级但不断服,国内电商大促常用此 “三板斧” 应急。