2013-10-14 36 views
0

我开发RoR应用程序,我需要创建一些后台服务,这应该与我的基础和控制器一起工作。我有一个线程类,它必须与队列一起工作。所以我们有:Rails应用程序中的自定义多线程服务

class ServerThread 

    def initialize(name) 
     @name = name 
     @queue = Queue.new 
     @thread = Thread.new do 
      while true 
       if @queue.empty? 
        Thread.stop 
       end 
       item = @queue.pop 
       log = `run #{item}` 
       save_log(log) #save into DB 
      end  
     end 
    end 

    def add_to_queue(item) 
     @queue << item 
     @thread.run 
    end 

end 

现在它的工作是这样的。我只是在一些文件中创建全局变量:

$threads = SomeService.new 
Server.all.each do |server|     #servers from DB 
    $threads << ServerThread.new(server.name) 
end 

而且有时浏览器用户添加项目由控制器来排队:

class ServerController < ApplicationController 

    def add_to_queue  
     $threads.get_thread_by_name(params['server']).add_to_queue(params['item'])  
     render :nothing => true 
    end  

end 

我有一些用户该项目添加到队列,我需要看所有线程在我的应用程序。 我需要创建这个$线程,当我开始我的rails应用程序,这个线程应该是所有浏览器用户通用的。现在我试图用apache2和乘客部署我的应用程序,所以这是全局变量不起作用!

如何做到没有全局变量?

RoR 3.2,ruby 1.9.2

+3

你应该看看后台处理的宝石,如Resque或Sidekiq。手动线程池是一个坏主意(特别是在削弱线程的MRI中)。 –

+0

+1对于Sidekiq来说,这几乎肯定会比从头开始写更好的工作。 –

+0

我建议[Delayed :: Job](https://github.com/collectiveidea/delayed_job),它可以让你避免维护一个全新的数据库服务(如Redis或其他),这在大多数情况下是不需要的并发症 – mdesantis

回答

0

像@Sergio已经说过。不要从头开始写这样的东西是个好主意。可靠编写并发程序不是最简单的任务之一,也很难调试。在ruby中有一些非常好的选择。看看红宝石工具箱:https://www.ruby-toolbox.com/categories/Background_Jobs

如果你reaaaaaaaaaaaaaaaaly想要自己做,那么你必须替换你的全局变量,可以在同一台甚至不同的机器上的多个进程共享的东西。我认为这个问题的一个非常简单的解决方案就是使用redis的排队功能,并在上面实现你的后台工作者。

+0

)你能帮我吗,用Resque宝石怎么做?我失去了2天了解它是如何工作的,但仍然在我的情况下无法实现。 – facetostool

+0

如果您有关于resque的具体问题,请继续并创建一个新问题。 – phoet

相关问题