使用Amazon S3和Cloudfront来智能缓存网页

2020年3月10日 8点热度 0条评论

我有一个网站(在Tomcat上的Elastic Beanstalk上运行),该网站生成艺术家唱片(单个艺术家的页面)。这可能会占用大量资源,因此由于美术人员页面在一个月内没有变化,因此我在其前面放置了CloudFront发行版。

我以为这意味着我的服务器永远都不能满足艺术家的要求,但它的要求却不尽如人意。这篇文章解释说,每个边缘位置(欧洲,美国等)在首次查找资源时都会错过机会,并且在云缓存中保留多少资源是有限制的,以便可以删除它们。

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

然而:

  • 该请求仍然必须转到服务器以检查艺术家页面是否存在。
  • 如果存在艺术家页面,则首先将网页(有时大小最大为20mb)下载到服务器,然后服务器返回页面。
  • 因此,我想知道我是否可以改善这一点-我知道您可以构造一个S3存储桶作为重定向到另一个网站的方法。有没有一种按页面的方式,我可以让艺术家请求转到S3存储桶,然后让其返回页面(如果存在)或调用服务器(如果不存在)?

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

    解决方案如下:

    OP说:

    they can sometimes be large up-to 20mb

    由于您提供的数据量可能很大,因此我认为您可以在2个请求中执行此请求,而不是一次,将内容生成与内容提供部分分离。这样做的原因是为了最大程度地减少在服务器上从S3提取数据并提供服务所需的时间/资源。

    AWS支持
    pre-signed URLs,它可以在短时间内有效;我们可以在这里尝试使用相同的名称,以避免安全性等问题。

    当前,您的体系结构如下所示。客户端发起一个请求,您检查请求的数据是否在S3上存在,然后获取并提供该数据(如果有),否则生成内容,并将其保存到S3:

                               if exists on S3
    client --------> server --------------------> fetch from s3 and serve
                        |
                        |else
                        |------> generate content -------> save to S3 and serve
    

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

    取而代之的是,您可以尝试以下两种方法,这两种方法都假定您有一些基本模板,并且可以通过AJAX调用获取其他数据,并且这两种方法在总体体系结构中都降低了2倍。

  • 仅服务于S3中的内容。 这要求更改产品的设计方式,因此可能不太容易集成。

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

    客户端等待时间T,然后向先前返回的URL发出请求。如果发生故障,最多要尝试3次以获取此数据。实际上,当存在T = 0时,可以将S3上已经存在的数据视为基本情况。

    在这种情况下,您从客户端发出2-4个网络请求,但是只有这些请求中的第一个到达您的服务器。仅在数据不存在且客户端始终从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
    
  • 检查数据是否已经存在,并进行相应的第二次网络 call 。

    这与您当前从服务器提供数据(如果该数据不存在)时的操作类似。同样,我们在这里发出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