在我的Ruby on Rails应用程序上,我需要并行执行50个后台作业。每个作业都创建到不同服务器的TCP连接,定义一些数据并更新活动记录对象。
我知道执行此任务的不同解决方案,但它们中的任何一个并行。例如,如果只有并行执行所有作业,delayed_job(DJ)可能是一个很好的解决方案。
有什么想法吗?感谢。
答案 0 :(得分:6)
实际上可以运行多个delayed_job worker。
来自http://github.com/collectiveidea/delayed_job:
# Runs two workers in separate processes.
$ RAILS_ENV=production script/delayed_job -n 2 start
$ RAILS_ENV=production script/delayed_job stop
所以,从理论上讲,你可以执行:
$ RAILS_ENV=production script/delayed_job -n 50 start
这将产生50个进程,但是我不确定是否会建议这取决于你运行它的系统的资源。
另一种选择是使用threads。只需为每个作业生成一个新线程。
有一点需要注意的是,这种方法是ActiveRecord
不是线程安全的。您可以使用以下设置使其成为线程安全的:
ActiveRecord::Base.allow_concurrency = true
答案 1 :(得分:1)
一些想法......
仅仅因为您需要阅读50个网站并且自然需要一些并行工作而不是意味着您需要50个进程或线程。您需要平衡减速和开销。如果有10个或20个进程分别读取几个站点呢?
根据您使用的Ruby,请注意绿色线程,您可能无法获得所需的并行结果
您可能希望将其构建为反向客户端inetd,并使用connect_nonblock
和IO.select
通过使所有服务器并行响应来获取所需的并行连接。您并不需要并行处理结果,只需要并行处理所有服务器,因为这是延迟的真正原因。
所以,来自套接字库的类似内容......将其扩展为多个未完成的连接......
require 'socket'
include Socket::Constants
socket = Socket.new(AF_INET, SOCK_STREAM, 0)
sockaddr = Socket.sockaddr_in(80, 'www.google.com')
begin
socket.connect_nonblock(sockaddr)
rescue Errno::EINPROGRESS
IO.select(nil, [socket])
begin
socket.connect_nonblock(sockaddr)
rescue Errno::EISCONN
end
end
socket.write("GET / HTTP/1.0\r\n\r\n")
# here perhaps insert IO.select. You may not need multiple threads OR multiple
# processes with this technique, but if you do insert them here
results = socket.read
答案 2 :(得分:0)
由于您正在使用rails,我建议您使用delayed_job来执行此操作,而不是拆分为线程或分叉。原因是 - 在浏览器等待时处理超时和事情可能是一个真正的痛苦。 DJ可以采用两种方法
首先是 - 产生50多名工人。根据您的环境,这可能是一个非常重要的内存解决方案,但它工作得很好。然后,当您需要运行工作时,只需确保创建50个独特的工作。如果存在过多的内存膨胀,并且您希望以这种方式执行操作,请创建一个单独的环境,专门针对您的工作人员。
第二种方法是创建一个使用Curl :: Multi来运行50个并发TCP请求的作业。您可以在此处找到更多相关信息:http://curl-multi.rubyforge.org/这样,您可以让一个后台处理器并行运行所有TCP请求。