Skip to content

配置RDS Proxy

  • 难度等级: 中级
  • 预计时长: 1-2 小时
  • 适用场景: 高连接数应用、Serverless 架构、频繁连接应用
  • 支持引擎: Aurora MySQL/PostgreSQL, RDS MySQL/PostgreSQL/MariaDB/SQL Server

通过部署 Amazon RDS Proxy 实现数据库连接池管理,降低数据库负载,缩短故障转移时间,并提升应用可用性。


在开始配置前,需满足以下条件:

  • RDS 数据库实例或 Aurora 集群已创建
  • VPC 中至少有 2 个私有子网
  • 数据库安全组已配置
  • 具有创建 RDS Proxy 的权限
  • 具有创建 Secrets Manager 密钥的权限
  • 具有创建 IAM 角色的权限
  • 数据库引擎为支持的版本
  • 数据库必须在 VPC 内(不支持 EC2-Classic)
  • 数据库不能是 RDS Custom for SQL Server

通俗类比:RDS Proxy 就像酒店前台接待员。客人(应用)不直接去找房间(数据库),而是先到前台(Proxy)登记。前台统一管理房间分配、钥匙(连接)复用,避免每位客人都要求新房间,从而提升酒店(数据库)的运营效率。

技术定义:RDS Proxy 是 AWS 托管的数据库代理服务,位于应用和数据库之间,通过连接池管理、连接复用和智能路由,优化数据库连接使用效率。

graph TB
    A[应用层<br/>100个应用连接] --> B[RDS Proxy<br/>连接池]
    B --> C[数据库层<br/>10个实际连接]
    
    B --> D[连接复用]
    B --> E[故障转移]
    B --> F[IAM认证]
    
    style A fill:#e1f5ff
    style B fill:#fff4e1
    style C fill:#e1ffe1

核心机制

  • 连接池:Proxy 维护一个到数据库的连接池,多个应用连接共享少量数据库连接
  • 连接复用:应用关闭连接后,Proxy 保持数据库连接活跃并分配给新请求
  • 智能路由:故障时自动切换到备用实例,保持应用连接不中断

强烈推荐使用

  1. Serverless 应用(Lambda 函数)

    • 问题:Lambda 并发执行时产生大量短生命周期连接
    • 解决:Proxy 的连接池避免数据库连接数耗尽
  2. 高频连接应用

    • 问题:PHP、Ruby on Rails 等框架频繁打开/关闭连接
    • 解决:连接复用减少数据库 CPU 和内存开销
  3. 突发流量应用

    • 问题:电商促销、SaaS 应用流量激增导致连接数超限
    • 解决:连接池管控和限流保护数据库
  4. 长连接空闲应用

    • 问题:保持大量空闲连接占用数据库资源
    • 解决:Proxy 管理空闲连接,释放数据库资源

可选使用

  • 需要集中管理数据库凭证
  • 需要强制 IAM 认证
  • 需要缩短故障转移时间(减少 66%)

不适合使用

  • 应用已有成熟的连接池管理
  • 连接数始终保持较低水平(< 20)
  • 使用不支持的数据库引擎或特性

通过 CloudWatch 监控判断:

指标阈值说明
DatabaseConnections接近 max_connections 的 80%连接数压力大
ConnectionAttempts高频率频繁建立新连接
CPU 利用率> 70%可能由连接开销导致
T2/T3 实例内存频繁接近上限小实例连接开销大

RDS Proxy 通过 Secrets Manager 安全存储和获取数据库凭证,实现:

  • 凭证集中管理
  • 自动轮换密码
  • 加密存储
  • IAM 权限控制

控制台操作

  1. 打开 AWS Secrets Manager 控制台
  2. 选择”存储新的密钥”
  3. 密钥类型:选择”RDS 数据库的凭证”
  4. 配置参数:
    用户名: 数据库管理员用户(如 admin)
    密码: 数据库密码
    加密密钥: 使用默认 KMS 密钥或自定义
    选择数据库: 选择目标 RDS 实例或 Aurora 集群
  5. 密钥名称:rds-proxy-secret-{database-name}
  6. 轮换配置:建议启用自动轮换(可选)

