使用Amazon S3和Cloudfront智能缓存webapges

Pau*_*lor 7 java amazon-s3 amazon-web-services amazon-cloudfront

我有一个网站(在Elastic Beanstalk上的Tomcat中运行),可以生成艺术家唱片(一个艺术家的单页).这可能是资源密集型的,因此艺术家页面在一个月内不会发生变化,因此我在其前面放置了CloudFront Distribution.

我认为这意味着我的服务器不会再多次提供艺术家请求,但这并不是那么好.这篇文章解释了每个边缘位置(欧洲,美国等)在第一次查找资源时都会遇到错误,并且在云端缓存中保留了多少资源,因此可以删除它们.

所以为了解决这个问题,我已经通过服务器代码更改了在S3中的存储桶中存储网页的副本并在请求进入时首先检查这一点,因此如果艺术家页面已经存在于S3中,那么服务器将检索它并返回其内容作为网页.这大大减少了处理,因为它只为特定艺术家构建一次网页.

然而:

  1. 请求仍然必须转到服务器以检查艺术家页面是否存在.
  2. 如果艺术家页面存在,那么首先将网页(并且它们有时可以大到20mb)最先下载到服务器,然后服务器返回页面.

所以我想知道我是否可以改进这一点 - 我知道你可以构建一个S3存储桶作为重定向到另一个网站.是否有每页的方式我可以让艺术家请求转到S3存储桶,然后让它返回页面,如果它存在或调用服务器,如果它没有?

或者我可以让服务器检查页面是否存在然后重定向到S3页面而不是先将页面下载到服务器?

mu *_*u 無 2

OP 说:

它们有时可能很大,高达 20mb

由于您提供的数据量可能非常大,因此我认为您可以通过 2 个请求而不是一个请求来完成此操作,其中您可以将内容生成与内容服务部分解耦。这样做的原因是为了最大限度地减少服务器从 S3 获取数据并为其提供服务所需的时间/资源。

AWS 支持预签名 URL,该 URL 可以在短时间内有效;我们可以尝试在这里使用相同的方法来避免安全等问题。

目前,您的架构如下所示。客户端发起请求,检查S3上是否存在请求的数据,如果存在则获取并提供服务,否则生成内容,并将其保存到S3:

                           if exists on S3
client --------> server --------------------> fetch from s3 and serve
                    |
                    |else
                    |------> generate content -------> save to S3 and serve
Run Code Online (Sandbox Code Playgroud)

就网络资源而言,你总是在这里消耗2倍的带宽和时间。如果数据存在,那么一旦您必须从服务器中提取数据并将其提供给客户(因此是 2X)。如果数据不存在,您将其发送给客户和 S3(所以又是 2X)


相反,您可以尝试下面的 2 种方法,这两种方法都假设您有一些基本模板,并且可以通过 AJAX 调用获取其他数据,并且这两种方法都会降低整体架构中的 2 倍因素。

  1. 仅提供来自 S3 的内容。这需要改变产品的设计方式,因此可能不太容易集成。

    基本上,对于每个传入请求,如果数据已存在,则返回其 S3 URL,否则在 SQS 中为其创建一个任务,生成数据并将其推送到 S3。根据您对不同艺术家的使用模式,您应该估计平均需要多少时间来收集数据,然后返回一个对任务的estimated_time_for_completetion( T)有效的URL。

    客户端等待一段时间T,然后向之前返回的 URL 发出请求。如果失败,最多会尝试 3 次获取此数据。事实上,当 时,S3 上已经存在的数据可以被视为基本情况T = 0

    在这种情况下,您从客户端发出 2-4 个网络请求,但只有第一个请求到达您的服务器。仅当数据不存在且客户端始终从 S3 拉取时,才将数据传输到 S3。

                               if exists on S3, return URL
    client --------> server --------------------------------> s3
                        |
                        |else SQS task
                        |---------------> generate content -------> save to S3 
                         return pre-computed url
    
    
               wait for time `T`
    client  -------------------------> s3
    
    Run Code Online (Sandbox Code Playgroud)


  1. 检查数据是否已存在,并相应地进行第二次网络调用。

    这类似于您当前在从服务器提供数据(如果数据尚不存在)时所做的操作。再次,我们在这里发出 2 个请求,但是,这一次我们尝试从服务器同步提供数据,以防数据不存在。

    因此,在第一次点击时,我们检查之前是否生成过内容,在这种情况下,我们会收到成功的 URL 或错误消息。成功后,下一次命中将转到 S3。

    如果 S3 上不存在数据,我们会发出一个新请求(到不同的 POST URL),在获取该请求后,服务器计算数据并提供服务,同时添加一个异步任务将其推送到 S3。

                               if exists on S3, return URL
    client --------> server --------------------------------> s3
    
    client --------> server ---------> generate content -------> serve it
                                           |
                                           |---> add SQS task to push to S3
    
    Run Code Online (Sandbox Code Playgroud)