Pergunta

No meu aplicativo Ruby on Rails Eu preciso executar 50 trabalhos de fundo em paralelo. Cada tarefa cria uma conexão TCP para um servidor diferente, fecths alguns dados e atualiza um objeto de registro ativo.

Eu sei soluções diferentes para executar esta tarefa, mas nenhum deles em paralelo. Por exemplo, delayed_job (DJ) poderia ser uma ótima solução se só ele pode executar todas as tarefas em paralelo.

Todas as idéias? Obrigado.

Foi útil?

Solução

Alguns pensamentos ...

  • Só porque você precisa ler 50 sites e, naturalmente, querem algum trabalho paralelo faz não significa que você precisa de 50 processos ou threads. Você precisa equilibrar a desaceleração e despesas gerais. Que tal ter 10 ou 20 processos cada ler alguns sites?

  • Dependendo que Ruby que você está usando, ter cuidado com os fios verdes, você pode não obter o resultado paralelo você quiser

  • Você pode querer estruturá-lo como um reverso, inetd do lado do cliente, ea utilização connect_nonblock e IO.select para obter as conexões paralelas que você quer, fazendo toda a responder servidores em paralelo. Você realmente não precisa de processamento paralelo dos resultados, você só precisa entrar na fila em todos os servidores em paralelo, porque é aí que a latência é realmente.

Assim, algo parecido com isto a partir da biblioteca de soquete ... estendê-lo para várias conexões pendentes ...

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

Outras dicas

Na verdade, é possível executar vários trabalhadores delayed_job.

A partir 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

Assim, em teoria, você poderia simplesmente executar:

$ RAILS_ENV=production script/delayed_job -n 50 start

Isto irá gerar 50 processos, no entanto eu não tenho certeza se que seria recomendável, dependendo dos recursos do sistema que você está executando isso em.


Uma opção alternativa seria usar tópicos . Basta gerar um novo segmento para cada um de seus postos de trabalho.

Uma coisa a ter em mente com este método é que ActiveRecord não é thread-safe. Você pode torná-lo thread-safe usando a seguinte configuração:

ActiveRecord::Base.allow_concurrency = true

Uma vez que você está trabalhando com os trilhos, gostaria de aconselhá-lo a usar delayed_job de fazer isso, em vez de cisão em fios ou garfos. Razão de ser - lidar com tempos de espera e outras coisas quando o navegador está esperando pode ser uma dor real. Existem duas abordagens que você pode levar com DJ

A primeira é - desova 50+ trabalhadores. Dependendo do seu ambiente pode ser uma solução muito pesado memória, mas ele funciona muito bem. Então, quando você precisa para executar o seu trabalho, apenas certifique-se de criar 50 postos de trabalho únicos. Se houver muito inchaço memória e você quer fazer as coisas desta maneira, fazer um ambiente separado que é despojado, especificamente para os seus trabalhadores.

A segunda maneira é criar um único trabalho que usa onda :: multi para executar seus 50 pedidos TCP simultâneas. Você pode descobrir mais sobre isso aqui: http://curl-multi.rubyforge.org/ Dessa forma, você pode ter um processador de fundo a execução de todos os seus pedidos TCP em paralelo.

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top