最佳实践

  • 为每个数据库用户创建独立密钥
  • 对于多租户应用,可创建最多 200 个密钥(Proxy 限制)
  • 密钥名称使用清晰命名规范

[创建Secrets Manager密钥]


RDS Proxy 需要 IAM 角色来访问 Secrets Manager:

信任策略

{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Principal": {
"Service": "rds.amazonaws.com"
},
"Action": "sts:AssumeRole"
}
]
}

权限策略

{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": [
"secretsmanager:GetSecretValue"
],
"Resource": "arn:aws:secretsmanager:region:account-id:secret:secret-name"
},
{
"Effect": "Allow",
"Action": [
"kms:Decrypt"
],
"Resource": "arn:aws:kms:region:account-id:key/key-id",
"Condition": {
"StringEquals": {
"kms:ViaService": "secretsmanager.region.amazonaws.com"
}
}
}
]
}

角色命名建议rds-proxy-role-{database-name}

[创建IAM角色]


控制台路径:RDS 控制台 → Proxies → Create proxy

必填参数

代理标识符: my-rds-proxy
引擎系列: 选择数据库引擎(MySQL/PostgreSQL)
目标数据库: 选择 RDS 实例或 Aurora 集群

VPC 和子网

  • VPC:必须与数据库在同一 VPC
  • 子网:选择至少 2 个不同可用区的私有子网
  • 最佳实践:选择与数据库相同的子网组

安全组

  • 创建新安全组或选择现有
  • 入站规则:允许应用安全组访问(端口 3306/5432)
  • 出站规则:允许访问数据库安全组(端口 3306/5432)

IAM 角色:选择步骤 3 创建的角色

密钥配置

  • 添加步骤 2 创建的 Secrets Manager 密钥
  • 可添加多个密钥支持不同数据库用户
  • IAM 身份验证:可选启用(推荐用于 Lambda)

关键参数

参数推荐值说明
最大连接百分比75%占数据库 max_connections 的百分比
最大空闲连接百分比50%保持活跃的最小连接数
连接借用超时120 秒等待可用连接的最长时间
空闲客户端连接超时1800 秒应用空闲连接关闭时间

为什么这样配置

  • 75% 最大连接:为直接连接和运维操作预留 25% 容量
  • 1800 秒超时:平衡资源释放和连接复用效率

Session Pinning Filters:某些数据库操作会导致连接”固定”到特定实例,降低连接池效率。

推荐配置:保持默认(None),除非遇到以下场景:

  • EXCLUDE_VARIABLE_SETS:排除设置会话变量的操作
  • 使用临时表、预处理语句时需评估影响

最佳实践:初期不配置过滤器,通过 CloudWatch 监控 DatabaseConnectionsCurrentlySessionPinned 指标,如持续偏高再调整。

[创建RDS Proxy配置]


关键认知:RDS Proxy 默认端点不会自动区分读写请求,所有流量都路由到写入实例。要实现读写分离,必须手动配置。

端点类型路由目标用途
默认端点(Read/Write)写入实例所有读写操作
只读端点(Read-Only)只读副本仅查询操作

重要说明:Proxy 不会分析 SQL 语句类型(SELECT/INSERT),需要应用层区分读写请求。

前提条件

  • Aurora 集群至少有 1 个 Reader 实例,或
  • RDS Multi-AZ 集群至少有 1 个 Reader 实例

创建步骤

  1. 进入 Proxy 详情页
  2. Proxy endpoints → Create endpoint
  3. 配置参数:
    端点名称: my-rds-proxy-readonly
    目标角色: Read-only
    VPC: 与 Proxy 相同
  4. 记录端点地址:my-rds-proxy-readonly.proxy-xxx.region.rds.amazonaws.com

[创建只读端点]

方案 1:使用双连接池(推荐)

