Rails背景图片上传导致应用程序超时

时间:2014-11-07 02:05:54

标签: ruby-on-rails carrierwave sidekiq

不幸的是,对于那些有类似问题的人来说,赏金被授予了无法解决此问题的答案。

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

目前的活动顺序:

  1. 用户提交表单
  2. 服务器收到表单
  3. 如果有图像,则服务器启动后台作业
  4. 如果后台作业已启动,则服务器等待它完成( rails times here out here
  5. 如果已启动,后台作业将完成
  6. 服务器处理请求
  7. 服务器响应用户
  8. 所需的活动顺序:

    1. 用户提交表单
    2. 服务器收到表单
    3. 服务器处理非图像字段
    4. 如果有图像,则服务器启动后台作业
    5. 服务器响应用户
    6. 后台作业完成,服务器处理上传的图像(保存URL)
    7. 上传代码

      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
      

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

      为了获得正确的事件顺序,我需要更改什么?

1 个答案:

答案 0 :(得分:6)

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

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

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

  • 用户在单击提交之前将一个或多个文件添加到表单。
  • 将文件直接上传到S3,并为表单的每个文件添加文件上传令牌。
  • 用户使用上传文件的标记而不是文件内容提交表单。
  • 服务器可以根据提交的令牌将文件移动到S3中的真实主页。

这使您的Web服务器可以专注于仅提供请求而不会阻止文件上载,这可能需要很长时间。

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

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