Amazon CloudFront 部署小指南(五)- 使用 Amazon 边缘技术优化游戏内资源更新发布

内容分发网络 CDN
Amazon CloudFront
游戏
游戏行业解决方案
0
0
## **内容简介** 游戏内资源包括玩家的装备/弹药/材料等素材,对游戏内资源的发布和更新是游戏运营商的一个常规业务流程,使用频率会十分高,所以游戏运营商希望该流程可以做到简化和可控。针对这个需求,我们设计了 3 个架构,面向游戏内资源更新发布的 3 个典型场景,来优化游戏内资源更新发布流程。3 个场景分别为: * 游戏内资源灰度更新 * 游戏内资源分渠道投放 * 游戏内资源黑白名单 该 3 个架构围绕亚马逊云科技 [Amazon CloudFront](https://aws.amazon.com/cn/cloudfront/?trk=cndc-detail) 服务 — CloudFront 边缘计算服务 — WAF 服务展开实现。 ## **场景一:游戏内资源灰度更新** 游戏在运营过程中会有资源更新的需求,用一个简单模型来描述:老的资源 A 需要替换成成新的资源 B。不过这里有一个痛点,B 资源在推广到所有 CDN 之前,需要内部或者小范围确认资源的正确性。因此需要一种方式来保证 B 资源哪怕在源端更新了,只有受限的访问;大部分的玩家还是访问的还是 CDN 缓存内的资源 A。等 B 资源验证通过后,才会通过 CDN 刷新推广到所有的节点。 这个需求实现的难点在于:在客户端不做任何修改的情况下,使用相同的 URL 将少量用户请求引导资源 B;资源 A 和资源 B 不能共享缓存,以免引起资源访问冲突。我们采用 CloudFront Continuous Deployment 来实现这个需求: ![image.png](https://dev-media.amazoncloud.cn/015b1e713b7642d1a3741924629b1c65_image.png "image.png") 配置步骤如下: 1. 创建 Staging Distribution 2. 功能验证\ 3. 调度流量\ 4. 正式上线 CloudFront 持续部署功能在实现上比较直观,用户可以通过控制请求配比方式实现金丝雀式的资源更新;在成本上相比于部署 CloudFront 边缘脚本 CloudFront Function 会更低一些。 ### **创建 Staging Distribution** - 在 CloudFront 生产 distribution 下,点击“create staging distribution” ![image.png](https://dev-media.amazoncloud.cn/f56cd63c368b44579f05d098f1a953a8_image.png "image.png") - 可以输入 Staging Distribution 的描述,然后点击“Next” ![image.png](https://dev-media.amazoncloud.cn/e1757cfb2a904786a80d862889d5e1e8_image.png "image.png") - 创建一个新的源站。用户可以对应创建一个新的源站部署资源 B(使用相同目录结构);也可以在现有源站上将资源 B 部署到另外一个目录中,然后创建新的 Host 容器,并且在 DNS 服务器上创建指向新的 Host 容器的记录 ![image.png](https://dev-media.amazoncloud.cn/59045ca6b9c74f77a23406d235baf3b9_image.png "image.png") ![image.png](https://dev-media.amazoncloud.cn/7fa91203dca5402d878a032733b72443_image.png "image.png") *注意:我们在新的 origin 中改写了 origin path,使得客户端无需做变更。 - 流量配置选择“header-based ”比例先选择为 0 ![image.png](https://dev-media.amazoncloud.cn/c7c24ea8fa5a493da8295d56908c5e61_image.png "image.png") - 创建 Staging Distribution ![image.png](https://dev-media.amazoncloud.cn/dfcca44476584f7d8ad15e83b88773f8_image.png "image.png") - 至此 Staging Distribution 创建完毕,等待 10 分钟左右部署完毕 ### **功能验证** 可以使用命令行工具 curl 进行验证: resource_b 下载: ```js curl -H 'aws-cf-cd-resource:b' -v -o /dev/null 'https://www.company.com/resource' ``` resource_a 下载: ```js curl -H -v -o /dev/null 'https://www.company.com/resource' ``` 通过观察下载的文件特征如字节数或者 ETAG 判断是否下载了不同内容的资源对象。 ### **调度流量** - 点击‘Edit Policy’ ![image.png](https://dev-media.amazoncloud.cn/1338c275bdd44693a5df9970b24762a0_image.png "image.png") 在弹出窗口中修改流量调度策略,调度 1%的流量进行灰度发布 ![image.png](https://dev-media.amazoncloud.cn/779b27d4b1594b63bd411ec5d3e23a49_image.png "image.png") ![image.png](https://dev-media.amazoncloud.cn/659d095121ce493086239d1422d0ac8e_image.png "image.png") ### **正式上线** 用户在源站正式将 Resource B 覆盖 Resource A 后,需要在 CloudFront 上进行缓存刷新,并删除 Staging Distribution ![image.png](https://dev-media.amazoncloud.cn/ec269b8c83bf43bf86f30703afdb40ba_image.png "image.png") ## **场景二:游戏内资源分渠道投放** 游戏在运营过程中会有针对不同渠道投放不同资源的需求,用一个简单模型描述:对于资源 A 和资源 B,从不同渠道进来的玩家会看到不同的资源。这里的痛点为,客户需要针对头部某个字段或者 url 中某个关键字快速匹配对应的资源。 ### **内容概述** 在这个方案构建中,我们将利用到 CloudFront Function 检查请求头部的字段,并根据匹配到的字段进行回源 URL Path 替换,此方案的好处在于,URL Path Rewrite 对于最终用户是无感知的,符合不同渠道进来的玩家对于某个相同的资源(比如资源 A),回源获取到的内容将会不同。 配置步骤如下: 1. 创建 CloudFront Function 2. 创建 Behavior 匹配存在不同渠道的 URL Path 3. 实验验证及结论 ### **创建 CloudFront Function** 在此需求中,不同渠道的所获取的内容不同,意味着在源站侧(如 S3)上的路径信息不同,如用户请求的文件路径统一为/sample.file,而不同渠道在源服务上所对应的文件真实路径为/a_vendor/sapme.file  或是/b_vendor/sample.file,我们可以根据不同渠道(携带不同的请求头信息),来对请求头值进行提取,并进行回源 URL 替换,具体 CloudFront Function 参考代码如下: ```js function handler(event) { // 获取请求头 var request = event.request; var headers = event.request.headers; var originUrl = event.request.uri; // 检查 x-vendor-type 请求头是否存在 if (headers['x-vendor-type']) { var targetObject = headers['x-vendor-type'].value //修改回源 URL Path event.request.uri = '/' + targetObject + originUrl; } return request; } ``` *注:此处 header 的值不直接取而是先进行判断的原因是,某些客户端可能不会携带 x-vendor-type 这个头,如果不增加判断直接取值,那么 header 不存在的情况将会导致 CloudFront Function 报错,在您部署代码时也可以进行相应的考虑。 CloudFront Function 代码保存完毕后,我们可以在调试界面进行调试并观察效果: ![image.png](https://dev-media.amazoncloud.cn/62d474019f9e41c0ab10b201940b57ce_image.png "image.png") 提交调试信息后,可以看到回源路径成功被修改,如下图: ![image.png](https://dev-media.amazoncloud.cn/2727f1e8ab3c4fd4954028bb7ac9f324_image.png "image.png") 调试无误后对 CloudFront 代码进行部署: ![image.png](https://dev-media.amazoncloud.cn/a82654556b254398af800ceed3f83f4f_image.png "image.png") ### **创建 Behavior 匹配存在不同渠道的 URL Path** 此处,为了方便展示效果,我们在 CloudFront 中的 Behavior 根据需求,进行路径匹配,此处的匹配以“/abtest-demo\*”进行展示。 ![image.png](https://dev-media.amazoncloud.cn/616853f43bad4f94846bfabedf307d3a_image.png "image.png") 由于此处仅做 URL 改写,不同渠道针对相同 URL 将会拿到不同的内容,此处您还需要在 Behavior 中针对不同的请求头进行缓存上的区分,您可以自定义 Cache Policy,并将 x-vendor-object 请求头作为 Cache Key 的一部分,以进行缓存区分: ![image.png](https://dev-media.amazoncloud.cn/6153028333e04fe6a5359157d72c6283_image.png "image.png") 自定义 Cache Policy 后,在 Behavior 中进行应用: ![image.png](https://dev-media.amazoncloud.cn/95df35691288401ca45e02c2fe53cba1_image.png "image.png") 在 origin policy 中,需要将自定义的请求头进行透传,以便 CloudFront Function 可以进行请求头的检查,您可以自定义 Origin Policy,也可以选择 AllViewer 将自定义请求头进行透传。 由于该改写逻辑运行的 event type 是 Viewer Request,您需要在 Behavior 定义中在正确的 event 中应用上述部署的 CloudFront Function 逻辑。 ![image.png](https://dev-media.amazoncloud.cn/50f311369af043828a876f235afd204d_image.png "image.png") ### **实验验证及结论** 在源服务侧,我们分别针对 A 和 B 渠道存放不同版本的文件,以供调试,此处示例文件对应关系如下: 渠道 A :a_vendor 渠道 B :b_vendor 携带对应的请求头,多次请求后并观测效果: ```js //在请求头中携带 A 渠道特殊标识,回源真实路径为/a_vendor/example.file % curl -v http://cloudfront-function.xxxxxxx.com/example.file -H 'x-vendor-type: a_vendor' 2>&1 | egrep 'X-Cache|This content' < X-Cache: Hit from cloudfront This content is for a vendor! //在请求头中携带 B 渠道特殊标识,回源真实路径为/a_vendor/example.file % curl -v http://cloudfront-function.xxxxxxx.com/example.file -H 'x-vendor-type: b_vendor' 2>&1 | egrep 'X-Cache|This content' < X-Cache: Hit from cloudfront This content is for b vendor! //在请求头中不携带渠道特殊标识,回源真实路径为/example.file % curl -v http://cloudfront-function.xxxxxxx.com/example.file 2>&1 | egrep 'X-Cache|This content' < X-Cache: Hit from cloudfront This content is for general usage without vendor! ``` 通过以上的演示,我们成功的验证了以下三个设置需求: 1. 您可以清楚的看到,针对相同的 URL path   为/example.file,通过不同的 x-vendor-type 指定内容,我们成功的改写了回源 URL,并根据获取到了不同渠道所对应的内容。 2. 如果客户端不是通过渠道发起的请求,不携带特殊标识头,也可以成功拿到内容。 3. 在命中缓存的情况下,由于 Cache Policy 将 x-vendor-type 作为缓存的一部分,在 URL 相同的情况下,请求依然可以按照预期命中到各自对应缓存。 ## **场景三:游戏内资源黑白名单** ### **场景描述** 游戏在运营过程中会有不同玩家有不同访问行为的需求,用一个简单模型描述:对于玩家 A 需要放在白名单中,对于玩家 B 需要放置在黑名单中。 用一个更具体的场景描述:假设需要通过 WAF web ACL 去匹配出 user-agent 中包含** “PostmanRuntime/x.xx.x” **的请求,并且拒绝该请求的访问。 对于上述场景,可以通过检查请求 header 重的 User-Agent 来实现。对于请求来说,通常会经过几个链路:客户端→公网→Amazon CDN 接入点→ 原站。那么将检查 header 的压力放在 CDN 处是比较好的选择,可以有效的减少原站的压力。在 CDN 侧检测也有几种方式。最先想到的是在 CDN 上用 edge function/lambda 来实现。这里会带来的挑战是需要是维护代码。另外一种比较好的方式是利用 WAF 对于规则来进行检查。WAF 在配置 Web ACL 的时候,需要配置允许和阻止的条件。通常包含的条件有: * 请求是否表现为包含恶意脚本允许或阻止请求 → **跨站点脚本匹配条件** * 请求源自的 IP 地址允许或阻止请求 →**IP 匹配条件** * 请求源自的国家/地区允许或阻止请求 →  **地理匹配条件** * 请求是否超过指定长度允许或阻止请求 →** 大小约束条件** * 请求是否表现为包含恶意 SQL 代码允许或阻止请求 →**SQL 注入匹配条件** * 出现在请求中的字符串允许或阻止请求 →**字符串匹配条件** * 出现在请求中的正则表达式模式允许或阻止请求 → **正则表达式匹配条件** 默认情况下,Amazon WAF 过滤器不检查 HTTP 请求参数是否存在。要检查 HTTP 请求参数是否存在,可以采取下面两种自定义规则中的任意一种: * 使用字符串匹配规则 * 使用正则表达式匹配规则 ### **环境准备** 在测试之前我们需要做如下步骤: 1. 进入 Amazon Website Service Console 界面,选择 WAF 服务,然后在左边导航栏选择 WAF ACLs。 2. 创建一个 Rule,根据业务需求命名。然后保护的对象可以是 CDN 也可以是负载均衡器之类的对外服务。资源部分可以现在就填写,也可以等待 Rule 创建完毕后再绑定。 ![image.png](https://dev-media.amazoncloud.cn/e2034e75eba14f2997f45e6c3f54e39b_image.png "image.png") 3. 完成 Web ACL 的信息录入之后,在第二部我们选择自定义规则。 ![image.png](https://dev-media.amazoncloud.cn/6f2d6c0e7ddb4a2dae1143e5183e9d93_image.png "image.png") 4. 在自定义规则中,我们选择 Rule Builder。并且设置好 Rule 的名字。 5. 在 inspect 中,选择 All headers,header content 选择默认的所有 keys and values,当然可以根据业务需求只监控特定的 header 和 content。 ![image.png](https://dev-media.amazoncloud.cn/9573a5d4634045ad87eeeafd299f1e0b_image.png "image.png") ### **字符串匹配规则** 对于字符串匹配规则,Web ACL 提供如下几种方式: * Exact matches string:严格匹配字符串 * Start swith string:匹配字符串开头 * Ends with string:匹配字符串结尾 * Contains string/word:包含某个字符串 根据需求,使用 Start with string 即可,设置如下: ![image.png](https://dev-media.amazoncloud.cn/f07991e6e76c4c37b52a44367b995123_image.png "image.png") ### **正确表达式匹配规则** 正则表达式规则,Web ACL 提供两种匹配方式: - regex pattern set:正则表达式集合,可以提前设置,在面板中选取即可 - regular expression:正则表达式,临时设置 这里我们选择第二种方式,其设置参考如下 ![image.png](https://dev-media.amazoncloud.cn/096a7a26901840b39bed0f73d6516f3b_image.png "image.png") ### **最终规则的 Json 格式参考** ```js { "Name": "StringMatch", "Priority": 0, "Action": { "Block": {} }, "VisibilityConfig": { "SampledRequestsEnabled": true, "CloudWatchMetricsEnabled": true, "MetricName": "StringMatch" }, "Statement": { "OrStatement": { "Statements": [ { "ByteMatchStatement": { "FieldToMatch": { "Headers": { "MatchScope": "ALL", "MatchPattern": { "All": {} }, "OversizeHandling": "CONTINUE" } }, "PositionalConstraint": "STARTS_WITH", "SearchString": "PostmanRuntime", "TextTransformations": [ { "Type": "NONE", "Priority": 0 } ] } }, { "RegexMatchStatement": { "FieldToMatch": { "Headers": { "MatchScope": "ALL", "MatchPattern": { "All": {} }, "OversizeHandling": "CONTINUE" } }, "TextTransformations": [ { "Type": "NONE", "Priority": 0 } ], "RegexString": "/PostmanRuntime[ \\\\/]+([0-9\\\\.]+)/gi" } } ] } } } ``` ### **规则测试** 规则建立好后,我们需要将它运用在保护的资源中。假设源站是一个网站,前面为一个 CDN,它只是返回一个 text=ok。 测试如下(User-Agent 的值为 **X-UnrealEngine-Agent):** ![image.png](https://dev-media.amazoncloud.cn/397b95a173b9400cbfe3afac59057912_image.png "image.png") 当请求头,包含了  **PostmanRuntime/x.xx.x**,可以看到请求被 block ![image.png](https://dev-media.amazoncloud.cn/e9e9d1406862455497a0e1ea0d392363_image.png "image.png") 在后台的界面中,也可以统计到过去 5 分钟的 WAF 的表现情况 ![image.png](https://dev-media.amazoncloud.cn/c846a092c53445c29294dcd52b87eacb_image.png "image.png") 可以通过以上实验,WAF 对于 CDN 的保护提供了十分灵活的配置规则,可以满足各种不同场景的需求。更进一步,它解放了 CDN 去做规则匹配和检查的压力,让 CDN 去做它更擅长的业务。 ## **总结** 通过亚马逊云科技 CloudFront 服务 — CloudFront 边缘计算服务 — WAF 服务,游戏运营商可以在不改动客户端的情况下,完成游戏内资源在预设条件下的更新发布,提高了业务部署的敏捷性和简易性。 ## **亚马逊云科技 CloudFront 部署小指南系列文章** - [Amazon CloudFront 部署小指南(一)- 快速构建 CDN 内容分发](https://dev.amazoncloud.cn/column/article/64ac21d60f1a002f2aff1c2c) - [Amazon CloudFront 部署小指南 (二)- 进阶部署:](https://dev.amazoncloud.cn/column/article/64b513651da59862086bbddd) - [Amazon CloudFront 部署小指南 (三)- 持续部署:](https://dev.amazoncloud.cn/column/article/64bf7d47d6513d1ed1129be5) - [Amazon CloudFront 部署小指南(四)- CloudFront Function 基础与诊断:](https://dev.amazoncloud.cn/column/article/64d074085306fa4a7fa4becf) - [Amazon CloudFront 部署小指南(六)- Lambda\\@Edge 基础与诊断](https://aws.amazon.com/cn/blogs/china/amazon-cloudfront-deployment-handbook-part-six/) ![开发者尾巴.gif](https://dev-media.amazoncloud.cn/d962f0dbb8d84a8a9b9b5dd02f349d6f_%E5%BC%80%E5%8F%91%E8%80%85%E5%B0%BE%E5%B7%B4.gif "开发者尾巴.gif")
目录
亚马逊云科技解决方案 基于行业客户应用场景及技术领域的解决方案
联系亚马逊云科技专家
亚马逊云科技解决方案
基于行业客户应用场景及技术领域的解决方案
联系专家
0
目录
关闭