порождая несколько параллельных задач - PullRequest
1 голос
/ 13 марта 2012

У меня есть M задач для обработки и N ресурсов параллельной обработки (например, рабочие потоки на экземплярах Heroko или EC2), где M >> N.

Я мог бы свернуть свою собственную систему, но, похоже, для этого уже есть отлаженный пакет или гем: что вы порекомендуете? (Теперь, когда я думаю об этом, я могу пытать Задержку :: Иов сделать это.)

Задачи могут быть написаны практически на любом языке - даже сценарий оболочки сделает эту работу. «Материнский корабль» - это Ruby On Rails с базой данных PostgreSQL. Основная идея заключается в том, что, когда ресурс готов обработать задачу, он запрашивает у материнской платы следующую необработанную задачу в очереди и начинает ее обрабатывать. Если работа не удалась, ее нужно повторить несколько раз, прежде чем сдаться. Результаты могут быть помещены в простые файлы или записаны в базу данных PostgreSQL.

(И, нет, это не для генерации спама. Я исследую степень распространения нескольких крупных социальных сетей.)

Ответы [ 3 ]

2 голосов
/ 13 марта 2012

Это будет ваш собственный переход, но если ваша параллельная задача не требует значительных ресурсов, это достаточно быстрое решение.С другой стороны, если они требуют значительных ресурсов, вам нужно реализовать что-то более надежное.

Вы можете запустить каждый поток с Process::fork (если процесс выполняется в ruby) или Process::execили Process::spawn (если процесс в чем-то другом).Затем используйте Process::waitall для завершения подпроцессов.

Ниже я использовал Hash для хранения как самих функций, так и PID.Это определенно можно улучшить.

# define the sub-processes
sleep_2_fail = lambda { sleep 2; exit -1; }
sleep_2_pass = lambda { sleep 2; exit 0; }
sleep_1_pass = lambda { sleep 1; exit 0; }
sleep_3_fail = lambda { sleep 3; exit -1; }

# use a hash to store the lambda's and their PID's
sub_processes = Hash.new

# add the sub_processes to the hash
#  key = PID
#  value = lambda (can use to be re-called later on)
sub_processes.merge! ({ Process::fork { sleep_2_fail.call } => sleep_2_fail })
sub_processes.merge! ({ Process::fork { sleep_2_pass.call } => sleep_2_pass })
sub_processes.merge! ({ Process::fork { sleep_1_pass.call } => sleep_1_pass })
sub_processes.merge! ({ Process::fork { sleep_3_fail.call } => sleep_3_fail })

# starting time of the loop
start = Time.now

# use a while loop to wait at most 10 seconds or until
# the results are empty (no sub-processes)
while ((results = Process.waitall).count > 0 && Time.now - start < 10) do
  results.each do |pid, status|
    if status != 0
       # again add the { PID => lambda } to the hash
       sub_processes.merge! ( { Process::fork { sub_processes[pid].call } => sub_processes[pid] } )
    end
    # delete the original entry
    sub_processes.delete pid
  end
end

ruby-doc на waitall полезен.

2 голосов
/ 13 марта 2012

Я думаю, что это задание с задержкой https://github.com/collectiveidea/delayed_job или resque https://github.com/defunkt/resque работа, как вы сказали.

1 голос
/ 13 марта 2012

Звучит так, будто ты хочешь работу процессора. Посмотрите на Gearman http://gearman.org/ Довольно языковой агностик.

А вот и информация о рубиновом самоцвете http://gearmanhq.com/help/tutorials/ruby/getting_started/

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