# Python 示例
from sqlalchemy import create_engine
# 写连接 - 连接到默认端点
write_engine = create_engine(
'mysql://user:pass@my-rds-proxy.proxy-xxx.region.rds.amazonaws.com:3306/db'
)
# 读连接 - 连接到只读端点
read_engine = create_engine(
'mysql://user:pass@my-rds-proxy-readonly.proxy-xxx.region.rds.amazonaws.com:3306/db'
)
# 应用中区分使用
def create_order(data):
with write_engine.connect() as conn:
conn.execute("INSERT INTO orders VALUES (...)")
def get_order(order_id):
with read_engine.connect() as conn:
return conn.execute("SELECT * FROM orders WHERE id = ?", order_id)

方案 2:使用 ORM 的读写分离功能

Spring Boot 示例:

@Transactional(readOnly = false) // 使用写端点
public void createOrder(Order order) {
orderRepository.save(order);
}
@Transactional(readOnly = true) // 使用读端点
public Order getOrder(Long id) {
return orderRepository.findById(id);
}

方案 3:使用第三方代理(不推荐)

对于需要自动 SQL 分析的场景,可使用:

  • ProxySQL(开源,需自行部署和维护)
  • Heimdall Proxy(第三方商业产品)

为什么不推荐:增加额外组件复杂度、维护成本和故障点。应用层读写分离更清晰可控。

连接字符串管理

环境变量方式:
DB_WRITE_HOST=my-rds-proxy.proxy-xxx.region.rds.amazonaws.com
DB_READ_HOST=my-rds-proxy-readonly.proxy-xxx.region.rds.amazonaws.com
DB_PORT=3306
DB_NAME=mydb

连接池配置建议

写连接池:
- 最小连接数: 5
- 最大连接数: 20
- 连接超时: 30s
读连接池:
- 最小连接数: 10
- 最大连接数: 50
- 连接超时: 30s

为什么读连接池更大:通常读操作占 70-80%,需更多连接满足查询需求。


从直连数据库改为通过 Proxy

原连接字符串:
mysql://user:pass@mydb.xxx.region.rds.amazonaws.com:3306/database
新连接字符串(写操作):
mysql://user:pass@my-rds-proxy.proxy-xxx.region.rds.amazonaws.com:3306/database
新连接字符串(读操作):
mysql://user:pass@my-rds-proxy-readonly.proxy-xxx.region.rds.amazonaws.com:3306/database

使用 IAM 认证(推荐)

import boto3
import pymysql
def get_db_connection():
client = boto3.client('rds')
token = client.generate_db_auth_token(
DBHostname='my-rds-proxy.proxy-xxx.region.rds.amazonaws.com',
Port=3306,
DBUsername='iam_user'
)
connection = pymysql.connect(
host='my-rds-proxy.proxy-xxx.region.rds.amazonaws.com',
user='iam_user',
password=token,
database='mydb',
ssl={'ca': '/path/to/rds-ca-bundle.pem'}
)
return connection

为什么使用 IAM 认证

  • 无需在代码中存储密码
  • 自动令牌轮换(15 分钟有效期)
  • 使用 Lambda 执行角色权限

Lambda 函数必须配置

  • VPC:与 Proxy 相同的 VPC
  • 子网:私有子网
  • 安全组:允许访问 Proxy 安全组

[更新应用连接配置]


CloudWatch 指标

指标正常范围异常处理
DatabaseConnections< 最大连接数的 75%增加 Reader 实例
DatabaseConnectionsCurrentlyBorrowed-活跃连接数,用于容量规划
DatabaseConnectionsCurrentlySessionPinned< 10%优化应用代码减少固定
ClientConnections-应用端连接总数
QueryDatabaseResponseLatency< 50ms数据库性能问题

告警配置建议

DatabaseConnectionsCurrentlySessionPinned > 20%:
问题:连接池效率低
原因:频繁使用临时表、预处理语句、SET 变量
解决:优化应用代码或配置会话固定过滤器
ClientConnections 突增:
问题:应用突发流量
解决:检查 Proxy 是否正常限流保护数据库

