2013-07-28 9 views
17

Potrzebuję pomocy z moją konfiguracją Puma (Multi-Thread + Multi-Core Server) w mojej aplikacji RoR4 Heroku. Dokumenty Heroku na ten temat nie są jeszcze aktualne. Połączyłem się z tym: Concurrency and Database Connections dla konfiguracji, która nie wspomina konfiguracji dla Klastra, więc musiałem używać obu typów razem (gwintowane i wielordzeniowe).Konfiguracja Puma Cluster na Heroku

Moja obecna konfiguracja:

./Procfile

web: bundle exec puma -p $PORT -C config/puma.rb 

./config/puma.rb

environment production 
threads 0,16 

workers 4 
preload_app! 

on_worker_boot do 
    ActiveRecord::Base.connection_pool.disconnect! 

    ActiveSupport.on_load(:active_record) do 
    config = Rails.application.config.database_configuration[Rails.env] 
    config['reaping_frequency'] = ENV['DB_REAP_FREQ'] || 10 # seconds 
    config['pool']    = ENV['DB_POOL'] || 5 
    ActiveRecord::Base.establish_connection 
    end 
end 

Pytania:

a) Czy potrzebuję konfiguracji before_fork/after_fork jak w Unicorn, ponieważ pracownicy Cluster są rozwidleni ?.
b) Jak dostroić liczbę wątków w zależności od mojej aplikacji - jaki byłby powód jej odrzucenia?/W jakich przypadkach miałoby to znaczenie? Czy zoptymalizowano już 0:16?
c) Baza danych Heroku umożliwia 500 połączeń. Jaka byłaby dobra wartość dla DB_POOL w zależności od liczby wątków, liczby robotników i dyno? - Czy każdy wątek na pracownika na dyno wymaga równoległego połączenia DB podczas pracy równoległej?

Ogólnie: Jak powinna wyglądać moja konfiguracja pod kątem współbieżności i wydajności?

+0

Jeśli chodzi o strojenie liczby wątków. Przeczytałem samouczek dotyczący tuningu pracownika Unicorn, który sugerował uruchomienie 'ab' i zwiększenie liczby robotników (wątek w twoim przypadku), aż do spadku wydajności (żądania wymagają więcej czasu, aby zakończyć). Dobrze jest wziąć dość dynamiczną stronę i zobaczyć, jak działają różne żądania/współbieżne proporcje (pamiętaj także, że jeśli wykonasz wiele żądań, heroku może odciąć cię od podejrzeń o DoS) –

+0

@MichaelSzyndel Więc zasadniczo muszę pójść pierwszy choć każdy pracownik , sprawdź wydajność, a następnie przejdź przez wątki i sprawdź ponownie? Czy to nie zależy od tego, co dokładnie jest wymagane? – Nikom

+1

Z tego, co czytałem gdzieś, Heroku ma dwa rdzenie (4 wirtualne) na dyno. Optymalne jest posiadanie jednego procesu na dyno, a następnie od Ciebie zależy, ile wątków uruchomi się na proces. Że będę testował z ab. Pamiętaj też, że jeśli przekażesz 521 MB pamięci RAM, Heroku wyśle ​​ostrzeżenia i zamieni się na> 1 GB (potwierdź za pomocą docptów w heroku). –

Odpowiedz

26

a) Czy muszę konfigurację before_fork/after_fork jak w Unicorn, ponieważ robotnicy klastrowe są rozwidlone ?.

Normalnie nie, ale ponieważ używasz preload_app, tak. Wstępne ładowanie aplikacji uruchamia i uruchamia instancję, a następnie wyświetla pamięć dla pracowników; wynikiem jest, że twoje inicjalizatory są uruchamiane tylko raz (prawdopodobnie przydzielając połączenia db i tym podobne). W tym przypadku odpowiedni jest twój kod on_worker_boot. Jeśli nie używasz preload_app, każdy robot uruchamia się sam, w takim przypadku użycie inicjalizatora byłoby idealne do skonfigurowania niestandardowego połączenia, tak jak to robisz. W rzeczywistości, bez preload_app, twój blok on_worker_boot mógłby się nie powieść, ponieważ w tym momencie ActiveRecord i znajomi nie są nawet ładowani.

