2015-04-24 50 views
7

我有一个网站(在Elastic Beanstalk的Tomcat中运行)生成艺术家唱片(一个艺术家的单个页面)。这可能是资源密集型的,因为艺术家页面在一个月内不会改变,所以我在其前面放置了CloudFront Distribution。使用Amazon S3和Cloudfront智能缓存webapges

我认为这意味着没有艺术家的请求曾经被我的服务器多次提供过,但是它不如那么好。这篇文章解释了每个边缘位置(欧洲,美国等)在第一次查找资源时都会错过,并且在云端缓存中保留了多少资源的限制,以便可以放弃这些资源。

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

但是:

  1. 请求还是要过到服务器以检查艺术家页面存在。
  2. 如果艺术家页面存在,那么网页(有时可能最大可达20mb)首先下载到服务器,然后服务器返回页面。

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

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

回答

2

OP说:

他们有时可以大上为20MB

由于数据的您服务可以相当大的量,我认为这是可行的,你这样做在2个请求而不是1个请求中,您将内容生成与内容服务部分分离。这样做的理由是为了尽量减少服务器从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倍的带宽和时间。如果数据存在,那么一旦你必须从服务器中提取数据并将其提供给客户(所以它是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接收数据。

          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 
    


  • 检查是否数据已经存在,并相应地使第二网络呼叫。

    这与您当前从服务器提供数据时所执行的操作类似,因为它尚不存在。再次,我们在这里提出2个请求,但是,这次我们试图在服务器不存在的情况下同步服务数据。

    因此,在第一次点击时,我们检查以前是否生成过内容,在这种情况下,我们获得了成功的网址或错误消息。一旦成功,下一个命中就是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 
    
  • +0

    我喜欢选项2,安全性不是真正的问题(我认为),因为我希望数据可以公开评估,我唯一的问题是这个。 –

    +0

    目前所有服务都通过http:// server/id服务,因此聪明的用户可以直接输入url。使用新方法http:// server/id只会告诉s3:// s3bucket/id的内容是否有效,但如果从未请求过页面,或者不是真正的问题,如果聪明的用户直接进入s3,这会给出错误? –

    +0

    @PaulTaylor如果用户很聪明,他会很容易弄清楚他必须去你的网络服务器并在那里提出请求:)另外,http://server.com/id告诉用户S3或者内容是否存在不是,并据此告诉他(重定向他?)关于内容的适当URL。 –

    0

    CloudFront缓存重定向,但不遵循:http://docs.aws.amazon.com/AmazonCloudFront/latest/DeveloperGuide/RequestAndResponseBehaviorCustomOrigin.html#ResponseCustomRedirects

    您没有提供具体的数字,但它可以帮助您预先生成所有这些页面,并将它们放到S3并将CloudFront直接指向S3?

    如果它是可行的,有几个好处:

    1. 您将脱钩从内容服务内容的生成,这将使系统在内容发电机整体
    2. 性能要求更稳定的要低得多因为它可以像它希望的再生那样缓慢地移动

    当然,如果你不知道你必须提前生成哪些页面,它将无法工作。

    +0

    呀它不是可行的预生成的所有页面,因为这将需要产生约1万页这将需要很多的CPU /时间,这将是一种浪费,因为大多数这些页永远不会被看在,所以我需要按需做,这是网站albunack.net –

    +0

    回到重定向,我不清楚如果服务器发送重定向到s3的页面,而不是retning页面本身会发生什么,会发生什么下次用户从Cloudfront请求页面时发生。 –

    0

    虽然我以前没有做过,但这将是一个我会看的技术。

    • 首先按照您所描述的那样设置S3存储桶,作为网站的“重定向”。

    • 看看S3事件处理程序。它们只处理创建S3对象的时间,但你可以尝试做一个GET开始,如果它无法通过POST或PUT回应相同的路径,放入一个“标记”文件或调用一个将触发的API一个事件?

    https://aws.amazon.com/blogs/aws/s3-event-notification/ http://docs.aws.amazon.com/AmazonS3/latest/dev/NotificationHowTo.html

    • 一旦事件被触发,要么你的服务器通过SQS监听事件,或移动您的艺术家创作者的代码到AWS LAMBDA这将养活了SNS的。

    我唯一担心的是GET的来源。你不希望任何人用无效的POST命令来触发你的S3存储桶 - 你会在所有地方产生。但是我会把它作为读者的练习。

    +0

    嗯,我的担心是这似乎非常复杂,并将我的代码更多地绑定到AWS基础架构中,而不是我特别想要的。目前唯一的AWS特定代码是S3 Put和S3 Get。 –

    +0

    我会提防不承诺的解决方案。如果你打算使用AWS,尽量确保你有接口,但是如果你退后一步,你会错过一些非常整洁的功能 - AWS的强大功能并非来自每个解决方案,它来自于(不敢相信我使用这个词)他们之间的协同作用。 我并不认为这是一个特别复杂的解决方案,但我不会成为实施它的人:) – Spedge

    0

    为什么不把像ngx或apache这样的web服务器放在tomcat前面?意味着tomat运行在8085的其他端口上,web服务器运行在80上。它获得命中并拥有自己的缓存。那么你根本不需要S3,但可以返回到你的服务器+ Cloudfront。

    因此,如果Cloudfront在高速缓存中直接返回页面,它将触发您的Web服务器。否则去tomcat。

    缓存可以在相同的进程或redis ... dependong上您需要缓存的数据的总大小。

    +0

    我喜欢简单的部署和EB提供的简单扩展,我假设将缓存添加到混合会打破这一点。此外,这些页面仍然由同一台机器提供服务,如果页面缓存在我的服务器上,如果我重新部署,它们全都会丢失 - 所以我不认为这是一个可行的解决方案。 –