亚马逊AWS官方博客

Amazon CloudFront 部署小指南(九)- 利用 Amazon CloudFront 支持万级源服务器的精准回源

Amazon CloudFront 为广大的互联网公司以及各行各业的企业客户提供 CDN 服务。得益于 CloudFront 带来的独特优势:基于骨干网的回源链路提升动态回源性能,原生集成 Amazon WAF 带来 CDN 层面的七层安全防护,原生集成边缘计算能力解锁更多创新场景等,客户得以在云端构建各种创新架构的 web 应用。我们今天向大家分享的是一个采用 CloudFront 构建全球大规模直播平台的案例及其 CDN 层关键设计。

一. 背景信息

客户的目标是打造在线视频直播/视频会议平台,支持全球用户访问。单个直播会议可容纳几百人在线参加,参与者实时收看演讲者的直播和投屏。每天同时在线的会场达几千个,对应的是服务端几千个流媒体服务器节点,这些节点分布在美国东部和亚太等地的 AWS 区域以及客户 IDC 中。从 CDN 方案的角度,是否可以根据用户的请求信息来决定回源的目标地区和节点,成为了主要的考虑点。如果可以在 CDN 层面解决这个问题,意味着不再需要源端考虑复杂的代理和转发逻辑,对平台整体性能/成本/运维的好处是显而易见的。

按照通常思路,我们需要将多个 Origin(源节点)配置到同一个 CloudFront distribution 里,并利用 Cache Behavior 配置来实现基于不同用户的请求路径来决定将回源请求发往哪个 Origin。但在这个场景中,静态的 Cache Behavior 配置已经无法满足客户需要,因为:

1. Origin 数量达到几千个,已远远超过 CloudFront 的默认限额(25 origins per distribution);

2. 随着业务的按需调整,Origin 的数量和配置也在动态变化中,采用手工 update origin 信息的方式涉及到对生产系统的频繁变更,既繁琐又不安全,显然不可取。

为了应对这一挑战,我们采用了 CloudFront 的两个特色功能:Lambda@Edge 以及 Origin Shield,如果您还不确定这两个功能的作用,这里做一下简单介绍:

Lambda@Edge

Lambda@Edge 是一个 Amazon Lambda 的扩展功能,可用于执行函数以自定义 CloudFront 提供的内容。您可以在美国东部区域(N.Virginia Region)中编写 Node.js 或 Python 函数,然后在与用户较为接近的全球 AWS 位置执行它们,而无需预置或管理服务器。Lambda@Edge 会自动扩展,支持从每天几个请求到每秒数千个请求。在与用户较为接近的亚马逊设施(而不是源服务器)上处理请求,可显著减少延迟并改善用户体验。

Lambda@Edge 有很多用途。例如:

  1. Lambda 函数可检查 Cookie 并重写 URL,以便用户可看到不同版本的站点以进行 A/B 测试。
  2. CloudFront 可通过检查 User-Agent header 标头信息来判断用户使用的设备,从而将合适的对象返回给浏览器。例如,CloudFront 可基于设备的屏幕尺寸返回合适尺寸的图片。同样,函数可考虑 Referer 标头的值,并使 CloudFront 将最低分辨率的图像返回给爬虫请求。
  3. 可以基于 Cookie 信息来进行功能定制。例如,在出售服装的零售网站上,如果您使用 Cookie 来指示用户选择了哪种颜色的夹克,Lambda 函数可更改相应请求,以便 CloudFront 返回选定颜色的夹克的图像。
  4. 可协助认证授权过程。使用 Lambda@Edge 函数来检查请求的标头或授权令牌,并相应地在 CloudFront 将请求转发到您的源之前插入一个标头,以控制特定用户对您的内容的访问。

详细信息请参考:https://docs.aws.amazon.com/zh_cn/AmazonCloudFront/latest/DeveloperGuide/lambda-at-the-edge.html

Origin Shield

