2012-10-07 44 views
6

Escribo una tarea de rake que se llamará cada minuto (posiblemente cada 30 segundos en el futuro) por Siempre, y entra en contacto con un punto final de la API de sondeo (por usuario en nuestra base de datos). Obviamente, esto no es eficiente ejecutar como un solo hilo, pero ¿es posible multiprocesar? Si no, ¿hay una buena biblioteca HTTP basada en eventos que pueda hacer el trabajo?tarea de rake multiproceso

Respuesta

12

estoy escribiendo una tarea rake que se llamaría cada minuto (posiblemente cada 30 segundos en el futuro) por Siempre

Cuidado con los rieles tiempos de arranque, puede ser mejor usar una bifurcación modelo como Resque o Sidekiq, Rescate proporciona https://github.com/bvandenbos/resque-scheduler que debería poder hacer lo que necesita, no puedo hablar de Sidekiq, pero estoy seguro de que tiene algo similar disponible (Sidekiq es mucho más nuevo que Resque)

Obviamente, esto no es eficiente ejecutar como un solo hilo , pero ¿es posible multihilo? Si no, ¿hay una buena biblioteca HTTP basada en eventos que pueda hacer el trabajo?

le sugeriría mirar a ActiveRecord's find_each para consejos sobre cómo hacer su proceso de buscador más eficiente, una vez que tenga los lotes que se pueden hacer fácilmente algo utilizando hilos tales como:

# 
# Find each returns 50 by default, you can pass options 
# to optimize that for larger (or smaller) batch sizes 
# depending on your available RAM 
# 
Users.find_each do |batch_of_users| 
    # 
    # Find each returns an Enumerable collection of users 
    # in that batch, they'll be always smaller than or 
    # equal to the batch size chosen in `find_each` 
    # 
    # 
    # We collect a bunch of new threads, one for each 
    # user, eac 
    # 
    batch_threads = batch_of_users.collect do |user| 
    # 
    # We pass the user to the thread, this is good 
    # habit for shared variables, in this case 
    # it doesn't make much difference 
    # 
    Thread.new(user) do |u| 
     # 
     # Do the API call here use `u` (not `user`) 
     # to access the user instance 
     # 
     # We shouldn't need to use an evented HTTP library 
     # Ruby threads will pass control when the IO happens 
     # control will return to the thread sometime when 
     # the scheduler decides, but 99% of the time 
     # HTTP and network IO are the best thread optimized 
     # thing you can do in Ruby. 
     # 
    end 
    end 
    # 
    # Joining threads means waiting for them to finish 
    # before moving onto the next batch. 
    # 
    batch_threads.map(&:join) 
end 

Esto iniciará sin más de batch_size de hilos, esperando después de cada batch_size para terminar.

Sería posible hacer algo como esto, pero entonces tendrá un número incontrolable de hilos, hay una alternativa de la que puede beneficiarse aquí, se vuelve mucho más complicado, incluido un ThreadPool, y una lista de trabajo compartida para hacer, lo he publicado como en Github no es para spam stackoverflow: https://gist.github.com/6767fbad1f0a66fa90ac

+0

¡El ThreadPool se ve genial! Voy a probarlo –

+0

Cosas buenas, gracias :) – Robin

3

Yo sugeriría usar sidekiq que es excelente en multihilo. A continuación, puede poner en cola trabajos separados por usuario para sondear la API. clockwork se puede utilizar para hacer que los trabajos que coloque vuelvan a aparecer.

Cuestiones relacionadas