评估连接池配置是否合理

  1. 观察 DatabaseConnections 是否接近配置的最大值
  2. 观察 ClientConnectionsDatabaseConnections 的比例
  3. 理想比例:10:1 到 20:1(取决于应用特性)

调整建议

场景 1:DatabaseConnections 经常达到上限
→ 增加最大连接百分比(75% → 85%)
→ 或增加 Reader 实例
场景 2:ClientConnections 很高但 DatabaseConnections 很低
→ 说明连接池工作良好,无需调整
场景 3:SessionPinned 比例高
→ 应用代码优化或启用会话固定过滤器

Proxy 计费方式:按数据库实例的 vCPU 小时计费

成本示例

db.r5.large(2 vCPU):
Proxy 费用 ≈ $0.015/vCPU/小时 × 2 × 730小时 = $21.9/月
db.r5.xlarge(4 vCPU):
Proxy 费用 ≈ $0.015/vCPU/小时 × 4 × 730小时 = $43.8/月

优化建议

  • 仅对需要连接池的数据库启用 Proxy
  • 开发测试环境可不启用
  • 评估 Proxy 带来的成本节约(减少数据库规格、避免连接数扩容)

[监控仪表板配置]


1. 连接池管理(核心价值)

  • 减少数据库连接开销(CPU、内存)
  • 允许应用打开数千连接但数据库只维护数百连接
  • 小实例(T2/T3)受益最大

2. 提升可用性

  • 故障转移时间缩短 66%(从 60 秒降至 20 秒)
  • 应用连接在故障转移期间保持,无需重连
  • Multi-AZ 部署确保 Proxy 自身高可用

3. 增强安全性

  • 集中管理数据库凭证(Secrets Manager)
  • 强制 IAM 认证
  • TLS 1.3 加密(即使数据库仅支持旧版本)

4. 无需修改应用代码

  • 仅更改连接字符串
  • 与数据库协议完全兼容

1. 不支持的功能

  • 不支持 RDS Custom for SQL Server
  • 不支持公开访问(必须在 VPC 内)
  • MySQL:不支持某些认证插件
  • PostgreSQL:不支持取消查询(Ctrl+C)

2. 配额限制

  • 每账号默认 20 个 Proxy(可申请增加)
  • 每个 Proxy 最多 200 个 Secrets Manager 密钥
  • 每个 Proxy 最多 20 个端点

3. 会话固定问题

  • 使用临时表、预处理语句、SET 变量会导致连接固定
  • 固定期间连接无法被其他请求复用
  • 影响连接池效率

4. 不支持某些数据库特性

  • SQL Server:不支持 Active Directory 认证
  • MySQL:@@IDENTITY@@ROWCOUNT 可能不准确
  • PostgreSQL:默认 postgres 数据库不能删除

最佳实践决策树

是否使用 Lambda 或容器化应用?
├─ 是 → 强烈推荐使用 Proxy
└─ 否 → 继续判断
应用是否频繁打开/关闭连接?
├─ 是(如 PHP/Ruby on Rails)→ 推荐使用
└─ 否 → 继续判断
数据库连接数是否接近上限?
├─ 是 → 推荐使用
└─ 否 → 可选
是否需要缩短故障转移时间?
├─ 是 → 推荐使用
└─ 否 → 评估成本后决定

推荐方案排序

  1. 应用层双连接池(首选)

    • 优点:逻辑清晰、可控性强、易于调试
    • 缺点:需要少量代码改动
    • 适用:所有新项目和可改造项目
  2. ORM 框架的 @Transactional(readOnly)(次选)

    • 优点:框架级支持、代码侵入小
    • 缺点:依赖框架能力
    • 适用:Spring、Django、Rails 等
  3. 第三方代理 SQL 解析(不推荐)

    • 优点:应用无需改动
    • 缺点:额外维护成本、故障点、学习曲线
    • 适用:遗留系统且完全无法修改代码

阶段化部署