CloudFront Origin Shield 是 CloudFront 缓存基础设施中的一个附加层,有助于最大限度地减少源的负载、提高其可用性并降低其运营成本。借助 CloudFront Origin Shield,您可以获得以下优势:

  1. 提高 CloudFront 的缓存命中率,因为它在源之前提供了额外的缓存层。当您使用 Origin Shield 时,从 CloudFront 缓存层到源的所有请求都会通过 Origin Shield,从而增加缓存命中的可能性。CloudFront 缓存的所有其他层(边缘站点和区域边缘缓存)可以从 Origin Shield 中检索对象而不必都回源。
  2. 进一步减少针对同一对象发送到源的同时请求的数量。对不在 Origin Shield 缓存中的内容的请求将与对同一对象的其他请求合并,从而确保发往源的请求只有一个。在源中处理较少的请求可以在高峰负载或意外流量峰值期间保持源的可用性,并且可以降低算力和数据传出成本。
  3. 更好的网络性能。对于亚马逊区域中的源,CloudFront 网络流量始终保留在高吞吐量 CloudFront 网络上,直至您的源。对于客户 IDC 中的源,用户请求也将得益于 CloudFront 网络, 借由离 IDC 最近的 Origin Shield 触达 IDC 源。

详细信息请参考:https://docs.aws.amazon.com/zh_cn/AmazonCloudFront/latest/DeveloperGuide/origin-shield.html

二. 方案架构

整体架构:

1. 采用单个 CloudFront Distribution 提供流媒体直播服务;

2. 采用 CloudFront Origin Shield 来提升性能,并减少源服务器负载。根据实际源服务器的全球地理分布来决定配置几个 Origin Shield;

3. 采用 Lambda@Edge 来提取用户请求路径中的关键信息并返回正确的源地址。

示意图如下:

单次用户请求的全过程:

1. 用户请求发往最近的 CloudFront edge location,CloudFront 检查该请求是否命中边缘缓存;

2. 如边缘侧没有缓存,则发起回源请求;

3. CloudFront 基于 Cache Behavior 配置以及客户请求的 URL 路径,决定将回源请求送往哪个 Origin Shield;

4. 如 Origin Shield 已有请求内容,则返回。如 Origin Shield 没有请求内容,则进行实际回源;

5. CloudFront 基于 Lambda@Edge 从用户请求中提取到的服务器信息发起回源请求,源服务器返回媒体文件;

6. 用户浏览器获取到媒体文件,CloudFront 将这批文件放入 Origin Shield 以及 CloudFront 边缘站点缓存,以满足相同会议的其他用户发起的就近访问。

三. 详细配置示例

详细配置参考:

1. 创建 CloudFront Distribution,该 Distribution 将是平台统一入口

注:在此处配置的 Origin domain 域名关系不大,最终我们将使用 Lambda@Edge 动态修改回源请求中的 host 域名。

在 Origin Shield 配置区选择 Yes(Enable Origin Shield)并基于 Origin 的地点(上图示例在美国)选择就近的 Origin Shield region

按需选择 Cache Policy

创建好后,在已创建的 Distribution 里选择 Origin 选项卡,可看到创建时配置的 Origin

2. 点击 Create Origin 以创建第二个 Origin 所在地(如新加坡)

类似地,指定就近的 Origin Shield

3. 创建 Behaviors 配置

在 Distribution 里点击 Behavior 选项卡,点击 Create Behavior

创建第一个 Behavior 配置,指定 path pattern 以及 Origin 如下

同样地,需要为美国的 Origin 创建另一个 Behavior 配置,Path pattern 参考上图,这里不做赘述。

4. Lambda@Edge 的集成

创建 Lambda 函数。打开 Lambda console(请根据 console 右上角区域信息确保自己在 us-east-1 区域),点击创建

本示例中用到的 Lambda 代码:

def lambda_handler(event, context):
request = event['Records'][0]['cf']['request']

targetURI = request['uri']

if targetURI:
        pos1 = targetURI.find('/', targetURI.find('/') + 1) 
        pos2 = targetURI.find('/', pos1 + 1)
        if pos1 >= 0 and pos2 >= 0:
            targetOrigin=targetURI[pos1+1 : pos2]
            targetOriURI=targetURI[pos2 :]
        else:
            print("Invalid string")

        domainName = '%s.example.com' % targetOrigin
        request['origin']['custom']['domainName'] = domainName
        request['headers']['host'] = [{'key': 'host', 'value': domainName}]
        request['uri'] = targetOriURI

