AWS 五大核心服务故障排查与问题诊断实战手册(2026最新版)
在 AWS 生产环境中,即便是最成熟的架构也难免遭遇各种"玄学"故障——S3 忽然返回 403、CloudFront 缓存迟迟不刷新、RDS 连接池耗尽、DynamoDB 写入被限流、ElastiCache 节点莫名其妙重启。
- 故障排查工具箱:先武装自己
- S3 故障排查:403 与性能瓶颈
- CloudFront 故障排查:缓存不回源
- RDS 故障排查:连接耗尽与慢查询
- DynamoDB 故障排查:节流与热分区
- ElastiCache 故障排查:内存溢出与连接风暴
- 跨服务故障排查:连锁反应诊断
- 故障排查速查表
在 AWS 生产环境中,即便是最成熟的架构也难免遭遇各种"玄学"故障——S3 忽然返回 403、CloudFront 缓存迟迟不刷新、RDS 连接池耗尽、DynamoDB 写入被限流、ElastiCache 节点莫名其妙重启。面对这些问题,如果缺乏一套系统的排查方法论,运维人员往往只能在 AWS 控制台和各日志系统之间来回跳转,浪费大量时间。
本文整理了过去一年中我们在生产环境遇到的最高频故障场景及其诊断流程,覆盖 S3、CloudFront、RDS、DynamoDB 和 ElastiCache 五大核心服务,每个问题都附带可执行的排查命令和根治方案。
一、故障排查工具箱:先武装自己
在深入具体问题之前,确认你已经配置好了以下工具——它们是排查 AWS 问题的"瑞士军刀":
| 工具 | 用途 | 安装/启用命令 |
|---|---|---|
| AWS CLI | 所有服务的命令行操作 | pip install awscli |
| CloudTrail | API 调用审计追踪 | 控制台启用,默认保留 90 天 |
| CloudWatch Logs | 服务级日志聚合 | 各服务日志出口配置 |
| VPC Flow Logs | 网络流量分析 | 控制台 → VPC → Flow Logs |
| AWS Reachability Analyzer | 网络连通性诊断 | 控制台 → VPC → Reachability Analyzer |
| Athena | S3 访问日志 SQL 查询 | CREATE EXTERNAL TABLE 建表 |
排查黄金法则:先查权限(IAM),再查网络(Security Group / NACL / VPC),最后查配置(服务自身参数)。这套顺序能覆盖 80% 的故障场景。
| 排查层级 | 检查对象 | 常用命令 |
|---|---|---|
| 第一层:权限 | IAM Policy、Bucket Policy、KMS Key Policy | aws iam simulate-principal-policy |
| 第二层:网络 | Security Group、NACL、Route Table、VPC Endpoint | aws ec2 describe-security-groups |
| 第三层:配置 | 服务自身参数、配额、限流 | 各服务 describe-* 命令 |
二、S3 故障排查:403 与性能瓶颈
问题 1:S3 返回 403 Access Denied
这是 S3 最高频的故障。403 不等于"没有权限"——它只是 S3 的一种通用拒绝响应。实际原因可能是:
| 真实原因 | 触发条件 | 诊断方法 |
|---|---|---|
IAM Policy 缺少 s3:GetObject | 用户/角色权限不足 | aws iam simulate-principal-policy |
| Bucket Policy 显式 Deny | 来源 IP、VPC Endpoint、Principal 不匹配 | 检查 Bucket Policy 中的 Deny 语句 |
| KMS 加密对象无解密权限 | 对象使用 SSE-KMS 加密,调用者无 kms:Decrypt | CloudTrail 查看 kms:Decrypt 事件 |
| 对象所有者与 Bucket 所有者不同 | 跨账号上传未设置 bucket-owner-full-control | aws s3api head-object --bucket B --key K 查看 Owner |
| S3 Block Public Access | 账户级或 Bucket 级阻止公开访问 | 控制台 → S3 → Permissions → Block Public Access |
排查命令:
# 1. 查看对象 ACL 和所有者
aws s3api get-object-acl --bucket my-bucket --key path/to/object
# 2. 查看 Bucket Policy
aws s3api get-bucket-policy --bucket my-bucket
# 3. 模拟 IAM 权限
aws iam simulate-principal-policy \
--policy-source-arn arn:aws:iam::123456789012:user/devops \
--action-names s3:GetObject \
--resource-arns arn:aws:s3:::my-bucket/*
# 4. 查看 CloudTrail 中与该对象相关的拒绝事件
aws cloudtrail lookup-events \
--lookup-attributes AttributeKey=ResourceName,AttributeValue=my-bucket \
--query 'Events[?contains(CloudTrailEvent,`errorCode`)]'
问题 2:S3 读写延迟异常高
| 症状 | 可能原因 | 解决方案 |
|---|---|---|
| PUT 请求 P99 延迟 > 500ms | 跨区域上传、对象过大未用分段上传 | 启用 S3 Transfer Acceleration;对象 > 100MB 使用 Multipart Upload |
| GET 请求首字节延迟高 | 请求未命中 S3 就近边缘节点 | 前置 CloudFront 做缓存层 |
| 大量 503 Slow Down | 前缀热点——单个前缀 QPS 超 3500(PUT)或 5500(GET) | 在 Key 前缀中加入时间戳或 Hash 分散请求 |
| ListObjects 超时 | Bucket 中对象数量超过 1 亿 | 使用 S3 Inventory + Athena 替代实时 List |
前缀热点是 S3 性能问题的头号杀手。S3 内部按前缀分区,如果所有请求集中在同一个前缀(如 uploads/2024/),就会触发限流。推荐的 Key 命名策略:
# ❌ 坏设计:所有对象共享同一前缀
uploads/2024/01/file1.jpg
uploads/2024/01/file2.jpg
# ✅ 好设计:在 Key 前端加入高基数字段
e8a4f2-uploads/2024/01/file1.jpg
3b7c1d-uploads/2024/01/file2.jpg
三、CloudFront 故障排查:缓存不回源
问题 3:更新源站内容后 CloudFront 仍返回旧版本
这是 CDN 运维中最令人头痛的问题——你明明上传了新版本,用户看到的却还是旧的。
排查路线图:
用户看到旧内容
↓
检查 Cache-Control / Expires 响应头 → TTL 过长? → 缩短 max-age
↓
执行手动失效(Invalidation)→ 成功但用户仍见旧版本?
↓
检查源站是否有中间缓存层(Nginx proxy_cache、ALB 缓存等)
↓
检查 CloudFront Behavior 中是否开启了 Origin Shield
↓
确认请求最终到达了正确的源站(查看 X-Cache 响应头)
关键诊断命令:
# 查看 CloudFront 响应的缓存状态
curl -sI "https://d123.cloudfront.net/image.jpg" | grep -i x-cache
# X-Cache: Hit from cloudfront → 命中缓存
# X-Cache: Miss from cloudfront → 回源
# X-Cache: Error from cloudfront → 源站错误
# 查看对象当前的缓存行为(带不同 Accept-Encoding 测试 Vary 头)
curl -sI -H "Accept-Encoding: gzip" "https://d123.cloudfront.net/page.html"
# 创建失效请求(支持通配符)
aws cloudfront create-invalidation \
--distribution-id EXXXXXXXXXXXXX \
--paths "/images/*" "/index.html"
| 失效类型 | 配额 | 费用 | 适用场景 |
|---|---|---|---|
标准失效(/*) | 每月 1000 个路径(免费) | 超出后 $0.005/路径 | 常规更新 |
版本化 URL(/v2/app.js) | 无限制 | 免费 | 推荐:永远不需要失效 |
| Cache-Control 覆写 | 无需失效 | 免费 | 设置短 TTL + stale-while-revalidate |
最佳实践:不要依赖手动失效,使用文件名版本化(Content Hashing)——每次构建时将文件内容哈希值嵌入文件名(如 app.a3f8b2c.js),新版本上线后 CDN 自动拉取新文件,旧文件自然过期。
问题 4:CloudFront 回源延迟高
| 场景 | 原因 | 解决方案 |
|---|---|---|
| 中国大陆用户访问慢 | CloudFront 无中国大陆节点 | 使用 CloudFront 中国专区或切换至阿里云 CDN |
| 源站在美东,欧洲用户延迟高 | 源站未做跨区域部署 | 启用 Origin Shield + 多区域源站(Lambda@Edge 智能路由) |
| 首次请求慢(冷启动) | 边缘节点无缓存,需回源 | 预热缓存(使用 Warm-up 脚本在低峰期遍历关键 URL) |
| 动态内容回源慢 | 每次请求都回源 | 启用 CloudFront 的 Regional Edge Cache 或将动态部分改为 AJAX 异步加载 |
四、RDS 故障排查:连接耗尽与慢查询
问题 5:RDS 连接数打满导致新连接被拒
症状:应用程序日志中出现 too many connections、remaining connection slots are reserved。
诊断流程:
-- 1. 查看当前连接数(需要在能连上数据库的时候执行)
SHOW STATUS LIKE 'Threads_connected';
SHOW VARIABLES LIKE 'max_connections';
-- 2. 查看哪些连接占用了资源
SELECT * FROM information_schema.processlist
WHERE command != 'Sleep'
ORDER BY time DESC;
-- 3. 通过 Performance Schema 分析连接来源
SELECT user, host, COUNT(*) as cnt
FROM information_schema.processlist
GROUP BY user, host
ORDER BY cnt DESC;
| 根本原因 | 排查手段 | 根治方案 |
|---|---|---|
| 应用连接池未配置或配置过小 | 应用日志中 connection timeout | 配置连接池(HikariCP: maximumPoolSize=30) |
| 慢查询堆积阻塞连接 | RDS Performance Insights → 按等待时间排序 | 优化慢 SQL、添加索引 |
| 突发流量峰值 | CloudWatch DatabaseConnections 指标突增 | 启用 RDS Proxy 做连接池复用 |
| 长时间未提交事务 | SHOW ENGINE INNODB STATUS 查看事务列表 | 设置 innodb_lock_wait_timeout + 应用层超时 |
RDS Proxy 是解决连接数问题的银弹——它在应用和数据库之间建立连接池,将数百个应用连接映射到几十个数据库连接,大幅降低数据库的内存和 CPU 压力:
| 对比维度 | 直连 RDS | RDS Proxy |
|---|---|---|
| 连接复用 | 不支持 | 自动复用,减少 60-80% 数据库连接数 |
| 故障切换耗时 | 30-90 秒 | 10-30 秒(自动检测并重定向) |
| IAM 认证 | 需额外代码 | 原生支持 IAM 数据库认证 |
| 费用 | 免费 | $0.015/小时 + 按 vCPU 计费 |
问题 6:RDS 存储空间耗尽
症状:数据库进入 storage-full 状态,无法写入。
诊断:
# 查看存储使用情况
aws rds describe-db-instances \
--db-instance-identifier my-db \
--query 'DBInstances[0].[AllocatedStorage,DBInstanceStatus]'
# 查看 CloudWatch 中的 FreeStorageSpace 指标
aws cloudwatch get-metric-statistics \
--namespace AWS/RDS --metric-name FreeStorageSpace \
--dimensions Name=DBInstanceIdentifier,Value=my-db \
--start-time $(date -d '1 hour ago' -u +%Y-%m-%dT%H:%M:%SZ) \
--end-time $(date -u +%Y-%m-%dT%H:%M:%SZ) \
--period 300 --statistics Minimum
处理方案:
| 场景 | 措施 | 注意 |
|---|---|---|
| 剩余空间 < 10% | 立即扩容存储(在线操作,不停机) | 扩容后不可缩容 |
| 存储自动增长已到上限 | 手动修改 max_allocated_storage | 默认上限 65536 GB |
| Binlog 占用过大 | PURGE BINARY LOGS BEFORE NOW() - INTERVAL 1 DAY; | 确认从库已同步后再清理 |
| 大量临时表占用 | 优化含 ORDER BY/GROUP BY 的查询,减少临时表创建 | 增大 tmp_table_size |
五、DynamoDB 故障排查:节流与热分区
问题 7:DynamoDB ProvisionedThroughputExceededException
症状:写入/读取请求返回 ProvisionedThroughputExceededException,CloudWatch 中 ThrottledRequests 指标飙高。
| 原因 | 判断方法 | 解决方案 |
|---|---|---|
| 预置容量不足 | CloudWatch ConsumedReadCapacityUnits > 预置值 | 提升 RCU/WCU 或开启 Auto Scaling |
| 热分区 | CloudWatch 中单个分区容量消耗远超其他分区 | 重新设计 Partition Key,使用 UUID 或时间戳后缀 |
| 突发流量超出自适应容量 | 短时间内流量超出预置 5 倍以上 | 改用 On-Demand 模式;为预置模式设置更高的 Target Utilization |
| GSI/LSI 也消耗容量 | 写入时同步更新索引导致额外消耗 | 仅创建必要索引,减少投影属性 |
DynamoDB 自适应容量(Adaptive Capacity) 会在检测到热分区时自动重新分配容量,但有以下限制:
自适应容量不是即时生效的——它需要几分钟时间识别热点并重新分配。如果流量在短期内呈指数级增长,自适应容量可能来不及响应,导致请求被限流。对于已知的高峰事件(如促销活动),应提前提升预置容量。
排障命令:
# 查看表的节流指标
aws cloudwatch get-metric-statistics \
--namespace AWS/DynamoDB \
--metric-name ThrottledRequests \
--dimensions Name=TableName,Value=my-table \
--start-time "$(date -d '1 hour ago' -u +%Y-%m-%dT%H:%M:%SZ)" \
--end-time "$(date -u +%Y-%m-%dT%H:%M:%SZ)" \
--period 300 --statistics Sum
# 查看表的当前容量模式
aws dynamodb describe-table --table-name my-table \
--query 'Table.[BillingModeSummary,ProvisionedThroughput]'
Partition Key 设计对比:
| 策略 | Key 示例 | 优点 | 缺点 |
|---|---|---|---|
| 用户 ID | user_12345 | 查询用户数据高效 | 活跃用户成为热点 |
| UUID | a3f8b2c1-... | 完美负载均衡 | 无法按用户高效查询 |
| 用户 ID + 时间戳 | user_12345#2026-07 | 均衡 + 可查询 | Key 设计复杂 |
| 租户 ID + UUID | tenant_01#a3f8 | 多租户场景理想选择 | 跨租户查询需 GSI |
六、ElastiCache 故障排查:内存溢出与连接风暴
问题 8:Redis 内存耗尽(OOM)
症状:Redis 返回 OOM command not allowed when used memory > 'maxmemory',写入操作全部失败。
诊断命令:
# 连接 Redis 查看内存使用
redis-cli -h my-cache.xxxxxx.0001.use1.cache.amazonaws.com INFO memory
# 关注以下指标:
# used_memory_human → 实际使用内存
# maxmemory_human → 最大可用内存
# mem_fragmentation_ratio → 内存碎片率(> 1.5 需关注)
# evicted_keys → 被驱逐的 Key 数量(非 0 说明内存不足)
# 查看 Key 的内存占用分布(需要 redis-rdb-tools)
rdb --command memory /var/lib/redis/dump.rdb --bytes 128
| 解决方案 | 适用场景 | 注意 |
|---|---|---|
设置合理的 maxmemory-policy | 允许淘汰旧数据 | allkeys-lru 最常用;volatile-lru 仅淘汰有过期时间的 Key |
| 纵向扩容节点类型 | 数据持续增长 | 在线扩容,不停机 |
| 增加数据分片(Cluster Mode) | 数据量超过单节点容量 | 需评估 Key 分布是否均匀 |
| 给 Key 设置 TTL | 临时数据(Session、验证码等) | Redis 7.0+ 支持 EXAT 绝对时间戳过期 |
| 清理大 Key | 单个 Key 过大导致内存碎片 | 使用 redis-cli --bigkeys 扫描 |
内存淘汰策略对比:
| 策略 | 行为 | 推荐场景 |
|---|---|---|
noeviction | 不淘汰,写入直接报错 | 缓存作为核心数据存储(不推荐) |
allkeys-lru | 淘汰最近最少使用的 Key | 通用缓存场景(推荐) |
allkeys-lfu | 淘汰访问频率最低的 Key | 有明确冷热数据的场景 |
volatile-lru | 仅淘汰有过期时间的 LRU Key | 混合持久化 + 临时数据场景 |
volatile-ttl | 淘汰 TTL 最短的 Key | 需要优先保留长期数据的场景 |
问题 9:ElastiCache 连接数过多
| 症状 | 诊断 | 解决方案 |
|---|---|---|
max number of clients reached | INFO clients → connected_clients 接近 maxclients | 应用层配置连接池,限制空闲连接数 |
| 大量 TIME_WAIT 连接 | 应用频繁建连断连 | 使用长连接 + 连接池;或使用 ElastiCache Serverless |
| 故障切换后连接数翻倍 | 新主节点与旧主节点同时有连接 | 客户端需检测拓扑变化并重建连接池 |
Redis 连接池最佳实践:
import redis
from redis import ConnectionPool
# ✅ 正确:使用连接池,设置合理的 max_connections
pool = ConnectionPool(
host='my-cache.xxxxxx.use1.cache.amazonaws.com',
port=6379,
max_connections=20, # 限制并发连接数
socket_keepalive=True, # 保持 TCP 长连接
socket_connect_timeout=2, # 快速失败
retry_on_timeout=True
)
r = redis.Redis(connection_pool=pool)
七、跨服务故障排查:连锁反应诊断
AWS 五大核心服务往往相互依赖,一个服务的故障会引发级联效应。以下是三个典型跨服务故障场景:
场景 A:S3 → CloudFront → 用户(静态资源加载失败)
用户请求 static.example.com/app.js
→ CloudFront 边缘节点无缓存,回源 S3
→ S3 返回 403(Bucket Policy 限制了 Referer 头)
→ CloudFront 缓存了 403 响应
→ 此后所有用户请求均返回缓存的 403
排查关键步骤:
curl -sI查看X-Cache: Error from cloudfront确认回源失败- 直接从 S3 访问(绕过 CloudFront)确认对象是否存在
- 检查 Bucket Policy 中的
aws:Referer条件键 - 失效 CloudFront 缓存 + 修复 Bucket Policy
场景 B:RDS → ElastiCache → 应用(缓存穿透)
应用先查 Redis → Miss → 查 RDS → RDS 慢查询超时
→ 应用重试 → 更多连接打到已过载的 RDS
→ RDS 连接耗尽 → Redis 也因缓存未及时更新而返回过期数据
防御策略:
| 策略 | 实现方式 | 效果 |
|---|---|---|
| 缓存空值 | 数据库返回 NULL 时也在 Redis 中缓存一个短 TTL 的空标记 | 防止穿透 |
| 互斥锁 | 缓存 Miss 时只有一个线程查 DB 并回写缓存 | 防止击穿 |
| 永不过期 + 异步更新 | 缓存 Key 不设 TTL,后台 Job 定期刷新 | 防止雪崩 |
| 熔断降级 | 数据库慢查询超过阈值时直接返回缓存数据或默认值 | 保护数据库 |
场景 C:DynamoDB 流 → Lambda → ElastiCache(缓存更新失败)
DynamoDB 表写入 → DynamoDB Stream 触发 Lambda
→ Lambda 解析事件并更新 ElastiCache
→ Lambda 因 VPC 冷启动耗时 8 秒,超时
→ ElastiCache 中数据过时,用户看到旧数据
排查清单:
- Lambda 是否在 VPC 内?(VPC 内的 Lambda 冷启动比非 VPC 慢 3-5 秒)
- Lambda 的安全组是否允许访问 ElastiCache 端口(6379/6380)?
- DynamoDB Stream 的 Batch Window 和 Lambda Reserved Concurrency 是否匹配?
- 是否开启了 Lambda Provisioned Concurrency 消除冷启动?
八、故障排查速查表
| 服务 | 最高频故障 | 第一排查命令 | 最快修复 |
|---|---|---|---|
| S3 | 403 Access Denied | aws s3api get-bucket-policy | 检查 IAM + Bucket Policy + KMS |
| S3 | 503 Slow Down | CloudWatch 5xxErrors | 分散 Key 前缀 |
| CloudFront | 缓存不更新 | curl -sI 查看 X-Cache | 文件名版本化 |
| CloudFront | 回源延迟高 | CloudFront 控制台 → 监控 → Origin Latency | 启用 Origin Shield |
| RDS | 连接数打满 | SHOW STATUS LIKE 'Threads_connected' | 启用 RDS Proxy |
| RDS | 存储空间耗尽 | CloudWatch FreeStorageSpace | 在线扩容 |
| DynamoDB | 写入节流 | CloudWatch ThrottledRequests | 改用 On-Demand 或优化 Partition Key |
| DynamoDB | 热分区 | CloudWatch ReadThrottleEvents | 在 Key 中加入 UUID 后缀 |
| ElastiCache | OOM 拒绝写入 | redis-cli INFO memory | 设置 allkeys-lru 淘汰策略 |
| ElastiCache | 连接数过多 | redis-cli INFO clients | 应用层使用连接池 |
九、建立主动监控体系
排查永远是事后补救,真正的运维高手在故障发生之前就收到了预警。建议在 CloudWatch 中为以下指标设置告警:
# RDS 连接数超过 80%
aws cloudwatch put-metric-alarm \
--alarm-name "RDS-High-Connections" \
--metric-name DatabaseConnections \
--namespace AWS/RDS \
--statistic Average --period 300 \
--threshold $(echo "$MAX_CONNS * 0.8" | bc) \
--comparison-operator GreaterThanThreshold \
--evaluation-periods 2
# DynamoDB 节流事件
aws cloudwatch put-metric-alarm \
--alarm-name "DynamoDB-Throttled" \
--metric-name ThrottledRequests \
--namespace AWS/DynamoDB \
--statistic Sum --period 300 \
--threshold 1 \
--comparison-operator GreaterThanThreshold \
--evaluation-periods 1
# ElastiCache 内存使用超过 75%
aws cloudwatch put-metric-alarm \
--alarm-name "ElastiCache-High-Memory" \
--metric-name DatabaseMemoryUsagePercentage \
--namespace AWS/ElastiCache \
--statistic Average --period 300 \
--threshold 75 \
--comparison-operator GreaterThanThreshold \
--evaluation-periods 2
总结
AWS 五大核心服务的故障排查遵循"权限 → 网络 → 配置"的三层模型。掌握这一方法论后,你不需要记住每一个具体错误的解法——只需要沿着这个层次逐层排除,绝大多数问题都能定位到根因。
- S3 的 403 不等于没权限,可能是 KMS、跨账号所有权或 Block Public Access
- CloudFront 的缓存问题应该通过文件名版本化根治,而不是依赖手动失效
- RDS 连接数问题首选 RDS Proxy,而非无脑提升
max_connections - DynamoDB 节流的根因通常是 Partition Key 设计不当,而非容量不足
- ElastiCache OOM 问题的第一反应应该是设置淘汰策略,而非立即扩容
将本文中的 CloudWatch 告警配置部署到你的生产环境,你将从此告别"用户投诉后才开始排查"的被动运维模式。
本文由 6.chengzicloud.cloud 提供,点击访问首页了解更多