将 Cloudfront 与 Active Storage 结合使用

Posted

技术标签:

【中文标题】将 Cloudfront 与 Active Storage 结合使用【英文标题】:Using Cloudfront with Active Storage 【发布时间】:2019-02-16 23:08:29 【问题描述】:

我正在使用 Ruby on Rails 构建一个网站。要上传图片,我使用 Active Storage 和 Amazon S3。这里一切都很好。用户可以上传图片,图片可以在网站上查看(图片是公开的)。

现在,在生产中,图片的网址是:https://example.com/rails/active_storage/representations/1ej21h...

将 302 返回到 S3 存储桶: https://my-bucket.amazonaws.com/variants/9jdh2...

我不太喜欢:

获取图像的两次往返; 向 Rails 服务器发送图像请求; 这些图像的呆滞感。

而且我更愿意使用 Cloudfront 来提供这些图像。

我在 Rails Guides、Google 和 *** 上进行了搜索,但目前没有找到合适的答案。

目前是否有任何解决方案可以?

编辑: 更多上下文:在正常流量和来自不同国家/地区的情况下,每张图片将至少每分钟加载 1000 次。我不想让服务器承受这种压力(它还有其他请求要处理)。我希望用户尽快加载这些图像。因此 Cloudfront 作为这些图像的 CDN(公共图像,无需获取签名的 url)。

【问题讨论】:

你指的是rails会攻击服务器让active_job为你的bucket生成一个新的签名url吗?这会导致图像在页面加载时闪烁,而前端在服务器上等待生成签名的 url。您可以应用一个补丁来解决此问题。你能确认这是否是你在说的吗? @Verty00 图像不会闪烁:加载速度很慢,并且图像请求由 rails 服务器处理(实际上是生成一个新的签名 url)。我不需要任何签名,图像是公开的。当用户显示页面时,我希望服务器显示的图像的 url 为my-distribution.cloudfront.net/my-image-url.jpg。所以 Rails 服务器不需要处理不必要的图像请求(例如“绕过签名”)。 在下面查看我的答案。这有帮助吗? 【参考方案1】:

试试这个……

controllers/active_storage/representations_controller.rb

module ActiveStorage
  class RepresentationsController < BaseController
    include ActiveStorage::SetBlob

    def show
      expires_in 1.year, public: true
      variant = @blob.representation(params[:variation_key]).processed
      send_data @blob.service.download(variant.key),
            type: @blob.content_type || DEFAULT_SEND_FILE_TYPE,
            disposition: 'inline'
    end
  end
end

然后,当您使用 @model.image.variant(resize: '250x250') 调用图像时,请确保替换您想要的尺寸。这是一个黑客。我认为这应该由 rails 6 release 修复。

【讨论】:

感谢@Verty00,但它没有回答我的问题,也没有解决问题。我不希望通过 RepresentationsController 完全请求图像。 这非常接近。它只在第一次签名 url。然后每个sunsequent请求都直接通过bucket 是的。但它仍然会给服务器带来压力。 S3 存储桶不适用于分发内容。如果我在一个页面上有 10 张图片,并且这个页面被请求了 1k 次,我仍然会收到 1k + 10k 次对服务器的请求。 @PaulWatson 在某个时候,我查看了以下 Github 问题 github.com/rails/rails/issues/31419 并开始使用人们在此线程中提出的一些要点来“修补”ActiveStorage S3 后端。我能够为我的资产返回一个云端 url,这已经足够了,但那些不是“干净的”(名称中没有扩展名)。但我最终还是一无所获,商业价值不如其他功能重要,并且宁愿拥有不完美的东西而不是骇人听闻的东西...... gist.github.com/timm-oh/10c4f06effa536ff32c5d038e0dd57e1 请随意离开 cmets :)【参考方案2】:

我总是将负载均衡器放在云端分配之后,并将 Route53 域指向分配,而不是负载均衡器。这样你就可以缓存你想要的任何行为。您当然可以缓存任何对 rails/active_storage/representations/redirect/* 的请求,它会保留应用服务器在第一次检索图像时返回的所有缓存头。

【讨论】:

以上是关于将 Cloudfront 与 Active Storage 结合使用的主要内容,如果未能解决你的问题,请参考以下文章

无法将SSL证书与Amazon Cloudfront相关联

将 CloudFront 分配与 Route 53 域相关联时出现问题

Akamai 与 CloudFront [关闭]

Cloudfront:设置与 Origin 的 s3 路径差异

将 CloudFront 与没有负载均衡器的单个 EC2 实例一起使用

将 Amazon S3 存储桶和 Cloudfront 与 SSL Wordpress 站点一起使用不会提供静态文件