return request

将以上代码拷贝至 Lambda console 代码编辑区域并保存

点击 Test 下拉三角,进入 Test event 编辑界面

可选择‘Create new event’, 或者基于现有 CloudFront Event 模板‘Edit saved event’。可以在以下文档中获取到 CloudFront origin request 的示例请求:https://docs.aws.amazon.com/AmazonCloudFront/latest/DeveloperGuide/lambda-event-structure.html#lambda-event-structure-request

基于实际业务场景来编辑测试请求体

点击‘Test’,在 Execution Results 页面可看到执行结果

下拉 response 结果并确认返回的 Origin domainName 和 uri 字段都符合预期。以下返回结果证明了 Lambda@edge 可正确地从 request 中提取出相应信息并拼接成实际的 Origin server 的域名和请求 url,确保精准回源,达到业务目的。

测试完毕,将该 Lambda 函数发布,并记录函数 ARN

在 CloudFront Distribution 的 Behavior 配置界面,参考下图将以上发布的 Lambda 函数关联到 Origin request 中,这样回源请求将触发该函数的执行,实现动态修改回源请求指向正确的源节点

相同的关联操作针对 us 和 singapore 的两个 Behavior 配置都需要做一遍。

至此,CloudFront 部分配置完毕。

四. 总结

本文主要介绍了基于 CloudFront 打造全球视频直播平台的实践,采用 Lambda@Edge 实现边缘侧的动态逻辑,以满足定制化场景的回源需求;采用 Origin Shield 功能进一步提升了 CDN 缓存能力和请求响应速度,减少了源服务器的压力。我们也希望能看到更多围绕 CloudFront 的独特功能打造的创新架构,持续为客户创造更大的价值。

亚马逊云科技 CloudFront 部署小指南系列文章

Amazon CloudFront 部署小指南(一)- 快速构建 CDN 内容分发:https://aws.amazon.com/cn/blogs/china/amazon-cloudfront-deployment-handbook-part-one/

Amazon CloudFront 部署小指南 (二)- 进阶部署:https://aws.amazon.com/cn/blogs/china/amazon-cloudfront-deployment-handbook-part-two/

Amazon CloudFront 部署小指南 (三)- 持续部署:https://aws.amazon.com/cn/blogs/china/amazon-cloudfront-deployment-handbook-part-three/

Amazon CloudFront 部署小指南(四)- CloudFront Function 基础与诊断:https://aws.amazon.com/cn/blogs/china/amazon-cloudfront-deployment-handbook-part-four/

Amazon CloudFront 部署小指南(五)- 使用 AWS 边缘技术优化游戏内资源更新发布:https://aws.amazon.com/cn/blogs/china/amazon-cloudfront-deployment-handbook-part-five/

Amazon CloudFront 部署小指南(六)- Lambda@Edge 基础与诊断:https://aws.amazon.com/cn/blogs/china/amazon-cloudfront-deployment-handbook-part-six/

Amazon CloudFront 部署小指南(七)- 使用 CloudFront Function 模板加 EchoServer 进行快速调试:https://aws.amazon.com/cn/blogs/china/quick-debugging-using-cloudfront-function-templates-and-echoserver/

Amazon CloudFront 部署小指南(八)- 使用中国区 CloudFront 及 CloudFront SSL 插件部署免费证书:https://aws.amazon.com/cn/blogs/china/divert-website-access-traffic-from-ec2-to-amazon-cloudfront/

本篇作者

李萌

AWS 解决方案架构师,负责跨国企业客户的解决方案咨询,应用架构设计优化,同时致力于 AWS 云存储及安全类服务的应用和推广,对云安全/高可用及容灾系统/区块链等技术有深入的研究和热情。加入 AWS 之前曾服务于多家跨国电信运营商及 IT 解决方案供应商,积累了丰富的电信/零售快消行业 IT 系统建设项目经验。

叶明

亚马逊云科技边缘产品架构师,负责 CloudFront 和 Global Accelerator 服务在中国和全球的市场拓展,专注于互联网用户访问云上服务的感受的优化以及数据洞察。在互联网基础设施领域有丰富的实践经验。