2012-10-07 9 views
6

Piszę zadanie rake, które będzie wywoływane co minutę (prawdopodobnie co 30 sekund w przyszłości) przez Ilekroć i będzie ono kontaktować się z punktem końcowym API odpytywania (na użytkownika w naszej bazie danych). Oczywiście, nie jest to wydajne działanie jako pojedynczy wątek, ale czy możliwe jest wielowątkowe? Jeśli nie, czy istnieje dobra biblioteka HTTP oparta na zdarzeniach, która byłaby w stanie wykonać zadanie?Zadanie wielowątkowe rake

Odpowiedz

12

Piszę zadanie natarcia, które można nazwać każdy minut (ewentualnie co 30 sekund w przyszłości) za każdym razem, gdy

Strzeż Rails czas uruchamiania, może lepiej byłoby użyć rozwidlone model taki jak Resque lub Sidekiq, Rescue zapewnia https://github.com/bvandenbos/resque-scheduler, który powinien być w stanie zrobić to, czego potrzebujesz, nie mogę mówić o Sidekiq, ale jestem pewien, że ma coś podobnego dostępnego (Sidekiq jest znacznie nowszy od Resque'a)

Oczywiście nie jest to wydajne działanie jako pojedynczy wątek , ale czy można wielowątkowe? Jeśli nie, czy istnieje dobra biblioteka HTTP oparta na zdarzeniach, która byłaby w stanie wykonać zadanie?

Sugeruję obejrzysz ActiveRecord's find_each wskazówki dotyczące podwyższenia proces finder bardziej efektywne, gdy masz swoje partie można łatwo zrobić coś przy użyciu wątków, takich jak:

# 
# 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 

To nie rozpocznie ponad batch_size z wątków, czekając po każdym batch_size, aby zakończyć.

Byłoby możliwe zrobienie czegoś takiego, ale wtedy będziesz miał niekontrolowaną liczbę wątków, istnieje alternatywa, z której możesz skorzystać, staje się o wiele bardziej skomplikowana, w tym wątek i udostępniona lista zadań do wykonania. do, wysłałem to jak na Github, więc nie spamować stackoverflow: https://gist.github.com/6767fbad1f0a66fa90ac

+0

ThreadPool wygląda świetnie! Wypróbuję to –

+0

Dobre rzeczy, dzięki :) – Robin

3

Proponuję użyć sidekiq, który jest świetny w wielowątkowości. Następnie możesz dodać do kolejki osobne zadania na użytkownika w celu odpytywania interfejsu API. clockwork można użyć do tworzenia powtarzających się zadań.