Niedawno pisałem, że przeniosłem stronę Webinsider.pl z DigitalOcean (ale nadal polecam) na VPS w HitMe. Oczywiście przy takiej przeprowadzce wsparłem się m.in. transferem plików/danych między serwerami z wykorzystaniem SSH, i wprawdzie w teorii można w ten sposób spróbować przenieść cały system z jednej maszyny na drugą, to raczej dotyczy to sytuacji, gdy obie maszyny są jak najbardziej zbliżone pod względem konfiguracji (np. z Raspberry Pi na drugą Raspberry Pi), dlatego zazwyczaj w ten sposób kopiuje tylko niektóre katalogi (np. strony internetowe, katalogi domowe), a resztę (np. zabezpieczenia, webserwer) instaluje i konfiguruje od podstaw – przy dobrej organizacji (i procedurach) nie zajmuje to aż tak dużo czasu, a przy okazji jest okazja przypomnieć sobie co nieco. Czasem w takich momentach pojawia mi się też pomysł na nowy wpis/poradnik – i tak było i tym razem, bo o ile o PHP-FPM i PHP Pools pisałem nawet niedawno, to jeszcze nie poruszałem tematu związanego z trybem pracy menedżera procesów PHP, a jest to dość ciekawe zagadnienie, które w wielu poradnikach sprowadza się zazwyczaj do domyślnego trybu pracy, który nie zawsze jest najlepszy…
Spis treści w artykule
Menedżer procesów PHP-FPM (process manager)
Wprawdzie w większości przypadków domyślne ustawienie będzie się pewnie sprawdzało całkiem nieźle, to jednak warto wiedzieć, jak można zarządzać procesami PHP na serwerze, choćby w przypadku gdy na naszej stronie zwiększy się znacznie ruch, czy zacznie brakować pamięci lub czasu/mocy procesora.
Przykładowym błędem związanym z tym tematem, jaki możecie spotkać w logach usługi PHP (/var/log/php5-fpm.log) będzie np.:
[DATA GODZINA] WARNING: [pool www] server reached pm.max_children setting (5), consider raising it
Jest to dość częsty błąd na stronach z trochę większym ruchem niż „kilak(set) osób dziennie” i – nie wdając się zbytnio w szczegóły – oznacza tyle, że trzeba zwiększyć ilość procesów PHP (PHP-FPM), jakie mogą w danej chwili pracować (w przypadku cytowanego błędu zostawiłem wartość domyślną, czyli 5).
Maksymalna ilość procesów
Oczywiście w tym przypadku najprościej zwiększyć maksymalną procesów PHP, jaka może działać w tym samym czasie, poprzez modyfikację tylko jednego parametru – pm.max_children:
sudo nano /etc/php5/fpm/pool.d/www.conf
I zmieniamy:
pm.max_children = 5
np. na 10:
pm.max_children = 10
Na koniec wystarczy zrestartować usługę PHP:
sudo service php5-fpm restart
Po co ustawiać w ciemno, jak można policzyć
Oczywiście możecie mieć wątpliwości, jaką wartość ustawić by było dobrze – nie ma na to jednoznacznej odpowiedzi, ja zazwyczaj stopniowo zwiększam liczbę (ilość ;-)) procesów, aż błąd zniknie, a do tego dodaje mały zapas.
Oczywiście nie jest to tak, ze wartość/liczbę możemy zwiększać baz ograniczeń, bo każdy proces to nie tylko dodatkowe obciążenie procesora, ale – a może przede wszystkim – wykorzystanie kolejnym megabajtów pamięci RAM, której zazwyczaj nigdy nie jest za dużo… ;-)
Na obecnym serwerze (XEN2G) mam 2 GB pamięci RAM (+ 4 GB pamięci SWAP, ale tego typu pamięci sugeruję nie brać pod uwagę w wyliczeniach, chyba że nie macie wyjścia), a więc jest to 2048 MB.
Średnio jeden proces (jedno wystąpienie) PHP u mnie to jakieś 3-3,3% pamięci, czyli ok 61-62 MB. Na wszelki wypadek dajmy z zapasem, więc powiedzmy, że będzie to 70 MB (ale nie kierujcie się tutaj moim przypadkiem, sprawdzicie, jak to wygląda u Was).
Tak więc 2048 MB dzielimy na 70, co nam daje ~29, ale trzeba pamiętać, że z pamięci RAM korzystają również inne usługi, w tym choćby system.
Dlatego lepiej sprawdzić ilość wolnej pamięci RAM podczas normalnej pracy serwera i podzielić ją przez 70-75. Otrzymaną wartość warto jeszcze trochę odchudzić i mniej więcej o to, co zostanie, możemy zwiększyć liczbę procesów PHP (pm.max_children).
Zarządzanie procesami (instancjami) PHP-FPM
Gdy już wiemy jaką wartość maksymalnie możemy ustawić (przynajmniej teoretycznie), to warto poznać jeszcze tryby pracy menedżera procesów PHP, gdyż nie w każdym przypadku domyślny tryb będzie najlepszy.
Static
Celowo nie zaczynam od domyślnie aktywnego trybu (dynamic), a od trybu static, gdyż na nim będzie mi chyba najłatwiej wyjaśnić, o co chodzi, a zarazem będzie to dobry punkt wyjścia dla pozostałych – już bardziej skomplikowanych w swojej zasadzie działania – trybów.
W tym trybie – jak sama nazwa wskazuje – ustalamy na sztywno liczbę procesów, która będzie cały czas działać w systemie, nawet jak nie będzie w danej chwili takiej potrzeby.
Ustawiamy właściwie tylko jeden parametr – ilość aktywnych procesów:
sudo nano /etc/php5/fpm/pool.d/www.conf
pm = static
pm.max_children = 5
Pewnie niektórym ten tryb już się spodobał, bo ilość dodatkowych ustawień jest równa zeru, ale ten tryb ma też swoje wady – niezależnie od ruchu na stronie, niezależnie od potrzeb zawsze w systemie będzie działać określona liczba procesów, tym samym stale zajmując dla siebie pamięć RAM (70-75 MB na każdą instancję).
Na plus – oprócz prostej konfiguracji – można zaliczyć również to, że w przypadku mocno obciążonych serwerów/stron z dużym ruchem może to być najbardziej wydajny tryb, gdyż zadeklarowana liczba procesów/instancji cały czas czeka w pogotowiu do działania…
Ondemand
Drugim trybem pracy, który chciałbym przedstawić jest ondemand – moim zdaniem dość niedoceniany tryb (rzadko pojawia się w poradnikach), a zwłaszcza w przypadku gdy korzystamy z niezależnych gniazd dla poszczególnych stron, na których dodatkowo ruch jest relatywnie niewielki, może to być prawdziwe wybawienie dla serwera, dzięki czemu możemy oszczędzić sporo pamięci RAM (a ew. różnica w wydajności względem trybu static powinna sprowadzać się właściwie tylko do czasu potrzebnego na wystartowanie potrzebnego procesu, czyli jakieś milisekundy).
Można powiedzieć, że jest to w pewnym sensie przeciwieństwo trybu static, bo w trybie ondemand ustawiamy maksymalną liczbę procesów, ale będą one uruchamiane tylko w razie potrzeby, a po ustawionym czasie bezczynności zabijane, zwalniając tym samym zasoby.
Parametrów do ustawienia nie ma dużo więcej – dochodzi czas bezczynności:
sudo nano /etc/php5/fpm/pool.d/www.conf
pm = ondemand
pm.max_children = 5
pm.process_idle_timeout = 10s
W powyższej przykładowej konfiguracji mamy maksymalnie 5 procesów, które będą zabijane po 10 sekundach bezczynności.
Dynamic
No i tym sposobem dotarliśmy do trzeciego i ostatniego trybu – dynamic, czyli dynamicznego zarządzania procesami.
Jest to tryb, który pewnie spotkacie w konfiguracji większości serwerów, co wynika nie tylko z tego, że jest on domyślnie aktywny, ale również z tego, że jest to chyba najbardziej uniwersalny tryb – z jednej strony procesy są tworzone i zabijane wedle potrzeb (ondemand), ale z drugiej strony możemy ustawić minimalną liczbę procesów oczekujących w stanie bezczynności na działanie (static).
Przykładowa konfiguracja usługi PHP wygląda np. tak:
sudo nano /etc/php5/fpm/pool.d/www.conf
pm = dynamic
pm.max_children = 5
pm.start_servers = 2
pm.min_spare_servers = 1
pm.max_spare_servers = 3
Jak widać, jest tu sporo więcej parametrów do ustalenia niż w pierwszych 2 trybach, ale chyba nadal nie jest to nic szczególnie skomplikowanego, zwłaszcza że jak wspomniałem – ten tryb jest aktywny domyślnie, a więc wstępne ustawienia macie gotowe.
Mamy tu dynamiczne zarządzanie procesami (pm = dynamic), których maksymalnie będzie 5, z tego 2 starują od razu, wraz ze startem webserwera/usługi PHP. W stanie oczekiwania (bez zadań) może być minimum 1 proces, ale nie więcej niż 3.
Wyciek pamięci
Skoro już jesteśmy przy tych ustawieniach, to jest jeszcze jedne parametr – właściwie uniwersalny, bo ma zastosowanie dla każdego z opisanych powyżej trybów, a może przeciwdziałać tzw. wyciekowi pamięci, jaki może się przydarzyć np. jakimś zewnętrznym modułom, a będzie się objawiał brakiem zwalniania wykorzystanej wcześniej pamięci, co w efekcie może doprowadzić nawet do wyczerpania pamięci RAM w naszym serwerze.
W tym celu wystarczy ustawić automatyczne resetowanie procesu PHP po zadeklarowanej liczbie aktywności, np. 500:
sudo nano /etc/php5/fpm/pool.d/www.conf
pm.max_requests = 500
I choć jak napiąłem, jest to uniwersalne ustawienie, to wydaje mi się szczególnie przydatne w przypadku korzystania z trybu static, gdzie poza restartem serwera lub usługi PHP procesy działają nieprzerwanie.
- Home Assistant 2024.11, czyli „sekcje” domyślnym widokiem z opcją migracji, WebRTC oraz wirtualna kamera - 1970-01-01
- Black Friday w ZUS, czyli jest jeszcze kilka dni, by złożyć wniosek RWS i skorzystać z wakacji składkowych płacąc ZUS za grudzień 2024 - 1970-01-01
- Wakacje składkowe ZUS a zawieszenie działalności gospodarczej, czyli uważaj, bo być może nie będziesz mógł skorzystać (w 2024) - 1970-01-01
Pytanie, ile interpreterów na hostingu współdzielonym to przyzwoita ilość? I teraz jak od strony webmastera walczyć z tym limitem.
Te ustawienia modyfikuje się by uzyskać jak największą dostępność strony przy jak najmniejszym obciążeniu serwera zbytecznymi procesami, co ma szczególne znaczenie w przypadku stron z większym ruchem, czy na serwerach z większą ilością niezależnych PHP Pools.
W przypadku hostingu współdzielonego to w większości przypadków nie ma co sobie tym niepotrzebnie zaprzątać głowy, bo to raczej w zakresie administracji… :-)
Tylko akurat pośrednio mnie to tyczy, bo ostatnio wszystkie monitoringi uptimów co chwilę zgłaszały brak działania strony. Jak się okazało się, iż moja strona mimo braku ruchu wykorzystuje wszystkie interpretery. Prawdopodobnie przyczyną tak „wzmożonego” ruchu były próby „skorzystania” z XML-RPC
Ale to chyba raczej/bardziej w temacie/kontekście blokowania XML-RPC (i chyba dobrze to przetestować, zwłaszcza że wdrożenie blokady jest dość proste) niż ustawień menedżera procesów PHP-FPM, bo to pewnie „na sztywno” masz w hostingu ustawione (choć w przypadku hostingu który podałeś można za złotówkę miesięcznie dokupić dodatkowy interpretator PHP, choć nie wiem czy to tylko w kontekście podniesienia bezpieczeństwa poszczególnych stron, czy też i wydajności).
Problem z XML-PRC już ogarnięty. Teraz tylko pytanie jak na przyszłość jeszcze walczyć z takim limitem?
Cache i serwowanie statycznego html raczej nie wykorzystuje interpretera.
Pytanie, czy 4 sztuki na hostingu współdzielonym to przyzwoita ilość, czy raczej „skąpstwo” i lepiej poszukać inny hosting?
Cloudflare + cache + jakaś wtyczka zabezpieczająca WordPressa (np. Wordfence) to chyba takie minimum jakie warto wdrożyć…
Co do ostatniego pytania – nie mam pojęcia, ale i nigdy się nad tym nie zastanawiałem. W przypadku swoich stron konfiguracje ustawiam indywidualnie dla każdej strony, zależnie od potrzeb (kolejna przewaga VPSa nad hostingiem współdzielonym).
W przypadku hostingu współdzielonego (bo wprawdzie głównie korzystam z VPSów, to mam 2 konta w Kylos) po prostu monitoruje działanie strony, i jak coś jest nie tak, to wtedy działam (optymalizacja, zmiana planu na wyższy, ew. migracja w inne miejsce, czy na VPSa).