CloudFront /api/*行为偶发路由到S3返回NoSuchKey报错
问题背景
使用CloudFront分发时配置了两个缓存行为:
- 默认行为对接S3存储桶,提供静态内容
- 路径模式为
/api/*的附加行为对接独立HTTP源站,作为后端API访问入口
对应的CDK部署代码如下:
const distribution = new Distribution(this, `${this.constructPrefix}-cloudfront-${this.constructSuffix}`, { defaultBehavior: { origin: new S3Origin(bucket, { originAccessIdentity: oai, }), functionAssociations: [ { function: cloudfrontFunctionRewritePath, eventType: FunctionEventType.VIEWER_REQUEST, }, ], viewerProtocolPolicy: ViewerProtocolPolicy.REDIRECT_TO_HTTPS, cachePolicy: frontCachePolicy, }, additionalBehaviors: { "/api/*": { origin: new HttpOrigin(`${buildConfig.ApiURL}`, { httpsPort: 443, protocolPolicy: OriginProtocolPolicy.HTTPS_ONLY, customHeaders: { "x-cloudfront-secret": `${cloudfrontSecret.secretValueFromJson("password")}`, }, }), cachePolicy: apiCachePolicy, viewerProtocolPolicy: ViewerProtocolPolicy.REDIRECT_TO_HTTPS, allowedMethods: AllowedMethods.ALLOW_ALL, edgeLambdas: edgeLambdaAssociations, }, }, logBucket: bucketLog, logFilePrefix: "cloudfront/", enabled: true, defaultRootObject: "index.html", domainNames: [domainName], certificate: secureCertificate, errorResponses: [ { httpStatus: 404, responseHttpStatus: 200, responsePagePath: "/index.html", ttl: Duration.seconds(86400), }, ], ...(buildConfig.AWSWebAclArn !== "NONE" ? { webAclId: buildConfig.AWSWebAclArn } : {}), });
故障现象
API端点/api/endpoint随机返回HTTP 404,报错内容为no such key the specified key does not exist,其余API端点均正常。异常响应携带Server: AmazonS3响应头,判断为CloudFront偶发未将该路径请求匹配到/api/*对应的HTTP源站,错误命中对接S3的默认行为。故障无稳定复现规律,需要明确排查方向。
排查思路(按故障概率从高到低排序)
- 优先排查默认行为绑定的Viewer Request级CloudFront Function(
cloudfrontFunctionRewritePath):这是最高概率的根因。Viewer Request层级的关联函数执行优先级高于缓存行为匹配,所有请求无论对应哪个路径,都会先经过该函数处理。只要函数内存在分支逻辑bug,比如对不带尾斜杠的路径、携带特殊query参数、特定请求方法的场景处理遗漏,偶发把/api/endpoint的URI改写为非/api/开头的形式,请求就会直接跳过/api/*规则匹配,落到S3默认源。直接在CloudFront控制台给该函数加测试用例,模拟/api/endpoint的所有请求变体(不同请求方法、带/不带尾斜杠、带不同query参数、带常规业务header),验证函数输出的URI是否始终保持/api/前缀即可。 - 排查API缓存策略的缓存污染问题:检查
apiCachePolicy的缓存键配置,如果策略未正确隔离不同路径的缓存,之前某次错误配置导致S3返回的404响应被边缘节点缓存,后续命中该缓存的请求就会直接返回S3的错误响应。可以先手动发起针对/api/endpoint的缓存失效操作,观察故障是否消失;同时确认缓存策略是否将不必要的header、query参数排除出缓存键,避免跨路径的缓存串扰。 - 检查Edge Lambda运行异常:
/api/*行为绑定的edgeLambdaAssociations如果存在Origin Request级别的函数偶发超时、执行报错,不会直接把错误返回给客户端,而是会自动跳过当前行为的源站配置,回退到默认行为的S3源。直接去CloudWatch筛选故障时间点、对应边缘节点的Lambda@Edge日志,查看是否有执行报错、超时、权限异常的记录即可。 - 核对路径匹配规则的边界:CloudFront路径模式大小写敏感,如果客户端偶发发起的请求路径为
/API/endpoint、/api/Endpoint这类大小写不匹配的形式,就不会命中/api/*规则,直接落到S3。去CloudFront访问日志里筛选返回S3 404的请求,查看cs-uri-stem字段记录的实际请求路径,确认是否完全符合/api/*的前缀要求即可。 - 确认分发配置的传播状态:如果近期修改过
/api/*的行为配置,CloudFront的配置更新是逐边缘节点传播的,传播窗口期(通常5-15分钟,极端情况可能到1小时)内会出现部分节点加载了新配置、部分节点仍使用旧配置的情况,如果旧配置未正确设置/api/*路径,就会出现偶发落S3的问题。可以通过不同地域的探测点发起请求,确认故障是否和特定地域/边缘节点强相关,如果是等待配置全量传播完成即可。
补充提示:当前配置的404错误响应规则是把所有404改写为返回
/index.html,如果故障时返回的是S3原生的XML格式404报错而不是index.html内容,基本可以排除配置传播问题,优先查函数改写和缓存污染两类问题。
内容的提问来源于stack exchange,提问作者Quentin Barbault
相关产品推荐
相关产品推荐

