我想定期并行执行一些操作,一旦完成,就会在页面上向用户显示结果。它每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
或者我应该继续使用我现在使用的方法:根本没有线程?
答案 0 :(得分:0)
我建议你有一个动作来加载页面,然后为每个进程单独的ajax动作。随着流程的完成,它们会将数据返回给用户(可能是在页面的不同部分),您将利用Web服务器的多进程/线程功能。
这种方法存在一些问题,因为与原始想法一样,在外部进程运行时,您可能会占用一些Web进程,并且可能会遇到超时问题。如果你想避免这种情况,可以将它们作为后台作业(delayed_job,resque等)运行,然后在作业完成后显示数据。