2016-10-04 22 views
7

Mam aplikację typu hubka, która pozwala użytkownikom oceniać zdarzenia. Po dokonaniu oceny zdarzenia przez użytkownika, działa zadanie resque, które zmienia kolejność innych zdarzeń na podstawie opinii użytkownika.Rails & Heroku: Ilu robotników/hamowni potrzebuję

To zadanie w tle trwa około 10 sekund i działa około 20 razy na minutę na użytkownika.

Korzystanie z prostego przykładu. Jeśli mam 10 użytkowników korzystających z aplikacji w danym momencie i nigdy nie chcę, aby praca była oczekiwana, jaki jest optymalny sposób na zrobienie tego?

Jestem zdezorientowany, jeśli chodzi o Dynos, pule resque i połączenia redis. Czy ktoś może mi pomóc zrozumieć różnicę? Czy istnieje sposób na obliczenie tego?

+0

Dlaczego zadanie jest uruchamiane 20 razy na minutę, na użytkownika? Dlaczego nie uruchamiać się tylko, gdy użytkownik szereguje wydarzenie? – toddmetheny

+0

Dokładnie to robi, użytkownik "ocenia" 20 wydarzeń na minutę przesuwając je ("lubienie" lub "nielubianie"). –

Odpowiedz

4

Nie jesteś pewien, że zadajesz właściwe pytanie. Twoje prawdziwe pytanie brzmi "jak mogę uzyskać lepszą wydajność?" Nie "ile dynosów?" Dodanie dynama niekoniecznie da ci lepszą wydajność. Więcej dynos daje więcej pamięci ... więc jeśli Twoja aplikacja działa powoli, ponieważ kończy ci się dostępna pamięć (to znaczy, że używasz wymiany), to więcej dynamów może być odpowiedzią. Jeśli te zadania trwają po 10 sekund, chociaż ... pamięć prawdopodobnie nie jest twoim rzeczywistym problemem. Jeśli chcesz monitorować wykorzystanie pamięci, skorzystaj z narzędzia do wizualizacji, takiego jak New Relic.

Istnieje wiele podejść do rozwiązania problemu. Ale zacznę od kodu, który napisałeś. Umieszczenie kodu na SO może pomóc w zrozumieniu, dlaczego to zadanie zajmuje 10 sekund (po napisaniu kodu!). 10 sekund to dużo czasu. Optymalizacja zapytań wewnątrz tej pracy z pewnością pomogłaby.

Kolejny kawałek nisko wiszącego owocu ... zmień z resque na sidekiq dla twoich prac w tle. Naprawdę łatwy w użyciu. Będziesz zużywał mniej pamięci i zobaczysz natychmiastowy wzrost wydajności.

+1

Zamierzam opublikować inne pytanie na SO z większą ilością szczegółów. Dzięki! –

+0

Oto bardziej szczegółowy opis problemu: http://stackoverflow.com/questions/40115387/rails-heroku-and-resque-long-running-background-job-optimization/40115470#40115470 –

0

Dynos: To są indywidualne serwery wirtualne/fizyczne. Pomyśl o nich jako o tych samych, co instancje EC2.

Połączenia Redis: indywidualne połączenia z instancją Redis.

Resque Pool: Klejnot, który umożliwia jednoczesne uruchamianie pracowników na tym samym stanowisku/instancji.

+0

Więc jeśli stwierdzę, że mam zbyt wiele zadań w mojej kolejce, czy potrzebuję więcej połączeń dynos lub redis czy coś innego? –

+0

Popraw to, czego potrzebujesz, aby zwiększyć liczbę dyno tego pracownika, jeśli kopie zapasowe są tworzone. Musisz również upewnić się, że masz instancję redis, która może obsłużyć liczbę posiadanych pracowników. –

0

Przede wszystkim warto poszukać sposobów na poprawę wydajności samego zadania. Możesz uzyskać ją poniżej 10 sekund, używając buforowania modelu niskiego poziomu lub optymalizacji swojego algorytmu.

Pod względem liczby wymaganych pracowników należy wykonać liczbę operacji na minutę (20) razy liczbę sekund potrzebnych do uruchomienia (10) razy większą liczbę użytkowników (10) . To da ci liczbę sekund na minutę, jaką musiałoby wykonać jeden pracownik. 20 * 10 * 10 = 2000. Podzielić to przez 60 i masz liczbę minut na minutę, 33.3. Więc jeśli masz 34 pracowników i wszystkie te liczby są konsekwentne, powinni być w stanie trzymać się na bieżąco.

Powiedziawszy, że nie powinieneś być w stanie uruchomić 36 lub więcej dynosów dla 10 równoczesnych użytkowników dla algorytmu rankingu. To bardzo szybko stanie się drogie.

Zoptymalizuj algorytm, spróbuj dodać więcej pamięci podręcznej, a także wypróbuj system Sidekiq. Z mojego doświadczenia wynika, że ​​Sidekiq może przetworzyć kolejkę do 10 razy szybszą niż Resque. To zależy od tego, co robisz i jak korzystasz z każdego narzędzia, ale warto je sprawdzić. Zobacz Sidekiq vs Resque.

+0

Dzięki, popatrzę. –

0

Zmiana rankingu innych wydarzeń to zły pomysł.

Powinieneś rozważyć posiadanie kolumn total_points i average_points dla tabeli wydarzeń, a następnie rozróżnianie kolejności według zapytań. Lubię to.

class Event 
    has_many :feedbacks 

    scope :rank_by_total, -> { order(:total_points) } 
    scope :rank_by_average, -> { order(:average_points) } 
end 

class Feedback 
    belongs_to :event 
    after_create :update_points 

    def update_points 
     total = event.feedbacks.sum(:points) 
     avg = event.feedbacks.average(:points) 
     event.update(total_points: total, average_points: avg) 
    end 
end 

Więc Ilu pracowników/hamowni trzeba?

Nie musisz martwić się o hamowanie lub robotnika w związku z tym problemem. Bez względu na to, ile dyn o wyższej mocy obliczeniowej używasz, twoje rozwiązanie zajmie dużo czasu, gdy stół wydarzeń stanie się ogromny. Więc spróbuj zmienić swoje rozwiązanie tak, jak opisałem.

+0

Ale nasze rankingi wydarzeń są spersonalizowane do każdego użytkownika. To nie jest popularność, ma to związek z konkretnym użytkownikiem na podstawie wcześniejszych wydarzeń, które podobały się –

+0

Więc mój pomysł brzmiał: Event has_many event_rankings i event_ranking belongs_to user. Każdy użytkownik ma więc własne rankingi wydarzeń ... –