2014-11-07 56 views
5

不幸的是,赏金被授予了一个答案,没有解决这个问题,对于那些有类似问题的人。Rails背景图片上传导致应用程序超时

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

当前事件的顺序:

  1. 用户提交表单
  2. 服务器接收形式
  3. 如果有图像,服务器启动后台作业
  4. 如果后台作业已经开始,服务器等待它完成(导轨超时这里
  5. 如果开始,后台作业完成
  6. 服务器处理
  7. 服务器响应于用户

事件的期望的顺序的请求:

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

上传代码

class PhotoUploader < CarrierWave::Uploader::Base 
    include ::CarrierWave::Backgrounder::Delay 
    include CarrierWave::MimeTypes 
    process :set_content_type 
    storage :fog 
end 

Carrierwave ::新闻背景初始化

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处理。我可以覆盖任何需要的地方,但无法弄清楚需要改变的地方。

我必须改变以获得正确的事件顺序?

+0

原谅我,如果我完全误解了这个问题,但不会上传不是异步的,如果通过标准的HTML表单提交完成?这不需要一些JavaScript异步处理上传,像这样? https://github.com/JangoSteve/remotipart – Ben 2014-11-07 14:41:03

+0

所有我看过的异步图像上传的教程和资源都没有改变生成的HTML表单,只是控制器。正如我所提到的**图像上传工作正常**。处理表单的控制器不需要等待。 – MishieMoo 2014-11-07 17:50:29

+0

对不起,我需要看到更多的代码才能理解你如何实现这一点。 sidekiq工作人员是否将整个上传处理为S3或者在上载完成时处于排队状态以处理数据库更新?你的控制器看起来像什么来响应表单提交? – Ben 2014-11-07 18:18:37

回答

6

这里的底层问题是Heroku严格限制请求可能阻塞多长时间而不发送数据回到客户端。如果您达到该限制(初始字节为30秒),Heroku会超时您的请求。对于文件上传,很可能你会达到这个限制。

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

如果你使用像jQuery的文件上传插件(https://github.com/blueimp/jQuery-File-Upload),流量会是这样的:

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

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

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

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

+0

我们不希望为此使用javascript/jQuery。理想情况下,我们可以修改请求处理,以在文件上传到后台的s3时响应用户。 – MishieMoo 2014-11-18 19:50:47

+0

如果您在Heroku上使用默认Rails服务器,则每个陀螺仪仅限于一个请求,因此您可以通过切换到支持多个Web进程的独角兽或美洲狮来执行您的线程方法。长期而言,最安全的方法是直接上传文件。我同意这不是很方便,但这只是使用Heroku的一个缺点。我刚刚也发现了这篇文章 - https://devcenter.heroku.com/articles/direct-to-s3-image-uploads-in-rails – TomDavies 2014-11-18 20:38:22

+0

我们已经在使用Unicorn,所以每个dyno的请求限制不应该在'不成问题。您链接的文章使用jQuery解决方案= / – MishieMoo 2014-11-19 01:25:32