在大规模内容分发场景中,前端静态资源或动态接口往往通过 AWS CloudFront 加速。当团队需要上线新版本时,如果直接替换源站或全部刷新缓存,一旦新逻辑存在缺陷,故障会瞬间扩散到所有边缘节点。借助 Lambda@Edge,我们可以在 CloudFront 的请求处理链路中嵌入自定义代码,在 viewer-request 阶段就决定请求应该被转发到蓝色环境还是绿色环境,以此实现蓝绿部署与金丝雀发布。

Lambda@Edge 的请求拦截机制与流量路由原理
CloudFront 的 Lambda@Edge 支持四种触发器:viewer-request、viewer-response、origin-request 和 origin-response。要实现蓝绿或金丝雀,最常用的是 viewer-request,因为它在用户请求刚进入边缘节点时触发,此时我们可以读取请求头、Cookie、查询字符串,然后修改 request.origin 字段,将流量指向不同的源站。例如蓝色环境对应原始 S3 桶,绿色环境对应新版本桶,函数内通过随机数或用户标识计算比例。
这种机制的本质是将“路由决策”从中心化的负载均衡器下沉到边缘。由于 Lambda@Edge 运行在 AWS 全球两百多个边缘站点,用户请求无需绕回区域级网关,切换延迟极低。同时,函数代码是版本化管理的,发布新函数版本并关联到 CloudFront 缓存行为后,全量边缘节点会在几分钟内完成部署,比修改 DNS 或源站配置更可控。
需要注意的是,viewer-request 函数不能读取响应体,只能改写请求。如果要根据后端响应做动态降级,就要配合 origin-response 函数。但在金丝雀场景里,我们一般提前定好权重,不依赖响应内容做路由,这样函数执行速度快,也不会因为源站慢而增加用户等待。
基于权重与用户粘性的金丝雀代码实现
下面示例展示了一个 viewer-request 函数,它用随机方式将 10% 流量导向绿色环境,其余走蓝色;同时如果请求携带 version=green 的 Cookie,则强制走绿色,方便内部验收。代码中的源站域名需要替换为真实分配名。
'use strict';
exports.handler = async (event) => {
const request = event.Records[0].cf.request;
const headers = request.headers;
const blueOrigin = 'blue-bucket.s3.amazonaws.com';
const greenOrigin = 'green-bucket.s3.amazonaws.com';
// 内部人员通过 Cookie 固定绿色环境
const cookie = headers.cookie ? headers.cookie[0].value : '';
if (cookie.includes('version=green')) {
request.origin = {
s3: { domainName: greenOrigin, region: 'us-east-1', path: '' }
};
return request;
}
// 10% 金丝雀流量
if (Math.random() < 0.1) {
request.origin = {
s3: { domainName: greenOrigin, region: 'us-east-1', path: '' }
};
} else {
request.origin = {
s3: { domainName: blueOrigin, region: 'us-east-1', path: '' }
};
}
return request;
};
上述代码使用了 Math.random() 做简单加权,但在生产环境建议结合用户 ID 哈希,避免同一浏览器多次请求被分到不同环境造成状态错乱。另外,Lambda@Edge 对函数包大小和运行时间有限制,viewer-request 超时必须低于 5 秒,且不能调用需要长连接的外部服务,因此路由逻辑应尽量轻量。
如果源站是自定义 HTTP 服务而非 S3,只需把 request.origin 改成 custom 结构并填写域名与端口。金丝雀比例调整也不需要改业务代码,只需更新函数中的阈值或读取外部配置(例如从 Parameter Store 通过 HTTP 接口拉取,但需注意超时),重新发布版本并关联 CloudFront 即可。
蓝绿切换、监控与快速回滚策略
蓝绿部署可以看作金丝雀比例为 0% 和 100% 的两个极端。当绿色环境经过金丝雀验证后,我们将函数中的随机判断去掉,全部请求指向绿色,蓝色保留作为兜底。若 CloudWatch 报警显示绿色源站 5xx 错误率突增,只需将函数回退到蓝色版本,整个过程在边缘节点生效仅需数十秒到几分钟,远快于重新构建流水线。
监控方面,应在 Lambda@Edge 函数里对关键路径打点,或依赖 CloudFront 自带的监控指标按源站域名过滤。由于函数分散在全球,日志会写入对应区域的 CloudWatch Logs,建议用日志订阅将各地日志聚合到中心桶,再用 Athena 查询不同环境的错误分布。下表对比了三种发布方式在 CloudFront 场景下的特点:
| 方式 | 切换速度 | 用户感知 | 回滚成本 |
|---|---|---|---|
| DNS 换源 | 依赖 TTL,慢 | 可能命中缓存旧 IP | 改回解析,等待生效 |
| 源站配置修改 | 中,需部署 | 缓存未刷新前混合 | 重新修改并发布 |
| Lambda@Edge 路由 | 快,边缘函数版本化 | 按权重精准控制 | 切函数版本秒级 |
在真实项目中,还应考虑缓存键的影响。如果 CloudFront 缓存了蓝色环境的响应,即使函数将新请求路由到绿色,回源前的缓存命中仍可能返回旧内容。因此做蓝绿发布时,通常需要变更资源的路径前缀或查询参数,使缓存键自然分离,或者主动失效相关缓存对象。这样才能保证金丝雀用户真正访问到新逻辑,而不是被旧缓存拦截。
AWS_CloudFrontLambda@Edgecanary_deployment修改时间:2026-08-18 13:40:32