【问题标题】:Running multiple background parallel jobs with Rails使用 Rails 运行多个后台并行作业
【发布时间】:2009-10-22 09:23:53
【问题描述】:

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

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

有什么想法吗?谢谢。

【问题讨论】:

标签: ruby-on-rails ruby multithreading background


【解决方案1】:

实际上可以运行多个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

【讨论】:

  • 你也可以在多台机器上运行delayed_job worker。我怀疑在单台机器上运行比 CPU 内核更多的工作程序会带来很多好处,但你可以通过在多个机器上运行来分散负载。如果您需要同时运行 50 个,我认为您将需要分发工作。
  • 我会在一台机器上运行多个工作人员受益,因为大多数工作人员会被 IO 阻止
【解决方案2】:

一些想法...

  • 仅仅因为您需要阅读 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

【讨论】:

  • IO.select 在这种情况下可能很有用,我会试一试。谢谢。
【解决方案3】:

由于您使用的是 rails,我建议您使用 delay_job 来执行此操作,而不是拆分为线程或分叉。原因是 - 在浏览器等待时处理超时和其他东西可能会很痛苦。 DJ 可以采用两种方法

第一个是 - 产生 50 多个工人。根据您的环境,这可能是一个占用大量内存的解决方案,但效果很好。然后,当您需要运行您的工作时,只需确保创建 50 个独特的工作。如果内存膨胀过多而您想以这种方式做事,请创建一个单独的环境,该环境已被剥离,专门用于您的员工。

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

【讨论】:

    猜你喜欢
    • 2018-05-19
    • 2011-09-10
    • 2015-01-24
    • 2013-10-02
    • 1970-01-01
    • 2011-06-17
    • 1970-01-01
    • 2013-04-22
    • 1970-01-01
    相关资源
    最近更新 更多