Ruby on Rails:如何在后台运行东西?
创建新资源并且在资源准备好之前需要进行一些冗长的处理时 ,如何将该处理发送到后台 ,它不会阻止当前请求或其他流量到我的网络应用程序?
在我的模型中:
class User < ActiveRecord::Base after_save :background_check protected def background_check # check through a list of 10000000000001 mil different # databases that takes approx one hour :) if( check_for_record_in_www( self.username ) ) # code that is run after the 1 hour process is finished. user.update_attribute( :has_record ) end end end
你应该看看以下Railscasts:
- http://railscasts.com/episodes/127-rake-in-background
- http://railscasts.com/episodes/128-starling-and-workling
- http://railscasts.com/episodes/129-custom-daemon
- http://railscasts.com/episodes/366-sidekiq
他们解释了如何以各种可能的方式在Rails中运行后台进程(有或没有队列……)
启动一个单独的过程,这可能是最容易用system
完成的,在“nohup”之前添加’并且在你传递它的命令的末尾附加’&’。 (确保命令只是一个字符串参数,而不是参数列表。)
您希望以这种方式执行此操作有几个原因,而不是尝试使用线程:
-
在执行I / O时,Ruby的线程可能有点棘手; 你必须注意你做的一些事情不会导致整个过程被阻止。
-
如果你运行一个具有不同名称的程序,它很容易在’ps’中识别,所以你不会意外地认为它是一个疯狂的FastCGI后端或什么东西,并杀了它。
实际上,你开始的过程应该是“deamonized”,请参阅Daemonize类获取帮助。
我刚刚尝试了’delayed_job’gem,因为它可以与Heroku托管平台一起使用,设置非常简单!
将gem添加到Gemfile, bundle install
, rails g delayed_job
, rake db:migrate
然后启动队列处理程序;
RAILS_ENV=production script/delayed_job start
你有一个方法调用,这是你漫长的过程,即
company.send_mail_to_all_users
你把它改成了;
company.delay.send_mail_to_all_users
查看github上的完整文档: https : //github.com/collectiveidea/delayed_job
理想情况下,您希望使用现有的后台作业服务器,而不是自己编写。 这些通常会让你提交一份工作并给它一个独特的钥匙; 然后,您可以使用该密钥定期查询作业服务器以获取作业状态,而不会阻止您的Web应用程序。 这里是各种选项的精彩综述 。
我喜欢使用backgroundrb,它很好,它允许你在长时间的过程中与它进行通信。 因此,您可以在rails应用中进行状态更新
我认为spawn是一个很好的方法来分叉你的进程,在后台进行一些处理,并向用户显示这个处理开始的一些确认。
关于什么:
def background_check exec("script/runner check_for_record_in_www.rb #{self.username}") if fork == nil end
然后,程序“ check_for_record_in_www.rb
”将在另一个进程中运行,并且可以访问ActiveRecord,从而能够访问数据库。