阶段 1:非生产环境验证
- 创建 Proxy 连接到开发/测试数据库
- 应用完整功能测试
- 性能基准测试
- 监控指标观察
阶段 2:生产环境灰度
- 选择 10% 流量切换到 Proxy
- 观察 1 周监控指标
- 逐步增加到 50%、100%
阶段 3:优化调整
- 根据 SessionPinned 指标优化代码
- 调整连接池参数
- 配置告警规则

回退方案

  • 保留原数据库直连端点
  • 通过配置中心快速切换连接字符串
  • 监控关键业务指标确保无异常

跨 VPC 访问

使用场景:应用和数据库在不同 VPC

graph LR
    A[应用 VPC] --> B[Proxy 跨VPC端点]
    B --> C[数据库 VPC]
    
    style A fill:#e1f5ff
    style B fill:#fff4e1
    style C fill:#e1ffe1

配置步骤:

  1. 创建额外的 Proxy 端点
  2. 选择应用 VPC 和子网
  3. 配置安全组允许跨 VPC 访问
  4. 应用连接到跨 VPC 端点

为什么不用 VPC Peering:Proxy 跨 VPC 端点使用 PrivateLink,配置更简单且更安全。


Q1: RDS Proxy 会增加延迟吗?

A: 会有轻微延迟增加(通常 < 1ms)。但连接复用带来的整体性能提升远超过这点延迟。对于高频建立连接的应用,整体响应时间反而会下降。

Q2: 使用 Proxy 后如何直接连接数据库进行运维?

A: 保留原数据库端点用于直接连接。运维操作(如执行 DDL、数据导入)建议直连数据库,避免受 Proxy 连接池限制。

Q3: Proxy 是否支持数据库参数修改?

A: 支持,但数据库参数修改需要重启实例才能被 Proxy 识别,即使选择”立即应用”。集群级参数需要集群范围重启。

Q4: 如何验证应用是否通过 Proxy 连接?

A: 查看 CloudWatch 指标 ClientConnections,或在数据库中执行:

-- MySQL
SELECT user, host FROM information_schema.processlist;
-- 通过 Proxy 的连接会显示 Proxy 的内部 IP
-- PostgreSQL
SELECT usename, client_addr FROM pg_stat_activity;

Q5: 使用 Proxy 后还需要应用层连接池吗?

A: 需要。应用层连接池管理到 Proxy 的连接,Proxy 管理到数据库的连接。两层连接池配合使用效果最佳。

Q6: Proxy 默认端点是否会自动读写分离?

A: 不会。这是常见误解。默认端点所有请求都路由到写入实例。必须创建只读端点并在应用层区分读写请求才能实现读写分离。

Q7: 如何处理复杂事务中的读写混合?

A: 整个事务使用写端点。示例:

# 错误做法
with read_engine.begin(): # 使用只读端点
data = conn.execute("SELECT * FROM accounts WHERE id = 1")
conn.execute("UPDATE accounts SET balance = ... WHERE id = 1") # 失败!
# 正确做法
with write_engine.begin(): # 整个事务使用写端点
data = conn.execute("SELECT * FROM accounts WHERE id = 1 FOR UPDATE")
conn.execute("UPDATE accounts SET balance = ... WHERE id = 1")

Q8: Proxy 费用如何计算?

A: 按数据库实例 vCPU 计费,与实例运行时间相同。如果 Proxy 连接到 Aurora 集群(1 个 Writer + 2 个 Reader),按所有实例的总 vCPU 计费。


  • 评估应用是否适合使用 Proxy
  • 确认数据库引擎和版本支持
  • VPC 至少有 2 个私有子网(不同 AZ)
  • 创建 Secrets Manager 密钥
  • 创建 IAM 角色并配置权限
  • 规划安全组规则
  • Proxy 状态为”Available”
  • 通过 Proxy 端点可正常连接数据库
  • 应用功能测试通过
  • 只读端点已创建(如需要)
  • CloudWatch 监控指标正常
  • 配置告警规则
  • 文档记录端点地址和配置
  • 已创建只读端点
  • 应用代码区分读写请求
  • 读连接池指向只读端点
  • 写连接池指向默认端点
  • 验证只读端点流量分布到 Reader 实例
  • 测试故障转移场景