如何将 S3 用作静态网页和 EC2 作为 REST API 一起使用? (AWS)

Posted

技术标签:

【中文标题】如何将 S3 用作静态网页和 EC2 作为 REST API 一起使用? (AWS)【英文标题】:How to use S3 as static web page and EC2 as REST API for it together? (AWS) 【发布时间】:2013-06-22 05:26:42 【问题描述】:

借助 AWS 服务,我们让 Web 应用程序从 S3 存储桶运行,并通过负载均衡器(在 EC2 实例上运行的一组 Node.js 应用程序)通过 REST API 访问数据。

目前我们指定的网址如下:

API 负载均衡器:      api.somedomain.com S3 上的静态 Web 应用:       somedomain.com

但是这种设置给我们带来了一系列问题,因为请求是这种设置的 CORS。我们可以使用特殊标头解决 CORS,但这不适用于所有浏览器。

我们想要实现的是在同一个域上使用不同的路径运行 API:

API 负载均衡器:           somedomain.com/api S3 上的静态 Web 应用:      somedomain.com

其中一个想法是将 API 负载均衡器附加到 CDN,如果查询来自“/api/*”路径,则将所有请求转发到负载均衡器。但这不起作用,因为我们的 API 不仅使用 HEAD 和 GET 请求,还使用 ​​POST、PUT、DELETE。

另一个想法是使用第二个 EC2 实例而不是 S3 存储桶来托管网站(使用一些 Web 服务器,如 nginx 或 apache)。但是,当一切都已经就绪(S3 静态内容托管)时,这会产生过多的开销。此外,如果使用此方案,我们将无法获得 Amazon CloudFront 性能的所有优势。

那么,您能否推荐如何组合负载均衡器和 S3,以便它们在同一个域上运行,但路径不同? (somedomain.com/api 上的 API 和 somedomain.com 上的 Web 应用)

谢谢!

【问题讨论】:

【参考方案1】:

您不能拥有具有相同主机名的 EC2 实例和 S3 存储桶。考虑当 Web 浏览器向该主机名发出请求时会发生什么。 DNS 将其解析为一个 IP 地址(或多个地址),并将请求的数据包传递到该地址。该地址要么终止于 EC2 实例,要么终止于 S3 存储桶,而不是两者。

据我了解,您在 S3 上托管了静态网页,其中包含向 EC2 实例发出各种 HTTP 请求的 javascript 代码。如果 S3 网页与 EC2 实例位于不同的主机上,那么同源策略将阻止浏览器甚至尝试某些请求。

我能看到的唯一解决方案是:

向 EC2 实例发出所有请求,它会在请求网页时获取 S3 内容并将其传送到浏览器。 让您的 JavaScript 使用 iframe 并将网页中的 document.domain 更改为共同的父源。例如,如果您的网页位于 www.example.com,而您的 EC2 实例位于 api.example.com,则 JavaScript 会将 document.domain 更改为仅 example.com,并且浏览器将允许来自 www.example.com 的 iframe 与 @987654328 通信@。 咬紧牙关,使用 CORS。这真的不难,it's supported 在所有远程最近的浏览器中(IE 8 和 9 都会这样做,但不是以标准方式)。

第一种方法不好,因为在这种情况下您几乎完全不使用 S3。

第二种情况对你来说应该没问题。它应该适用于任何浏览器,因为它不是真正的 CORS。所以不需要 CORS 标头。但这很棘手。

第三种,CORS,方法应该没问题。您的 EC2 实例只需返回正确的标头,告诉 S3 存储桶中的网页它们与 EC2 实例通信是安全的。

【讨论】:

谢谢你这么好的解释!可能我们会采用 CORS 方法并为 IE 创建解决方法。 很高兴。如果这解决了您的问题,请将其标记为已回答。【参考方案2】:

只是想在答案中添加一点,如果我们使用 CORS 方法并且预检请求会增加服务器和网络带宽的开销,我们甚至可以考虑将标头“Access-Control-Max-Age”添加到CORS 响应

Access-Control-Max-Age

【讨论】:

以上是关于如何将 S3 用作静态网页和 EC2 作为 REST API 一起使用? (AWS)的主要内容,如果未能解决你的问题,请参考以下文章

AWS攻略——使用S3托管静态网页

PowerShell AWS 自动化管理

如何使用我的 EC2 弹性 IP 地址作为代理服务器?

AWS Elastic beanstalk 和 S3 静态 Web 中的 CORS 策略

仅限注册用户访问 Amazon S3 静态网页

如何将 S3 存储桶挂载到 EC2 实例并使用 PHP 写入?