Konfiguracja klastra Puma na Heroku

Potrzebuję pomocy z konfiguracją Puma (Multi-Thread+Multi-Core Server) na mojej aplikacji Ror4 Heroku. Dokumenty Heroku na ten temat nie są do końca aktualne. Podążałem za tym: Concurrency i database Connections dla konfiguracji, która nie wspomina o konfiguracji dla klastra, więc musiałem użyć obu typów razem (threaded i multicore).

Mój prąd 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, skoro workery klastra są rozwidlone?.
b) jak dostroić liczbę wątków w zależności od mojej aplikacji - jaki byłby powód, aby ją upuścić? / W jakich przypadkach to coś zmieni? Czy 0:16 nie jest już zoptymalizowane?
c) baza danych Heroku pozwala na 500 znajomości. Jaka byłaby dobra wartość dla DB_POOL w zależności od liczby wątków, workerów i hamowni? - Czy każdy wątek na pracownika na hamowni wymaga jedynego połączenia DB podczas pracy równoległej?

Ogólnie: jak powinna wyglądać moja konfiguracja dla współbieżności i wydajności?

Author: Nikom, 2013-07-28

2 answers

A) czy potrzebuję konfiguracji before_fork / after_fork jak w Jednorożec, od kiedy pracownicy klastra są rozwidleni?.

Normalnie nie, ale skoro używasz preload_app, tak. Wstępne ładowanie aplikacji uruchamia instancję, a następnie rozwidla przestrzeń pamięci dla workerów; rezultatem jest uruchomienie inicjalizatorów tylko raz (ewentualnie przydzielanie połączeń db itp.). W tym przypadku twój kod on_worker_boot jest odpowiedni. Jeśli nie używasz preload_app, to każdy pracownik 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 on_worker_boot blok byłby błędny, ponieważ w tym momencie ActiveRecord i przyjaciele nie są nawet załadowane.

B) jak dostroić liczbę wątków w zależności od mojej aplikacji-co czy to był powód, by to upuścić? / W jakich przypadkach różnica? Czy 0:16 nie jest już zoptymalizowane?

Na Heroku (i moje testy) jesteś najlepiej dopasować swoje min/max nitki, z max DB_POOL ustawienie. Threads min pozwala Twojej aplikacji na spin down zasobów, gdy nie jest pod obciążeniem, co jest zwykle świetne, aby zwolnić zasoby na serwerze, ale prawdopodobnie mniej potrzebne na Heroku; to hamownia jest już dedykowana do obsługi żądań internetowych, równie dobrze może mieć je gotowe. Podczas ustawiania wątków max DB_POOL nie jest wymagana, istnieje ryzyko pochłonięcia wszystkich połączeń z bazą danych w pool, wtedy masz wątek, który chce połączenia, ale nie może 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. Zależy to jednak od twojej aplikacji, bardzo dobrze możesz mieć max > DB_POOL i będzie dobrze. Powiedziałbym, że twoja DB_POOL powinna być co najmniej taka sama jak twoja wartość min wątków, nawet jeśli Twoje połączenia nie są chętnie ładowane(5: 5 wątków nie otworzy 5 połączeń, jeśli Twoja aplikacja nigdy nie trafi do bazy danych).

C) baza danych Heroku pozwala na 500 połączeń. Co by było dobre wartość dla DB_POOL w zależności od wątku, workera i liczby hamowni? - Czy każdy wątek na pracownika na dyno wymaga jedynego połączenia DB, gdy działa równolegle?

Poziom produkcji pozwala na 500, żeby było jasne:)

Każdy wątek na pracownika na dyno Może zużyć połączenie, w zależności od tego, czy wszyscy próbują uzyskać dostęp do bazy danych w tym samym czasie. Zazwyczaj połączenia są ponownie używane po ich zakończeniu, ale jak wspomniałem w b), jeśli wątki są większe niż pula, możesz mieć zły czas. Połączenia zostaną wykorzystane ponownie, wszystko to jest obsługiwane przez ActiveRecord, ale czasami nie najlepiej. Czasami połączenia stają się bezczynne lub giną, dlatego sugeruje się włączenie Żniwiarza, aby wykryć i odzyskać martwe połączenia.

 26
Author: catsby,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-08-01 19:13:31

Nie chcesz mniej połączeń DB niż wątków. Pamiętaj, że każdy osobny proces ma swoją własną pulę połączeń, więc jeśli twój DB obsługuje 20 połączeń i chcesz uruchomić 2 procesy, najwięcej wątków, które możesz uruchomić bez ryzyka timeoutów, to 10 wątków, każdy z pulą 10 połączeń.

Chcesz pozostawić kilka połączeń dla sesji konsoli rails. Należy również pamiętać o pracowników tle, i czy są one gwintowane.

Jeśli Twoi pracownicy są w osobnym procesie (sidekiq), będą mieli swój własny basen. Jeśli wątki Twoich pracowników wywodzą się z procesu sieciowego (girl_friday lub sucker_punch), chcesz, aby DB_POOL był większy niż maksymalna liczba wątków sieciowych, ponieważ będą one współdzielić pulę połączeń.

 2
Author: Duke,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-08-14 21:27:36