以非阻塞模式运行外部进程

时间:2014-08-10 12:56:11

标签: ruby-on-rails ruby ajax multithreading ruby-2.0

我想定期并行执行一些操作,一旦完成,就会在页面上向用户显示结果。它每5分钟大约发生一次,这取决于用户的活动。 这些操作由外部第三方应用程序(进程)执行。现在大约有4个。所以我必须为每个用户请求运行4个外部进程。 在他们正在执行时,我向用户显示一个带有ajax微调器的页面,并向服务器发送ajax请求以检查是否一切都已完成。完成后,我会显示结果。

这是我所拥有的粗略版本

class MyController

  def my_action request_id

    res = external_apps_cmds_with_args.each do |x|

      # new process
      res = Open3.popen3 x do |stdin, stdout, stderr, wait_thr|
        exit_value = wait_thr.value.exitstatus
        if exit_value == 0 ....
      end
    end

    write_res_to_db res, request_id #each external app writes to the db its own result for each request_id

  end
end

计算可以并行完成,因为这里没有总体结果,只有每个工具的结果。没有竞争条件。 所以我希望它们能够以非阻塞模式运行。

Open3.popen3是非阻塞命令吗?或者我应该在不同的线程

中运行外部流程
threads = []
external_apps_cmds_with_args.each do |x|
  # new threads
  threads << Thread.new do

    # new process
    res = Open3.popen3 x do |stdin, stdout, stderr, wait_thr|
      exit_value = wait_thr.value.exitstatus
      if exit_value == 0 ....
    end
  end

  write_res_to_db res, request_id #each external app writes to the db its own result for each request_id    
end

threads.each &:join

或者我应该创建只有一个主题吗?

# only one new thread
thread = Thread.new do
   res = external_apps_cmds_with_args.each do |x|
      # new process
      res = Open3.popen3 x do |stdin, stdout, stderr, wait_thr|
        exit_value = wait_thr.value.exitstatus
        if exit_value == 0 ....
      end
    end

    write_res_to_db res, request_id #each external app writes to the db its own result for each request_id    
end

thread.join

或者我应该继续使用我现在使用的方法:根本没有线程?

1 个答案:

答案 0 :(得分:0)

我建议你有一个动作来加载页面,然后为每个进程单独的ajax动作。随着流程的完成,它们会将数据返回给用户(可能是在页面的不同部分),您将利用Web服务器的多进程/线程功能。

这种方法存在一些问题,因为与原始想法一样,在外部进程运行时,您可能会占用一些Web进程,并且可能会遇到超时问题。如果你想避免这种情况,可以将它们作为后台作业(delayed_job,resque等)运行,然后在作业完成后显示数据。