使用Rails运行多个后台并行作业

在我的Ruby on Rails应用程序上,我需要并行执行50个后台作业。 每个作业都创建到不同服务器的TCP连接,定义一些数据并更新活动记录对象。

我知道执行此任务的不同解决方案,但它们中的任何一个并行。 例如,如果只有并行执行所有作业,delayed_job(DJ)可能是一个很好的解决方案。

有任何想法吗? 谢谢。

一些想法……

  • 仅仅因为你需要阅读50个站点并且自然想要一些并行工作并不意味着你需要50个进程或线程。 您需要平衡减速和开销。 如果有10个或20个进程每个读取几个站点怎么样?

  • 根据您使用的Ruby,请注意绿色线程,您可能无法获得所需的并行结果

  • 您可能希望将其构造为反向客户端inetd,并使用connect_nonblockIO.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 

实际上可以运行多个delayed_job工作程序。

来自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个进程,但是我不确定是否会建议这取决于你运行它的系统的资源。


另一种选择是使用线程 。 只需为每个作业生成一个新线程。

需要注意的一点是,使用此方法的ActiveRecordActiveRecord不是线程安全的。 您可以使用以下设置使其成为线程安全的:

 ActiveRecord::Base.allow_concurrency = true 

由于您正在使用rails,我建议您使用delayed_job来执行此操作,而不是拆分为线程或分叉。 原因是 – 在浏览器等待时处理超时和事情可能是一个真正的痛苦。 DJ可以采用两种方法

首先是 – 产生50多名工人。 根据您的环境,这可能是一个非常重要的内存解决方案,但它工作得很好。 然后,当您需要运行工作时,只需确保创建50个独特的工作。 如果存在过多的内存膨胀,并且您希望以这种方式执行操作,请创建一个单独的环境,专门针对您的工作人员。

第二种方法是创建一个使用Curl :: Multi来运行50个并发TCP请求的作业。 您可以在此处找到更多相关信息: http : //curl-multi.rubyforge.org/通过这种方式,您可以让一个后台处理器并行运行所有TCP请求。