亚马逊AWS官方博客
CloudFront 部署小指南(十六): 通过 CloudFront Functions 实现动态选择源站
![]() |
动态选择源站(Origin Modification)是 CDN 的一个典型应用场景,特别在网页服务场景中,服务提供方希望可以根据访问者的地理位置或者设备信息将 HTTP 请求分配到合适的源站进行数据的处理和页面的渲染。
过去,Amazon CloudFront 使用 Lambda@Edge 或者使用重定向的功能来实现源站的动态选择;现在,Amazon CloudFront 支持在 CloudFront Functions 中对源站服务器进行动态的修改。您可以在 CloudFront Functions 中编写自定义逻辑,将请求转发到亚马逊云科技源站如 S3/API gateway/ELB,也可以将请求转发到任何公共 HTTP 端点,获得更加高的性能和性价比。
在接下来的博客中,我们将为大家介绍 CloudFront Functions 对源站服务器进行动态修改的功能架构和应用场景。
内容简介
我们将首先介绍这一功能的工作原理及其在 CloudFront 中的适用场景,分析这一功能在实际应用场景中的优势,展示它相比传统方式的独特价值。接着将详细说明如何部署和配置相关的 CloudFront Functions 代码。
通过这篇文章,希望读者可以理解 CloudFront Functions“修改源站服务器”功能的特点,并获得在具体项目中加以应用的实践指引。
架构描述
CloudFront Functions 是运行在 Amazon CloudFront 服务之上的边缘脚本,当来自客户端的 HTTP 请求进入 CloudFront(Viewer Request),或者 HTTP 响应从 CloudFront 发往客户端时(Viewer Response),我们都可以配置 CloudFront Function 来运行特定的代码,比如客户端鉴权 / HTTP header 改写 / URI 改写 / 自定义响应等。详细介绍请参考《Amazon CloudFront部署小指南(四)》。
发布 CloudFront Functions Origin Modification 这一功能后,我们可以在 Viewer Request 触发器下使用 CloudFront Functions,根据客户端传递的信息或 CloudFront 自带的请求头,动态选择不同的源站。下图展示了在 CloudFront Functions 中使用方法 updateRequestOrigin() 路由至不同的源站的架构。在此方法中,可以指定回源的特征,如源站域名、请求路径、请求协议、超时时间等。
![]() |
相比于 Lambda@Edge 完成动态源站选择,CloudFront Functions 可以提供更低的延时和更高的扩展性。
- 性能:Lambda@Edge – >10ms 每次执行时间;CloudFront Functions – <1ms 每次执行时间
- 可扩展性:Lambda@Edge – up to 10K 每个区域每秒;CloudFront Functions – 10,000K 每秒并且可提升
在成本上,CloudFront Function 相比 Lambda Edge 的单价更低
- Pricing:Lambda@Edge – $0.60/million invocation;CloudFront Functions – $0.10/million invocation
在执行效率上,Lambda@Edge 可以在CloudFront 到源站的转发路径上运行,所以当您拥有高度可缓存的内容时,Lambda@Edge 更具成本效益,因为它仅在缓存未命中时运行,而 CloudFront Functions在每个请求时运行。
在代码实现上,Lambda@Edge 可以执行更加复杂的逻辑,如从第三方数据源(如 Amazon DynamoDB 或 Amazon S3)获取数据。
所以我们建议在以下场景使用 CloudFront Functions 动态源站选择功能:
- 当您的请求是动态的(无法被缓存)且始终回源时,CloudFront Functions 可提供更好的性能和更低的总体成本,例如需要动态回源的 A/B Testing 或需要根据客户端 IP 动态就近回源。
- 当您已经有一个将在每个请求上运行的现有 Viewer Request CloudFront Functions 时,您可以将源站更新逻辑添加到现有函数中。
部署演示
演示场景:“根据客户端地址动态指定源站”
此演示将分别在三个 Region 的 EC2 上搭建源站服务器,分别是 us-east-1、ap-southeast-1、eu-central-1;CloudFront 根据访问客户端 IP 地址所在的地理位置,Cloudfront 会自动产生标头“CloudFront-Viewer-Country”,来动态就近选择源站服务器。
Step 1:创建 CloudFront Functions
![]() |
CloudFront Functions Runtime 2.0 与 1.0 的区别:
- 语言支持:
- Runtime 1.0 支持 ES5.1,以及 ES6~9 的部分功能
- Runtime 2.0 支持 ES5.1,以及 ES6~12 的部分功能
- 模块/方法支持:
- Runtime 2.0 支持更丰富的模块,如新增 Buffer 模块
- Runtime 2.0 新增支持 atob() & btoa()全局函数
- Runtime 2.0 移除了 1.0 中非标准的 string 方法
综上,新创建的 CloudFront Functions 均建议使用 Runtime2.0,它提供了更丰富的功能和更完善的开发体验。
Step 2:在三个区域分别启动 EC2 实例,部署 Nginx 服务,作为源站
在每台 EC2 上部署 NGINX 和带有亚马逊云科技 region 信息的页面
在安全组放开 80 端口,此处因为是 Demo,所以未使用 HTTPS,生产环境建议使用 HTTPS 协议。
![]() |
Step 3:CloudFront Functions 测试
当前 CloudFront Functions 未发布到线上,先完成测试。
CloudFront → 函数 → <函数名> → 测试 :
![]() |
因为未发布到线上,所以“阶段”选择 Development,由于我们所需的 Header 头是 CloudFront 在 Viewer 收到请求后添加的,在测试阶段需要显示指定对应 Header。
由于 Functions 部署在 Viewer Request,所以执行结果输出无法提供具体的回源信息。可以在 CloudFront Functions 里打印最终的回源 domain,根据打印日志,确认代码逻辑是否正常:
![]() |
根据 Viewer Country 为 CN,最终选择的源站为 ap-southeast-1,符合预期。
Step 4:为 CloudFront 分发创建缺省源站
CloudFront → 分配 → <分配名> → 源 → 创建源
需要在分发中配置一个缺省源站,才能进行 Step5 Behavior 里的相关配置。此处源站可随意选择上述三个区域的源站之一,也可以是任意其他地址。
![]() |
Step 5:修改 CloudFront 分发行为
CloudFront → 分配 → <分配名> → 行为 → <行为名>
将第 4 步创建的缺省源站关联到行为中
![]() |
为该行为配置缓存键和源请求策略
![]() |
模拟的业务场景为动态请求,需要回源,所以在缓存策略处配置“CachingDisabled”;如果源站配置了和终端访问域名(CloudFront 备用域名)相同的 Servername,则源请求策略建议选择“AllViewer”;如果不是的话,选择“AllViewerExceptHostHeader”。
Step 6:关联并发布 CloudFront Functions
CloudFront → 分配 → <分配名> → 行为 → <行为名> → 函数关联:
![]() |
CloudFront → 函数 → <函数名> → 发布 → 发布函数:
![]() |
Step 7:验证功能是否生效
从中国大陆访问:模拟来自中国大陆的 HTTP 访问,Country 为 CN,根据 Functions 逻辑应访问 ap-southeast-1 的服务器。
![]() |
查看 Functions Logs(CloudFront Functions logs 存储在 us-east-1 的 CloudWatch LogGroup 里):
![]() |
从美国访问:
![]() |
查看 Functions Logs:
![]() |
附录
CloudFront Functions 代码:
总结
本文介绍了 Amazon CloudFront 发布的 Functions 新功能——支持对源站服务器进行修改。这一重要更新为用户提供了更灵活的请求路由控制能力,使得在边缘位置实现智能请求分发成为可能。
主要优势包括:
- 性能提升:相比 Lambda@Edge,CloudFront Functions 运行在边缘节点层面,可以处理更高的请求量,延迟更低。
- 成本效益:对于需要动态路由的场景,CloudFront Functions 的成本是 L@E 的六分之一,是一个更经济的解决方案。
不过在选择使用 CloudFront Functions 还是 Lambda@Edge 时,需要根据具体使用场景权衡。高度可缓存内容可能更适合 Lambda@Edge,而对于需要动态路由且请求量大的场景,CloudFront Functions 则更具优势。
这一功能的发布进一步丰富了 Amazon CloudFront 的功能集,为构建全球化、高性能的应用提供了更多可能性。该功能目前在亚马逊云科技全球支持,中国区暂不支持。