0

我有以下代码config/application.rb

config.after_initialize do
  MyConcern.init_processing
end

然后是以下相关方法:

def init_processing
  @queue_processor = Thread.new do
    process_op_queue
  end
  @queue_processor.name = "Some Queue"
  # @queue_processor_notifier = Queue.new
end

def process_op_queue
  while true
    req = MyRequest.where(done: Helper::FALSE_NIL_OR_MISSING, started_at: nil).order_by(id: :asc).find_one_and_update({'$currentDate' => {started_at: true}}, return_document: :after)
    req ? process_queue_item(req) : sleep(30)
  end
end

基本上在服务器启动时启动一个线程来执行应用程序通过 HTTP 调用从用户那里接受的一些后台任务。

在开发模式下一切正常。在具有相同 puma 服务器的生产环境中运行,@queue_processor显示已死(来自 rails 控制台):

MyConcern.instance_variable_get("@queue_processor").join
=> #<Thread:0x00000002b8fa68@MyConcern Queue@/var/lib/openshift/5842d71a5110e25cdf00000c/app-root/runtime/repo/app/controllers/concerns/my_concern.rb:23 dead> 
MyConcern.instance_variable_get("@queue_processor").value
=> false

首先,对我来说(温和地说)一个线程如何毫无例外地死亡并在上面的循环中返回 false 对我来说并不明显process_op_queue。其他非常有趣的事实是:

  1. 实际上有一个线程在做对我来说显而易见的工作,同时对应用程序进行请求并查看数据库中的哪些变化
  2. 在 Rails 控制台中,我只看到一个线程:

.

2.3.1 :009 > Thread.list
 => [#<Thread:0x000000012f63a8 run>] 
2.3.1 :010 > 

该应用程序的一部分正在检查队列处理器线程并报告错误,因此显示为已死确实打破了该逻辑。任何建议如何调试和解决问题将不胜感激。谢谢你。

4

1 回答 1

0

阅读 puma 和 workers 时,我似乎不清楚 puma 在分叉工人等时有什么魔力。所以最终决定为它创建一个 rake 任务:

rails g task mynamespace process_queue

然后放入lib/tasks/mynamespace.rake启动处理器所需的代码:

namespace :mynamespace do
  desc "Process reuqest queue"
  task process_queue: :environment do
    MyConcern.process_op_queue
  end
end

然后将其作为单独的进程而不是单独的应用程序线程启动。这使得我可以在尽可能多的容器中运行尽可能多的处理器和容器。rake 任务的好处是它具有应用程序本身的所有行为。这意味着MyModel.something将自动在应用程序内部工作。

nohup bin/rails mynamespace:process_queue > my.log
于 2016-12-07T15:47:51.767 回答