b) Jak dostroić liczbę wątków w zależności od mojej aplikacji - co to jest ?/W jakich przypadkach spowodowałoby to różnicę ? Czy zoptymalizowano już 0:16?

Na Heroku (i moich testów) jesteś najlepiej spełniających podane min/max wątki z max < = DB_POOL ustawienia. Wątki min umożliwiają aplikacjom kręcenie zasobów, gdy nie są obciążone, co zwykle jest wspaniałe, aby zwolnić zasoby na serwerze, ale prawdopodobnie jest mniej potrzebne na Heroku; to dyno jest już dedykowane do obsługi żądań internetowych, może równie dobrze je mieć i gotowe.Ustawienie zmiennej środowiskowej max < = twoja DB_POOL nie jest wymagane, istnieje ryzyko, że zużyjesz wszystkie połączenia z bazą danych w puli, wtedy masz wątek, który chce nawiązać połączenie, ale nie możesz go uzyskać, i możesz uzyskać stary "ActiveRecord :: ConnectionTimeoutError - nie można uzyskać połączenia z bazą danych w ciągu 5 sekund." błąd. To zależy od twojej aplikacji, ale możesz mieć max>DB_POOL i dobrze. Powiedziałbym, że twój numer DB_POOL powinien być co najmniej taki sam jak wartość wątków min, mimo że twoje połączenia nie są ładnie ładowane (wątki 5: 5 nie otwierają 5 połączeń, jeśli twoja aplikacja nigdy nie trafi do bazy danych).

c) Baza danych Heroku umożliwia 500 połączeń. Jaka byłaby dobra wartość dla DB_POOL w zależności od liczby wątków, liczby pracowników i liczby dynów? - Czy każdy wątek na pracownika na dyno wymaga pojedynczego połączenia DB, gdy działa równolegle?

Production Tier pozwala 500, aby być jasne :)

Każdy wątek jednego pracownika na hamowni mógłby zużywają połączenia, w zależności czy są one wszystkie próby dostępu do bazy danych w tym samym czasie. Zwykle połączenia są ponownie używane, gdy są już gotowe, ale jak wspomniałem w artykule b), jeśli wątki są większe niż puli, możesz mieć zły czas. Połączenia będą ponownie wykorzystane, wszystko to jest obsługiwane przez ActiveRecord, ale czasami nie idealnie. Czasami połączenia idą bezczynnie lub umierają, dlatego zaleca się włączenie Reaper'a, aby wykryć i odzyskać martwe połączenia.

+0

Czy mam rację, że "robotnicy 2" oznaczają dodatkowe procesy robotnicze dla pumy, więc w sumie są procesy "3"? – gaussblurinc

2

Nie chcesz mniej połączeń DB niż wątków. Pamiętaj, że każdy oddzielny proces ma swoją własną pulę połączeń, więc jeśli twoja baza danych obsługuje 20 połączeń i chcesz uruchomić 2 procesy, większość wątków, które możesz uruchomić bez ryzyka przekroczenia limitu czasu, to 10 wątków, każdy z pulą 10 połączeń.

Chcesz zostawić kilka połączeń dla sesji konsoli szyn. Należy również pamiętać o pracownikach działających w tle i o tym, czy są oni powiązani.

Jeśli twoi pracownicy są w oddzielnym procesie (sidekiq), będą mieli własną pulę. Jeśli wątki Twoich pracowników są tworzone w procesie sieciowym (girl_friday lub sucker_punch), będziesz chciał, aby DB_POOL był większy niż maksymalna liczba wątków internetowych, ponieważ będą one współużytkować pulę połączeń.