Rails ActiveStorage:如何避免对每个图像进行一次重定向?

col*_*rco 8 ruby-on-rails amazon-s3 rails-activestorage ruby-on-rails-6

如果您使用 ActiveStorage 并且您有一个包含 N 个图像的页面,您会收到 N 个对 Rails 应用程序的额外请求(即 N 个重定向)。如果页面上有数十张图像,这意味着浪费大量服务器资源。

我知道重定向对签名 URL 很有用。但是我想知道为什么 Rails 不预先计算最终的签名 URL 并将其嵌入到 HTML 页面中......这样我们可以保持签名 URL/受保护文件的优势,而无需对 Rails 服务器进行 N 次额外调用。

是否可以直接在 HTML 中包含图像变体的最终 URL/预签名 URL(从而避免重定向)?否则,为什么不可能?

col*_*rco 23

经过几天的推理和测试,我对我的最终解决方案感到非常兴奋,我将在下面解释。这是对图像的一种固执己见的方法,可能不代表当前的 Rails Way™?,但是对于提供许多公共图像的网站来说,它具有难以置信的优势,尤其是:

  1. 当您提供包含 N 个图像的页面时,您不会收到 1 + N 个对您的应用程序服务器的请求,而是只收到 1 个对该页面的请求
  2. 图像通过 CDN 提供,这改善了加载时间
  3. 该存储桶并非完全公开,而是受 Cloudflare 保护
  4. 图像由 Cloudflare 缓存,大大减少您的 S3 账单
  5. 您大大减少了对 S3 的 API 请求(即存在)的数量
  6. 此解决方案不需要对 Rails 进行大量更改,因此在出现问题时可以直接切换回 Rails 默认行为

这是解决方案:

  1. 创建一个 s3 存储桶并将其配置为托管公共网站(即调用它storage.example.com)-您甚至可以在存储桶级别禁用公共访问,并使用存储桶策略仅允许访问 Cloudflare ip
  2. 转到 Cloudflare 并为storage.example.com指向您的域的 CNAME 配置;您需要使用灵活的 SSL(您可以为子域使用页面规则);使用页面规则设置重缓存:设置 Cache Everything 并为 Browser Cache TTL 和 Edge Cache TTL 设置一个很长的值(例如 1 年)
  3. 在您的 Rails 应用程序中,您可以继续使用私有存储/ acl,这是 Rails 的默认行为
  4. 在您的 Rails 应用程序中@post.variant(...).processed每次更新或创建之后调用@post;然后在您的视图中使用'https://storage.example.com/' + @post.variant(...).key'(请注意,我们不会processed在视图中调用此处以避免在 s3 中进行额外检查);您还可以有一个 rake 任务来调用processed每个对象,以防您需要重新生成变体;如果您只有很少更改的几个变体(例如,每个帖子 1 个图像/变体),这是完美的

上述大部分步骤都是可选的,因此您可以根据需要将它们组合起来。