亚马逊AWS官方博客
全站加速,Amazon CloudFront 配置不求人
本文适合希望使用 CloudFront 对网站、视频进行加速的初始用户及有一定使用经验的用户,涵盖如何配置及优化,内容难度200~300。
背景
随着移动互联网的发展,越来越多的图片分享、短视频、在线直播等应用越来越火,如何安全、经济高效、低延迟的将内容分发到终端用户受到开发者越来越多的关注。内容分发网络(CDN)是为解决互联网访问拥塞的问题而生,通过使用大量更靠近终端用户的边缘节点向终端用户提供服务以加速内容的分发,因此在应用系统前端部署 CDN 成为内容加速分发的不二选择。
一、什么是 Amazon CloudFront
Amazon CloudFront 是一种全球内容分发网络服务,可以安全地以低延迟和高传输速度向浏览者分发数据、视频、应用程序和 API。CloudFront 与 AWS 与多种 AWS 产品集成,如用于 DDoS 缓解的 AWS Shield、应用程序防火墙 AWS WAF、 Amazon S3、 Elastic Load Balancing、 Amazon EC2 以及 Amazon Route 53,以及可在 AWS 全球基础设施运行用户代码的 Lambda@Edge。
截止目前(2018年7月),Amazon CloudFront 在26个国家/地区的59个城市中设有131个接入点(121个边缘站点和11个区域性边缘缓存站点)。
举例说明,当客户端发起对 www.customer.com 的访问时,首先需要 DNS系统解析出该域名对应的主机 IP,通过本地 ISP DNS 递归查询到 customer.com 的 DNS 域名服务器并了解到该域名是指向了 xxx.cloudfront.net,进一步解析 xxx.cloudfront.net,CloudFront 的 DNS 域名服务器会根据请求来源的 IP 等信息,返回适合当前该客户端访问的边缘节点的主机 IP 如1.1.1.1,最终该客户端向1.1.1.1发出请求。如果该边缘节点已经缓存了该客户端请求的内容(图片、视频等静态文件),则直接返回给客户端,如果未缓存,则首先回源取回该内容,并存储在边缘节点,以便下次客户端对该内容请求时可以直接返回该内容。
更好的 CDN 性能表现带来更多的访问流量,以及更好的用户体验,下面我们将介绍如何配置以及优化建议。
二、如何配置 CloudFront Distribution
下面介绍下如何为自己的应用配置 CloudFront,实现网站访问加速。
在开始之前,首先简单介绍下 CloudFront的常见术语。
Distribution:分配是 CloudFront 的基本单元,每个分配有独一的 ID 以及CloudFront 为其分配的域名(类似 abcdefg13456789.cloudfront.net)。目前有 Web 和 RTMP 两种方式的分配, Web 分配主要用于分发静态、动态内容,基于 HTTP/s 协议的媒体文件分发,基于 HLS 协议的互联网直播等。 RTMP 分配主要用于基于 RTMP 协议的视频点播场景,源站必须为 S3 存储桶。本文以 Web 分配为例。
Origin: 源站,顾名思义,是加速的站点,可以是 S3 存储桶,可以是 ELB/EC2,可以是 Elemental MediaStore/MediaPackage,或者是用户自定义的站点(如第三方 IDC 中的 HTTP Web 服务器)。一个分配中可以有多个源站。
Behaviors:行为, CloudFront 通过路径匹配的方式决定执行哪一个缓存行为,一个分配中可以有多个 Behaviors,并且每个 Behaviors 对应一个源站。在 Behaviors 中可以设置缓存 TTL 时间,允许的 HTTP 行为(GET,PUT,POST 等),与 Lambda 关联等等。
本节将涉及如下内容:
- 创建一个分配;
- 该分配有两个源站,其中一个是创建时添加,一个是后添加。一个源站为ELB,一个源站为 S3 存储桶;
- 两个 Behaviors,一个是默认 Behaviors 并对应回源 ELB,一个是新加Behaviors 并对应源站 S3 存储桶;
- ELB,S3 创建过程不做介绍;
1、进入 CloudFront console,并选择新建 Distribution,选择 Web Distribution。
2、源站设置
部分解释如下:
Origin Settings | |
Origin Domain Name | 源站地址,仅支持域名方式。下拉列表中可以看到帐号里已经创建过的 ELB,S3,Elemental Media Service。 如果是自定义站点,需先给该站点配置域名,不能填写 IP。 |
Origin Path | (可选)如果源站内容有多层目录,而又希望回源的时候路径上不体现这些目录,可以在此设置要隐藏的目录层级。 |
Origin Protocol Policy | CloudFront 回源协议,可以是 HTTP 或 HTTPS,或者与client 发出请求时一样的协议。注意这儿是 CloudFront 回源站时用的协议,而不是 client 到达 CloudFront PoP 点的协议。 如果选用了 HTTPS,一定要注意源站配置对应回源域名(Origin Domain Name)的 SSL 证书。 |
Origin Response Timeout | 回源超时时间。 |
Origin Custom Headers | (可选)自定义回源 Header,即回源的时候添加的 Header,可以是一些自定义的 Header,通常用于由源站对该 Header 进行检测,如果有该 Header 则提供服务,没有则返回错误码,可用于内容访问的安全加强。 |
Default Cache Behavior Settings | |
Path Pattern | 此时是默认的 Default |
Viewer Protocol Policy | Client 到达 CloudFront 时用的协议,支持 HTTP 和 HTTPS,并且提供重定向 HTTP 到 HTTPS。 |
Allowed HTTP Methods | 允许的 HTTP 动作,不同的 Behavior 可以配置不同的选项。 |
Cache Based on Selected Request Headers | 是否按 Header 进行缓存。有 None,Whitelist,All 三个选项。如果只是需要按部分 Header 进行缓存,则选 Whitelist 并把对应的 Header 添加。All 是不做缓存,全部转发回源,此时 TTL 必须设置为0. 通常情况下,CloudFront 会将 client 发来的部分 Header 移除,因此需要按 Header 进行内容区分缓存或者源站需要由 Header 内容进行分别处理的,一定要在此白名单该 Header。 默认情况下,源站收到 CloudFront 发来的请求中的 Host 字段值为 Origin 中设置的源站域名,如果用户的源站需要拿到客户端发来的 Host 字段的值(即用户 CNAME 到该分配的域名),在此处就需要将 Host 添加到白名单,此时源站将收到该字段为客户端发出请求时用的值。 |
Object Caching | 缓存时效。可以遵循源站的设置(Cache-Control Header),或者在此处 Customize。Min, Max, Default TTL 之间的关系及效果详见: https://docs.thinkwithwp.com/zh_cn/AmazonCloudFront/latest/DeveloperGuide/Expiration.html |
Forward Cookies | 是否将 Cookie 转发回源,同样 CloudFront 会基于此值缓存不同的内容。 |
Query String Forwarding and Caching | 是否将查询字符串转发回源,同样 CloudFront 会基于此值缓存不同的内容。 |
Restrict Viewer Access (Use Signed URLs or Signed Cookies) |
是否使用签名的 URL 或签名的 Cookie |
Compress Objects Automatically | 是否启用自动压缩。如果请求中 Accept-Encoding 支持 gzip,则 CloudFront 可以自动压缩,以减小流量传输。 |
Lambda Function Associations | 是否关联 Lambda@Edge,我们在另一篇 blog 中将介绍Lambda@Edge 的使用,本篇不做说明。 |
由上可见,是否缓存、缓存多久跟是否转发 Header、Cookie、Query string也有关联,如何提高缓存的命中率以提高访问性能,可见https://docs.thinkwithwp.com/zh_cn/AmazonCloudFront/latest/DeveloperGuide/ConfiguringCaching.html 。
Distribution Settings | |
Price Class | 有三类,北美与欧洲、北美欧洲加亚太非、全球加速,不同类别应用到的 PoP 点不同,对应价格也不一样。 |
AWS WAF Web ACL | 如果配置了 WAF,可以在此关联,当然 CloudFront Distribution 创建完成后也可以在WAF Console关联。 |
Alternate Domain Names(CNAMEs) | (必须项,若使用自己域名) CloudFront Distribution 创建完成后,CloudFront 会提供一个以 cloudfront.net 结尾的域名,如果用户需要使用自己的域名的话,需要在此处填写待使用的域名。 |
SSL Certificate | 支持用户使用自己域名的证书,需要与上一栏域名匹配。可以使用 Amazon ACM 申请证书,需要注意的是,此时需要在 us-east-1 区域下的 ACM 申请才能应用到 CloudFront。 支持 dedicate IP 和 SNI 两种模式。 |
Logging | 访问日志,建议开启。 |
Bucket for Logs/ Log Prefix | 日志开启时,日志将存放的位置。开启日志有助于 client 访问行为分析,debug 等等。 |
点击创建后,来到 Distribution 的列表页面,可以看到 Status 的状态是“In Process”,大概10分钟左右该状态是“Deployed”时,则表示该分配创建完成,可以使用,并且可见 CloudFront 为其分配的域名。
3、添加源站
点击分配的 ID,可见当前分配的相关设置。
点击 Origin,可见当前的 Origin 配置,点击 Create Origin,可以添加源站。
此时我们添加一个 S3 桶为源站。
注意选择 S3 桶为源站时,会出现是否“Restrict Bucket Access”的选项,我们知道 S3 通过 ACL 和 Bucket Policy 控制存储桶的对象是否被公开访问,因此该 S3 存储桶需要允许 CloudFront 能够从 S3 存储桶拉取对象,这儿有两种方式,一个是该桶设置为公开访问桶,任何人可以直接从该桶下载;方式二是使用 OAI(Origin Access Identity),即该分配获取一个 OAI,并且在 S3 bucket policy 中的 principle 部分填写该 OAI,这样该 S3 存储桶将仅向该分配开放了相应的权限,而其他人无法直接从该存储桶下载资源。
建议选择“Yes, Update Bucket Policy”以避免 Bucket Policy 配置错误[2]。
4、添加 Behavior
同样进入分配后,在 Behavior 栏选择 Create Behavior。我们假定访问 jpg图片的请求,回源到前面创建的 S3 存储桶。
Path Pattern 中支持通配符,在此处配置路径模式,即当一个请求到达CloudFront POP 点,CloudFront 检查该请求的 URL 路径,并与 Behavior 中设置的进行匹配,按先匹配到的 Behavior 的配置执行对应的行为。
Origin 栏可以选择该分配中已添加的源站。
当拥有多个 Behavior 时,若路径模式中有重合,可以通过 Move Up/Down调整匹配的顺序,一旦匹配到将按该 Behavior 执行,不再去匹配其他 Behavior。优先级 Precedence 数字越小越优先匹配。
三、缓存优化
本节将介绍常见的 TTL 设置建议、动态加速,设置样例以及错误处理。
1、TTL 设置建议
CloudFront 在计算 Cache key 时会将请求的 URL 以及当前分配对应的Behavior 的配置(如是否转发 Header、Cookie、查询字符串)考虑在内,计算出唯一值。因此即使两次请求都是相同的 URL,如果两次请求的个别 Header 不一样,且该 Header 配置为了转发(Cached based on Selected Headers),则计算出的 Cache key 也不同,返回给客户端的内容自然也不同。因此配置转发的查询字符串、Cookie 及 Header 越少,Cache key 也将越少,缓存命中率就越高,带来了性能也越好。
对于用户内容在 PoP 点的缓存 TTL,可以使用源站设置的 Cache Control: max-age 的值,或者在 Behavior 中使用 Customized 设置 Minimum TTL,Maximum TTL、Default TTL(https://docs.thinkwithwp.com/zh_cn/AmazonCloudFront/latest/DeveloperGuide/Expiration.html )。
分类 | 静态内容,长期 | 静态内容,短期 | 动态内容 |
举例 | *.css, *.js, *.jpg, *.png 软件下载,媒体文件,媒体分片文件(HLS *.ts,*.m3u8)。 |
登录页,index.jsp,新闻,天气信息,HLS 直播 m3u8 文件。 | 变化的内容,不可缓存的内容。 |
建议 | 不变的内容可以设置较大的 TTL 值,使用版本号更新内容。 | 定期更新的内容设置低 TTL 值。TTL 到期后,CloudFront 回源校验源站内容是否发生变化。 | 经常变化的内容;按请求不同内容不同; 设置很低甚至0 TTL。 |
对于动态内容,动态加速场景,可以在源站设置:
Cache-Control: no-cache; max-age=0; No-store; private
或 Cache-Control: public; max-age=0;
若使用 CloudFront Behavior 中 Customize TTL,可以直接在‘Cache based on Selected Header’处选‘All’,然后 Minimum TTL,Maximum TTL,Default TTL 均设置为0.
对于 Cache-Control Header 设置样例:
静态资源 | 登录页 | 媒体分片 | 动态内容 | HLS 直播 |
*.css, *.js, 软件下载,更新包等 | Index.html | /*.ts | /*.m3u8 | |
Cache-Control: public; max-age=31536000 |
Cache-Control: no-cache=Set-Cookie; max-age=30 |
Cache-Control: public; max-age=31536000 |
Cache-Control: no-cache; max-age=0;No-store;private |
Cache-Control: public; max-age=2 |
2、错误处理
当源站不可用时,可以在 CloudFront 配置针对400,403,404,405,414,500,501,502,503,504等错误码的自定义响应页并修改返回给客户端的响应码。CloudFront 将周期性验证源站的可用性,并可在源站恢复前将当前缓存中的内容作为响应返回给客户端。
四、内容更新
当源站静态内容更新时,如何让客户端在 TTL 失效时间前即可拿到最新版本的内容是每一位开发者关心的问题,在 CloudFront 有两种方式。
1、版本号控制
当已发布的内容更新时,可在文件名或者路径中使用版本号进行区分,比如从 v1 到 v2,或者时间戳等可以区别同一对象两种版本的其他方法,同时应用测对资源链接指向新版本号的资源。
2、使用 Invalidation 使缓存中的文件失效
CloudFront 提供一个名为‘Invalidation’的功能,可以使文件在 TTL 失效时间到达前将文件从 PoP 点删除,使用该功能可以快速的在文件名不变的前提下将文件更新。
Invalidation 支持指定单个文件或者以*通配符结尾的路径。限制及费用见https://docs.thinkwithwp.com/zh_cn/AmazonCloudFront/latest/DeveloperGuide/Invalidation.html
五、监控与日志
CloudFront 提供多种报告供用户了解自己分配的使用率等情况,您可以使用 CloudWatch API 获取分配的相应监控指标,需要注意的是,使用 CloudWatch API 时 region 应设置为 us-east-1。
CloudFront 报告提供按天或按小时的请求数、数据传输、HTTP Status Code、Top50 访问的对象,使用率以及按设备、浏览器、操作系统、客户端位置等指标的报告,同时可以配置 CloudWatch 警报,对关键指标数据进行监控(请求数、已下载字节、已上传字节、总错误率、4xx错误率、5xx错误率),一旦超过正常阈值,运维人员可第一时间得到告警。
尽管 CloudFront 提供了多维度的报告,但可能仍不能满足用户的多维度分析的需求。因此推荐这类用户对 CloudFront 日志进行分析,当用户开启 CloudFront 分配日志后,日志将会上传到指定的 S3 存储桶,通过分析日志可以了解有关该分配的更多的客户端请求行为,有助于做运营分析或者 debug。关于日志字段解释见https://docs.thinkwithwp.com/zh_cn/AmazonCloudFront/latest/DeveloperGuide/AccessLogs.html 用户可以使用 Amazon EMR 或者无服务器交互式查询服务Amazon Athena轻松的使用标准 SQL 直接在 S3 中分析数据,并与 Amazon QuickSight 集成,轻松实现数据可视化。
使用 Amazon Athena 查询 Amazon CloudFront 日志方式见https://docs.thinkwithwp.com/zh_cn/athena/latest/ug/cloudfront-logs.html
使用 Amazon EMR 分析 CloudFront 日志可见参考资料8。
六、合规与安全
CloudFront 目前已经获得 PCI DSS 合规,GDPR(https://amazonaws-china.com/compliance/gdpr-center/service-capabilities/ )、HIPPA、SOC 以及 ISO 9001, 27001, 27017, 27018 等合规认证。
同时开启 CloudTrail,用户帐号下所有的 CloudFront API 调用记录将均被CloudTrail 记录,便于用户后期审计。
下面我们将从4个方面进行介绍 CloudFront 如何保证您的内容安全。
1、回源保护
我们可以将源站设置为仅允许 CloudFront 访问,而拒绝客户端的直接回源。
当源站为 ELB/EC2 时:
(1)ELB/EC2 的安全组仅对 CloudFront 节点 IP 开放对应的端口(80/443),CloudFront 节点服务器的 IP 地址范围见:
(2)在 CloudFront Origin 设置时,添加自定义 Header 字段及值,源站对请求中的字段检查,若不含有该 Header 字段及值,则返回错误码。
(3)回源 HTTPS
回源支持 TLSv1.1、TLSv1.2 安全协议以及 RSA,ECDSA 两类密码算法。
当源站为 S3 存储桶时:
在 S3 存储桶策略中应用 OAI,仅允许带该 OAI 的 CloudFront 分配从存储桶中获取内容。
2、传输安全
CloudFront 支持客户端到 PoP 点使用 HTTPS 请求,CloudFront 为每个分配生成的域名支持 HTTPS 请求,并支持用户上传自己从可信 CA 购买的证书。用户可以在 Amazon ACM 服务免费申请自己域名的证书,需要注意的是,需要在 us-east-1 区的 ACM 服务申请,才能应用到 CloudFront 的分配。
对于用户域名证书,CloudFront 支持专属 IP 和 SNI 两种方式。
3、内容保护
(1)签名 URL、签名 Cookie
针对有些内容限制访问的情景,如仅允许付费用户或者授权用户访问的内容,我们可以通过签名 URL 或签名 Cookie 的方式提供内容的私有化访问。文档中已有非常详细的说明,在此不再展开,具体方式见:https://docs.thinkwithwp.com/zh_cn/AmazonCloudFront/latest/DeveloperGuide/PrivateContent.html 另外也可见参考资料[3]。
(2)Field-Level Encryption 字段级加密
2017年12月份,CloudFront 推出了该功能,使用该功能,可以进一步增强敏感数据 (如信用卡号码或个人身份信息) 的安全性。在将 POST 请求转发到您的源站之前,CloudFront 的字段级加密使用特定于字段的加密密钥 (由用户提供) 对 HTTPS 表单中的敏感数据进行进一步加密。这可确保敏感数据只能被应用程序堆栈中的某些组件或服务解密和查看。
(3)Geo 限制
CloudFront 提供了基于地理位置访问限制的功能,用户可以通过设置白名单或者黑名单的方式,允许或禁止某个国家或地区对自己分配的访问。
4、与 AWS WAF、Shield 集成
AWS WAF 是一款 Web 应用程序防火墙,帮助保护您的 Web 应用程序免受常见 Web 漏洞的攻击[5]。AWS Shield 是一种托管式分布式拒绝服务 (DDoS)防护服务,可以保护在 AWS 上运行的防护应用程序 [7]。
用户可以在创建 CloudFront 分配时关联已创建的 WAF,或者在 WAF Console 创建完 WAF 规则后与 CloudFront 分配关联。
七、可编程 CDN
AWS在2017年7月正式推出了 Lambda@Edge,借助 Lambda@Edge,用户可以轻松在 AWS 的全球基础设施上运行代码,从而以最低的延迟响应最终用户。代码可以由 Amazon CloudFront 事件触发,例如源服务器和浏览者之间的内容请求或响应。您只需将 Node.js代码上传到 AWS Lambda,Lambda 就能在靠近最终用户的 AWS 站点实现高可用性,提供复制、路由和扩展代码所需的一切。
我们将在下一篇中对 Lambda@Edge进行讲解与使用案例分享,感兴趣的读者可以查看官方文档进一步的了解:https://docs.thinkwithwp.com/zh_cn/AmazonCloudFront/latest/DeveloperGuide/lambda-at-the-edge.html
参考资料
[1]开发人员指南:https://docs.thinkwithwp.com/zh_cn/AmazonCloudFront/latest/DeveloperGuide/Introduction.html
[2] Amazon CloudFront 常见错误配置及解决方法: https://amazonaws-china.com/cn/blogs/china/cloudfront-errors-solutions/
[3] 使用 Amazon CloudFront 签名 URL+S3 实现私有内容发布https://amazonaws-china.com/cn/blogs/china/amazon-cloudfront-signature-url-s3/
[5] AWS WAF https://amazonaws-china.com/cn/waf/?nc2=h_m1
[6] AWS Certificate Manager https://amazonaws-china.com/cn/certificate-manager/?nc2=h_m1
[7] AWS Shield https://amazonaws-china.com/cn/shield/?nc2=h_m1
[8] 手把手教你使用 Amazon EMR 进行交互式数据查询https://amazonaws-china.com/cn/blogs/china/amazon-emr/
本篇作者