ruby-on-rails - Rails 背景图片上传导致应用程序超时

标签 ruby-on-rails carrierwave sidekiq

不幸的是,对于那些有类似问题的人,赏金被授予没有解决这个问题的答案。

我有一个带有图像上传的表单(heroku 到 s3)。当我提交表单时,我的 rails 服务器等待上传图像的后台作业完成,然后再向用户返回响应。这会导致每次上传图像时应用程序超时。

当前事件顺序:

  • 用户提交表单
  • 服务器接收表单
  • 如果有图片,服务器启动后台作业
  • 如果后台作业已启动,服务器将等待它完成(此处 rails 超时)
  • 如果启动,后台作业完成
  • 服务器处理请求
  • 服务器响应用户

  • 所需的事件顺序:
  • 用户提交表单
  • 服务器接收表单
  • 服务器处理非图像字段
  • 如果有图片,服务器启动后台作业
  • 服务器响应用户
  • 后台作业完成,服务器处理上传的图片(保存网址)

  • 上传者代码
    class PhotoUploader < CarrierWave::Uploader::Base
      include ::CarrierWave::Backgrounder::Delay
      include CarrierWave::MimeTypes
      process :set_content_type
      storage :fog
    end
    

    Carrierwave::Backgrounder 初始化器
    CarrierWave::Backgrounder.configure do |c|
      c.backend :sidekiq, queue: :carrierwave
    end
    

    用户模型
    class User < ActiveRecord::Base
      mount_uploader :photo, PhotoUploader, delayed: true
      process_in_background :photo
    end
    

    没有 Controller 代码,因为表单由 ActiveAdmin 处理。我可以覆盖任何需要的地方,但无法弄清楚需要改变什么。

    我必须改变什么才能获得正确的事件顺序?

    最佳答案

    这里的潜在问题是 Heroku 对请求在不将数据发送回客户端的情况下可以阻塞的时间有严格的限制。如果您达到该限制(初始字节为 30 秒),Heroku 将使您的请求超时。对于文件上传,您很可能会达到此限制。

    最好的方法是先让用户的浏览器直接将文件上传到 S3。这里有一些与此相关的讨论:Direct Uploads to S3 using Carrierwave

    如果您使用类似 jQuery 文件上传插件 ( https://github.com/blueimp/jQuery-File-Upload ) 的内容,流程将类似于:

  • 用户在单击提交之前向表单添加一个或多个文件。
  • 这些文件会直接上传到 S3,并且会为每个文件添加一个文件上传 token 到您的表单中。
  • 用户使用上传文件的 token 而不是文件的内容提交表单。
  • 服务器可以根据提交的 token 将文件移动到它们在 S3 中的真实位置。

  • 这允许您的 Web 服务器专注于只处理请求,而不是阻止可能需要很长时间的文件上传。

    由于 Heroku 的限制,这需要更多的工作 - 但最终我认为这是避免超时限制的唯一选择。

    此外,我建议您创建一个上传 S3 存储桶,然后设置 S3 生命周期策略以清除早于某个时间间隔的文件。当您进行直接文件上传时,由于用户放弃等原因,某些上传没有被处理是很常见的,因此生命周期会完成清理这些文件的工作。

    关于ruby-on-rails - Rails 背景图片上传导致应用程序超时,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/26792860/

    相关文章:

    ruby-on-rails - Devise中sign_in页面的路径助手的名称是什么?

    javascript - 未命中 Javascript/JQuery 中的调试器

    ruby-on-rails - 使用 Heroku 显示存储在 Amazon S3 上的图像

    ruby-on-rails - 如何在 Sidekiq 和 Foreman 中使用 Byebug

    ruby-on-rails - 如何为 HAML 页面设置特定标题

    ruby-on-rails - 载波/雾/S3 "is not a recognized storage provider"

    ruby-on-rails - 如何从 carrierwave 中的 id 和 name 中查找 url

    ruby - 使用sidekiq、redis发送邮件

    ruby-on-rails - 每个 sidekiq worker 有多种方法

    html - 当 anchor 标签内部有跨度时, anchor 标签不起作用