Запуск нескольких фоновых параллельных заданий с помощью Rails - PullRequest
8 голосов
/ 22 октября 2009

В моем приложении Ruby on Rails мне нужно выполнить 50 фоновых заданий параллельно. Каждое задание создает TCP-соединение с другим сервером, отображает некоторые данные и обновляет объект активной записи.

Я знаю разные решения для выполнения этой задачи, но любое из них параллельно. Например, delayed_job (DJ) может быть отличным решением, если только он может выполнять все задания параллельно.

Есть идеи? Спасибо.

Ответы [ 3 ]

6 голосов
/ 22 октября 2009

На самом деле можно запустить несколько рабочих 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 процессов, однако я не уверен, будет ли это рекомендовано в зависимости от ресурсов системы, на которой вы его используете.


Альтернативным вариантом будет использование threads . Просто создайте новую ветку для каждой вашей работы.

При использовании этого метода важно помнить, что ActiveRecord не является потокобезопасным. Вы можете сделать его поточно-ориентированным, используя следующую настройку:

ActiveRecord::Base.allow_concurrency = true
1 голос
/ 22 октября 2009

Некоторые мысли ...

  • То, что вам нужно прочитать 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
0 голосов
/ 27 октября 2009

Поскольку вы работаете с rails, я бы посоветовал вам использовать delayed_job для этого, а не разбивать на потоки или вилки. Причина в том, что работа с таймаутами и прочее, когда браузер ждет, может быть настоящей болью. Есть два подхода, которые вы можете использовать с DJ

Первый - порождение 50+ рабочих. В зависимости от вашей среды это может быть довольно трудоемким решением, но оно прекрасно работает. Затем, когда вам нужно выполнить свою работу, просто убедитесь, что вы создали 50 уникальных рабочих мест. Если в памяти слишком много памяти и вы хотите что-то делать таким образом, создайте отдельную среду, которая будет урезана специально для ваших работников.

Второй способ - создать отдельное задание, которое использует Curl :: Multi для выполнения ваших 50 одновременных TCP-запросов. Вы можете узнать больше об этом здесь: http://curl -multi.rubyforge.org / Таким образом, у вас может быть один фоновый процессор, выполняющий все ваши TCP-запросы параллельно.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...