Ruby on rails 使用回形针加速S3上传

Ruby on rails 使用回形针加速S3上传,ruby-on-rails,paperclip,Ruby On Rails,Paperclip,我用回形针上传S3中的图像。 但是我注意到这个上传速度非常慢。我认为,因为在完成提交之前,文件必须经过我的服务器,进行处理并发送到S3服务器 有什么方法可以加速这一过程吗 谢谢您想让上传的外观更快,还是让上传速度更快 如果是前者,您可以将图像处理逻辑放入后台任务中,方法如下。这样,当用户单击按钮时,他们将在您处理图像时立即转到下一页(您可以显示“正在处理”图像占位符,直到任务完成) 如果是后者,则完全取决于您的服务器和internet连接。你在哪里托管?直接上传到S3怎么样 不确定回形针是否能在

我用回形针上传S3中的图像。 但是我注意到这个上传速度非常慢。我认为,因为在完成提交之前,文件必须经过我的服务器,进行处理并发送到S3服务器

有什么方法可以加速这一过程吗


谢谢

您想让上传的外观更快,还是让上传速度更快

如果是前者,您可以将图像处理逻辑放入后台任务中,方法如下。这样,当用户单击按钮时,他们将在您处理图像时立即转到下一页(您可以显示“正在处理”图像占位符,直到任务完成)


如果是后者,则完全取决于您的服务器和internet连接。你在哪里托管?

直接上传到S3怎么样

不确定回形针是否能在开箱即用,但你可以做到


正如cwninja所建议的,我们直接上传到s3,以避免额外的上传。我们使用本博客文章中描述的插件的修改版本:

我们的被修改为处理多个文件上传(重写flex对象)


不确定这对回形针的效果如何,我们使用了附件,但让它与回形针配合使用并没有那么糟糕。

使用延迟作业,这是一个很好的例子

或者您可以使用flash upload。

如果您最终选择直接上传到S3,从而从Rails服务器卸载工作,请查看我的示例项目:

使用Rails 3、Flash和基于MooTools的FancyUploader直接上传到S3的示例项目:

使用Rails 3、Flash/Silverlight/GoogleGears/BrowserPlus和基于jQuery的Plupload直接上传到S3的示例项目:

顺便说一句,你可以用回形针做后处理,就像这篇博文描述的:


您没有发布任何代码,因此我将在这里做一些假设:

  • 在您的项目中,您有一个
    相册
    图像
    模型
  • 一本
    相册有许多:图像
  • 你已经有了 及 使用铲斗和所有其他工具正确设置
  • 您正在一次上载多个图像
为了上传许多图像,您的表单将如下所示:

<%= form_for @album, html: { multipart: true } do |f| %>
  <%= f.file_field :files, accept: 'image/png,image/jpeg,image/gif', multiple: true %>

  <%= f.submit %>
<% end %>
这正是最重要的内容。使用此设置,在本地服务器上平均执行22个图像(总计12MB)需要
:files=
方法41.1806895秒。要检查方法运行所需的时间,请使用:

def files=(array = [])
  start = Time.now

  array.each do |f|
    images.create file: f
  end

  p "ELAPSED TIME: #{Time.now - start}"
end
您要求更快地上传许多图像。有几种方法可以做到这一点。使用 无法工作,因为无法将图像等复杂数据传递给作业


改为使用。它将图像样式创建(如
缩略图:“500x500”
)移动到后台作业中

Gemfile

source 'https://rubygems.org'

ruby '2.3.0'

...
gem 'delayed_paperclip'
...
图像文件

class Image < ApplicationRecord
  ...
  process_in_background :file
end
您可能会尝试此操作,但会出现一些奇怪的错误,只看到保存了4个图像。您还必须使用。此外,您不能在线程上使用
:join
,因为如果您加入,该方法将等待线程完成运行

def files=(array = [])
  semaphore = Mutex.new

  array.each do |f|
    Thread.new do
      semaphore.synchronize do
        images.create file: f
      end
    end
  end
end
通过对方法的简单更改,并且没有添加gems,与以前相同的上传运行时间为0.017628秒。即1313
delayed_回形针
快。它也比常规设置快2336


如果使用
延迟回形针
线程
,会发生什么情况

不要更改
:files=
方法。只需在GEM文件中重新打开
延迟回形针
,并在背景:file行中重新添加
过程

在我的机器上进行此设置后,该方法平均运行时间为0.001277秒。这就是

  • 13.8
    线程快几倍
  • 18120.6
    delayed\u回形针快几倍
  • 32248.0比常规设置快几倍
记住,这是在我的机器上,我还没有在生产中测试过。我也使用wifi,而不是以太网。所有这些都会改变结果,但我认为数字本身就说明了问题

上传图片更快。完成


更新:不要使用
延迟的回形针
。这会导致数据库繁忙,一些图像可能无法保存。我已经测试过了。我认为只使用线程已经足够快了。从
图像
文件中删除
后台进程
行。另外,我的
文件=
方法如下所示:

def files=(array = [])
  Thread.new do
    begin
      array.each { |f| images.create file: f }
    ensure
      ActiveRecord::Base.connection_pool.release_connection
    end
  end
end
注意:因为我们将图像保存推送到后台任务,然后重定向。加载的页面上还没有图像。用户必须 更新页面。解决此问题的一种方法是使用 . 轮询是指JavaScript每隔5秒左右检查一次任何更改,并对页面进行更改(如果有)

另一个选择是使用 . 现在我们有了Rails 5,我们可以使用它了。每次创建图像时,我们都会广播相册的更新。如果用户在该相册的页面上,他们将在数据库上看到更新,而无需用户刷新或浏览器在无限循环中每5秒发出一次请求


很酷的东西。

新链接在这里:我刚刚修复了损坏的链接。
class Image < ApplicationRecord
  ...
  process_in_background :file
end
def files=(array = [])    
  threads = []

  array.each do |f|
    threads << Thread.new do
      images.create file: f
    end
  end

  threads.each(&:join)
end
def files=(array = [])
  semaphore = Mutex.new

  array.each do |f|
    Thread.new do
      semaphore.synchronize do
        images.create file: f
      end
    end
  end
end
def files=(array = [])
  Thread.new do
    begin
      array.each { |f| images.create file: f }
    ensure
      ActiveRecord::Base.connection_pool.release_connection
    end
  end
end