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

fjy*_*iez 8 ruby multithreading background ruby-on-rails

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

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

有任何想法吗?谢谢.

Oll*_*lly 6

实际上可以运行多个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
Run Code Online (Sandbox Code Playgroud)

所以,从理论上讲,你可以执行:

$ RAILS_ENV=production script/delayed_job -n 50 start
Run Code Online (Sandbox Code Playgroud)

这将产生50个进程,但是我不确定是否会建议这取决于你运行它的系统的资源.


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

有一点需要注意的是,这种方法ActiveRecord不是线程安全的.您可以使用以下设置使其成为线程安全的:

ActiveRecord::Base.allow_concurrency = true
Run Code Online (Sandbox Code Playgroud)

  • 因为大多数工作人员都会被IO阻止,所以我可以在一台机器上运行多个工作人员 (2认同)

Dig*_*oss 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
Run Code Online (Sandbox Code Playgroud)