利用 Amazon Lambda@edge 构建多区域就近访问应用

Amazon Simple Storage Service (S3)
Amazon CloudFront
Amazon Lambda
0
0
## **摘要** 本文将介绍如何使用 Amazon Lambda\@edge 和 [Amazon CloudFront](https://aws.amazon.com/cn/cloudfront/?trk=cndc-detail) 构建多区域就近访问的应用,从而提高用户体验。与传统的多区域部署方案不同的是,该方案通过 Lambda\@edge 在 Origin Request 阶段修改请求的特性,动态地修改源站的域名,从而实现就近访问的目的。 ## **方案场景介绍** 某个 Web 应用会部署在美西和新加坡,静态资源利用 S3 部署。美西和新加坡的用户通过 S3 读取图片/文本等静态信息。目前 S3 部署在新加坡,虽然 CF 可以缓存静态资源,但资源的首次加载或缓存过期、仍旧会增加美西用户的访问耗时。希望提供方案解决多个 Region 用户的访问体验。 ## **解决方案** 可以在美西和新加坡 2 个区域均部署 S3 存储桶,当客户端请求访问 CloudFront 时未命中时后访问 Origin 源站时,利用 Lambda\@edge 在 Origin Request 阶段可以对 Request 请求进行 Domain 和 Host 的修改的特性,动态去修改源站的域名从而达到就近访问的目的,提高用户体验。 ## **架构方案** ![image.png](https://dev-media.amazoncloud.cn/e33ae860828744568fe2f6e76684c515_image.png "image.png") ### **工作流程** **前置工作** 1. 在 CloudFront 的 Behavior 上设置 Original Request 关联 Lambda\@edge,当请求经过 Original Request 时,通过 Lambda\@edge 进行修改。 ![image.png](https://dev-media.amazoncloud.cn/2fefa3f85a2247118e232db657c2291c_image.png "image.png") 2. 在美西和新加坡上创建 S3 存储桶,并在 CloudFront 上以 S3 为目标创建源。 ![image.png](https://dev-media.amazoncloud.cn/b58025abb2424ca3a2adc0f0c9f0ff87_image.png "image.png") 注意(**可选**):为了安全访问 S3 存储桶(不打开公开访问),可以通过 Cloudfront 的 OAC/OAI 身份验证方式来访问 S3,建议使用 OAC(Origin Access Control),因为它支持: - Amazon Website Service 区域中的所有 [Amazon S3](https://aws.amazon.com/cn/s3/?trk=cndc-detail) 存储桶,包括 2022 年 12 月之后推出的选择加入区域。 - [Amazon S3](https://aws.amazon.com/cn/s3/?trk=cndc-detail) 使用 Amazon KMS 的服务器端加密(SSE-KMS)。 - 对 [Amazon S3](https://aws.amazon.com/cn/s3/?trk=cndc-detail) 的动态请求( PUT 和 DELETE )。 以下为 OAC 的配置(**可选**) **在 S3 的 Policy 上配置只允许 OAC 访问** ```js { "Version": "2012-10-17", "Statement": { "Sid": "AllowCloudFrontServicePrincipalReadOnly", "Effect": "Allow", "Principal": { "Service": "cloudfront.amazonaws.com" }, "Action": "s3:GetObject", "Resource": "arn:aws:s3:::<S3 bucket name>/*", "Condition": { "StringEquals": { "AWS:SourceArn": "arn:aws:cloudfront::<AWS 账户 ID>:distribution/<CloudFront distribution ID>" } } } } ``` **在 CloudFront 的 Origin 上开启 OAC** ![image.png](https://dev-media.amazoncloud.cn/75ee17d268cf4a91a8687d87f6a8aace_image.png "image.png") ![image.png](https://dev-media.amazoncloud.cn/a7fe397426f74f5997ae7dfa6bd7a147_image.png "image.png") 选择“签署请求”后,CloudFront 将使用 SigV4 签署每个发送到 S3 的 Request。它将包含身份验证信息、日期、动作、和参数等。以 Authorization head 的形式发送给 S3,S3 接受到信息后,通过密钥对信息进行签名然后进行比对。通过后处理请求。 最后,创建 Origin group,并将 CloudFront 的 behavior 上的源配置改为 Origin Group。 ![image.png](https://dev-media.amazoncloud.cn/8a9bb4137e764494b0ca1b607a1f3d60_image.png "image.png") ![image.png](https://dev-media.amazoncloud.cn/1116574f38d241a994e258ed193786b2_image.png "image.png") 具体流程 1. 客户端发送请求至 CloudFront。 2. 请求未命中缓存时,在 Edge Location 上,CloudFront 在 Origin Request 调用 Lambda@edge。 3. Lambda@edge 读取当前 Region 的 Code,识别出是 us-west2 或者是 ap-southeast-1,并根据代码里预设的 map。找到该 region 对应的 S3 的地址(注意:也可以基于 route53 的延迟策略来找到最合适的 S3 存储桶位置,参考资料里会有此种方法的链接)。 4. Lambda@edge 修改 Request 的域名地址,Request 请求会路由到对应 S3 存储桶。 5. 返回从存储桶获取的对象到客户端。 Lambda@edge 代码具体如下: ```js import json us_bucket = "amazon-cloudfront-secure-static-site-s3bucketroot-21aorhazvsj1.s3.amazonaws.com" ap_bucket = "amazon-cloudfront-sin-s3root.s3.ap-southeast-1.amazonaws.com" default_bucket = "amazon-cloudfront-secure-static-site-s3bucketroot-21aorhazvsj1.s3.amazonaws.com" s3Mapping = { "us-east-1": us_bucket, "us-east-2": us_bucket, "eu-central-1": us_bucket, "eu-west-2": us_bucket, "ap-southeast-1": ap_bucket } def lambda_handler(event, context): request = event['Records'][0]['cf']['request'] defaultRequest = event['Records'][0]['cf']['request'] print(request['origin']) print('req='+json.dumps(request)) try: originKey = list(request['origin'].keys())[0] if originKey != 's3' return request currentRegion = context.invoked_function_arn.split(':')[3] print("aaa="+currentRegion) domainName = s3Mapping.get(currentRegion, default_bucket) request['origin']['s3']['domainName'] = domainName request['headers']['host'] = [{'key': 'host', 'value': domainName}] return request except TypeError: print('modify s3 domain failure') return defaultRequest ``` ## **总结** 本文介绍了如何利用 Lambda\@edge 构建多区域就近访问应用,从而减少回源延迟,提升性能。通过在 CloudFront 中配置多个区域的源站,并利用 Lambda\@edge 在 Origin Request 阶段修改请求的特性,动态地修改源站的域名,可以实现就近访问的目的。此外,这个方案还具有以下几个优势: * **高可用性**:通过在多个区域部署源站和 CloudFront,可以实现高可用性,确保即使某个区域出现问题,应用仍然可以正常访问。 * **高性能**:通过将静态资源分发到多个区域,并在边缘节点上缓存最新的资源,并在下一次请求时直接从缓存中获取,可以减少回源的次数和延迟,从而提高性能。 * **通用性**:除了对 S3 源站进行加速,在 API Gateway 等服务中也可以应用类似的方案,实现跨区域访问降低延迟的目的。 通过利用 Lambda\@edge 和 CloudFront 构建多区域就近访问应用,可以提高用户体验,减少回源延迟,提升性能,同时还具有高可用性和通用性,是一个非常值得尝试的解决方案。 ## **参考资料** OAC: [Amazon CloudFront](https://aws.amazon.com/cn/cloudfront/?trk=cndc-detail) introduces Origin Access Control (OAC) | Networking https://aws.amazon.com/cn/blogs/networking-and-content-delivery/amazon-cloudfront-introduces-origin-access-control-oac/?trk=cndc-detail SignV4: https://docs.aws.amazon.com/IAM/latest/UserGuide/signing-elements.html?trk=cndc-detail 基于 Route53 的延迟策略动态修改 API gateway: https://aws.amazon.com/cn/blogs/china/build-nft-offering-systems-with-cloud-native-components/?trk=cndc-detail ![开发者尾巴.gif](https://dev-media.amazoncloud.cn/0754daee74264fbbaa06c671402a12e2_%E5%BC%80%E5%8F%91%E8%80%85%E5%B0%BE%E5%B7%B4.gif "开发者尾巴.gif")
目录
亚马逊云科技解决方案 基于行业客户应用场景及技术领域的解决方案
联系亚马逊云科技专家
亚马逊云科技解决方案
基于行业客户应用场景及技术领域的解决方案
联系专家
0
目录
关闭