AWS 五大核心服务故障排查与问题诊断实战手册(2026最新版)

📅 · 海外服务器线路与网络实测 - ChengziCloud

一句话结论

在 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
CloudTrailAPI 调用审计追踪控制台启用,默认保留 90 天
CloudWatch Logs服务级日志聚合各服务日志出口配置
VPC Flow Logs网络流量分析控制台 → VPC → Flow Logs
AWS Reachability Analyzer网络连通性诊断控制台 → VPC → Reachability Analyzer
AthenaS3 访问日志 SQL 查询CREATE EXTERNAL TABLE 建表

排查黄金法则:先查权限(IAM),再查网络(Security Group / NACL / VPC),最后查配置(服务自身参数)。这套顺序能覆盖 80% 的故障场景。

排查层级检查对象常用命令
第一层:权限IAM Policy、Bucket Policy、KMS Key Policyaws iam simulate-principal-policy
第二层:网络Security Group、NACL、Route Table、VPC Endpointaws 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:DecryptCloudTrail 查看 kms:Decrypt 事件
对象所有者与 Bucket 所有者不同跨账号上传未设置 bucket-owner-full-controlaws 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 压力:

对比维度直连 RDSRDS 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 示例优点缺点
用户 IDuser_12345查询用户数据高效活跃用户成为热点
UUIDa3f8b2c1-...完美负载均衡无法按用户高效查询
用户 ID + 时间戳user_12345#2026-07均衡 + 可查询Key 设计复杂
租户 ID + UUIDtenant_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 reachedINFO 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

排查关键步骤:

  1. curl -sI 查看 X-Cache: Error from cloudfront 确认回源失败
  2. 直接从 S3 访问(绕过 CloudFront)确认对象是否存在
  3. 检查 Bucket Policy 中的 aws:Referer 条件键
  4. 失效 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 消除冷启动?

八、故障排查速查表

服务最高频故障第一排查命令最快修复
S3403 Access Deniedaws s3api get-bucket-policy检查 IAM + Bucket Policy + KMS
S3503 Slow DownCloudWatch 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 后缀
ElastiCacheOOM 拒绝写入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 提供,点击访问首页了解更多