在Rails中管理多个请求的线程

时间:2015-08-18 02:21:57

标签: ruby-on-rails ruby ruby-on-rails-4

所以我有一个rails(4.1.8)应用程序,我正在使用mongodb实例,并遇到尝试使用线程的问题。我试图使用一个线程在后台修剪数据库,但希望能够从rails应用程序启动/停止/监视此线程。目前,启动/停止/监控都可以正常工作,但线程似乎在不应该被杀死时被杀死。

所以我的问题是rails应用程序是否有任何持久性部分?

我以为我可能会对config / application.rb运气不错,但似乎我对其工作方式的理解是不正确的。

以下是我用来进行监控的课程

class RentalAccountAutoRelease
  def self.instance(rental_account_service)
    @monitor ||= RentalAccountAutoRelease.new(rental_account_service)
  end

  def initialize(rental_account_service)
    @rental_account_service = rental_account_service
  end

  def monitor
    @monitor ||= Thread.new do
      loop do
        #prune database
        sleep 60
      end
    end
  end

  def status
    if @monitor
      if @monitor.alive?
        return {:status => 'on'}
      else
        return {:status => 'off'}
      end
    else
      {:status=>'off'}
    end
  end

  def stop
    if @monitor
      Thread.kill(@monitor)
      @monitor = nil
    end
  end
end

我在config / application.rb

中使用它
module Leo
  class Application < Rails::Application
    def self.apollo_rental_account_service
    config = DBConfig.new
    @apollo_rental_account_service ||= RentalAccountService.new(config.apollo["development"]["address"],
                                                         config.apollo["development"]["port"],
                                                         config.apollo["development"]["rental_accounts"]["db_name"],
                                                         config.apollo["development"]["rental_accounts"]["collection_name"])
    end

    def self.rate_view_rental_account_service
      config = DBConfig.new
      @rate_view_rental_account_service ||= RentalAccountService.new(config.rate_view["development"]["address"],
                                                           config.rate_view["development"]["port"],
                                                           config.rate_view["development"]["rental_accounts"]["db_name"],
                                                           config.rate_view["development"]["rental_accounts"]["collection_name"])
    end

    def self.siebel_rental_account_service
      config = DBConfig.new
      @siebel_rental_account_service ||= RentalAccountService.new(config.siebel["development"]["address"],
                                                           config.siebel["development"]["port"],
                                                           config.siebel["development"]["rental_accounts"]["db_name"],
                                                           config.siebel["development"]["rental_accounts"]["collection_name"])
    end

    def self.auto_release
      @auto_release = RentalAccountAutoRelease.instance([Leo::Application.apollo_rental_account_service,
                                                         Leo::Application.rate_view_rental_account_service,
                                                         Leo::Application.siebel_rental_account_service])
    end

  end
end

以下是我在控制器中使用它的方法

class AutoReleaseController < ApplicationController

  def initialize
    begin
      @auto_release = Leo::Application.auto_release
    rescue => e
      puts e
      puts e.backtrace
    ensure
      super
    end
  end


  def status
    render json: JSON.generate(@auto_release.status)
  end

  def start
    @auto_release.monitor
    render json: JSON.generate({:status => 'ok'})
  end

  def stop
    @auto_release.stop
    render json: JSON.generate({:status=>'ok'})
  end

end

提前致谢

1 个答案:

答案 0 :(得分:1)

您不应该将线程用于后台作业,因为在生产环境中,Rails应用程序通常会生成多个进程以实现并发(Rails应用程序通常以单线程模式运行)。因此,在您的情况下,每个进程将有一个后台作业。

实现后台作业的首选方法是将该作业与Rails应用程序的进程分开。例如,您可以在后台运行一个长期的 rake任务,它可以捕获UNIX信号或侦听某些特定端口上的套接字请求。您的Rails应用程序只是向该任务发送信号或请求以监视和控制它。