Życie aplikacji PHP toczy się w rytmie uruchamianych i kończących się procesów. W świecie serwerów i hostingów to właśnie one decydują, jak szybko użytkownik zobaczy stronę, ile równoległych zapytań obsłuży witryna i jak skutecznie będą wykorzystane zasoby maszyny. Zrozumienie, czym są procesy PHP, jak powstają, w jaki sposób przetwarzają żądania oraz jak je kontrolować, jest kluczowe dla stabilności, przewidywalności i kosztów utrzymania każdej aplikacji. Poniżej znajdziesz praktyczny przewodnik obejmujący mechanikę działania, konfigurację, monitoring oraz optymalizację, z uwzględnieniem realiów hostingu współdzielonego, VPS-ów, serwerów dedykowanych i środowisk kontenerowych.
Czym właściwie są procesy PHP: cykl życia i przepływ żądania
Proces PHP to instancja programu interpreterem PHP, która realizuje pracę związaną z obsługą pojedynczego zapytania HTTP (lub zadania CLI). W typowym układzie serwerowym frontend (np. Nginx, Apache, LiteSpeed) przyjmuje połączenie od przeglądarki, a następnie przesyła je do warstwy wykonawczej PHP działającej w trybie FastCGI lub LSAPI. Tam uruchomiony zostaje kod aplikacji: bootstrapping frameworka, ładowanie konfiguracji, inicjalizacja połączeń do bazy, logika kontrolera, renderowanie widoków, a na końcu zwrócenie odpowiedzi do klienta.
Kluczowa cecha: procesy PHP są zwykle krótkotrwałe i “bezstanowe” względem kolejnych żądań. Każde żądanie to osobny przebieg – przynajmniej w klasycznym modelu. Dzięki temu nie “niesiemy” w pamięci pozostałości z poprzednich wywołań, co ułatwia stabilność i izolację błędów, ale ma koszt w postaci narzutu startu aplikacji. Dlatego tak ważny jest opcache, buforowanie autoloadera i biblioteki, które minimalizują czas rozruchu.
Na serwerach produkcyjnych najczęściej spotkasz PHP-FPM, czyli menedżera procesów FastCGI. Tworzy on pulę procesów-robotników, które czekają na żądania. W ramach pojedynczej puli możesz konfigurować, ile dzieci (workers) działa jednocześnie, jaką mają politykę uruchamiania i wygaszania, ile żądań obsłużą przed recyklingiem oraz jak długi czas mogą pracować nad jednym zapytaniem, zanim zostaną przerwane.
Warto rozróżnić procesy webowe (FPM) od uruchomień CLI. Te drugie służą do zadań wsadowych, kolejek, crontabów i migracji. Działają zwykle w oddzielnych przestrzeniach wykonawczych, mogą mieć inne limity i nie podlegają tym samym regułom, co pulowy model FPM. To rozróżnienie bywa krytyczne, gdy “znikające” zasoby wynikają z uruchomionych skryptów CLI, a nie z żądań HTTP.
Tryby uruchamiania PHP na serwerze
Apache + mod_php
Historycznie PHP uruchamiano jako moduł serwera Apache (mod_php). To proste podejście integruje interpreter bezpośrednio z serwerem WWW, ale skaluje się gorzej i komplikuje separację użytkowników. Dziś stosuje się je rzadziej w środowiskach wieloużytkownikowych, choć w prostych, jednoużytkowych instalacjach nadal może być wygodne.
FastCGI i PHP-FPM
Dominujący standard to FastCGI z warstwą FPM. Serwer WWW (Nginx, Apache z mod_proxy_fcgi, Caddy) przekazuje żądanie do socketu TCP/Unix należącego do puli FPM. Dzięki temu można niezależnie skalować część webową i część aplikacyjną, łatwiej też izolować użytkowników (oddzielne pule, user/group, chroot). To podejście jest wydajne i elastyczne, a jego działaniem zarządza menedżer procesów – rdzeń FPM.
LiteSpeed i LSAPI
W hostingach komercyjnych często spotkasz LiteSpeed lub OpenLiteSpeed z LSAPI. Koncepcja przypomina FastCGI, lecz jest specyficznie zoptymalizowana pod LiteSpeed. W panelach hostingowych wiele opcji strojenia sprowadza się do limitów na użytkownika oraz liczby jednoczesnych procesów, podobnie jak w FPM.
IIS i FastCGI na Windows
Na Windowsie PHP uruchomisz przez FastCGI w IIS. Jest to dojrzałe rozwiązanie, choć rzadziej używane w środowiskach masowych. Zasada dystrybucji żądań do procesów jest podobna: definiujesz limity i cykl życia, monitorujesz logi i wskaźniki wydajności.
Kontenery i orkiestracja
W środowiskach Docker/Kubernetes uruchamiasz FPM w kontenerze, a serwer WWW w innym, co ułatwia separację i aktualizacje. Kontrolę procesów przejmuje częściowo system init kontenera (np. s6, tini) oraz mechanizmy orkiestratora, ale decyzje o liczbie i parametrach workerów wciąż należą do FPM.
Kluczowe parametry i mechanika PHP-FPM
Konfiguracja FPM składa się z pliku głównego i plików puli. Najważniejsze ustawienia wpływają na wydajność, stabilność oraz budżet pamięci RAM.
Polityka zarządzania procesami: pm = static | dynamic | ondemand
- static – stała liczba procesów; przewidywalne zużycie RAM, dobre przy ruchu stabilnym i serwerach dedykowanych.
- dynamic – minimalna i maksymalna liczba procesów, które FPM utrzymuje, uruchamiając i wygaszając je według potrzeb (pm.min_spare_servers, pm.max_spare_servers).
- ondemand – procesy startują dopiero, gdy pojawi się ruch i wygaszają się po bezczynności. Oszczędza pamięć w okresach ciszy, kosztem czasu zimnego startu.
pm.max_children i planowanie zużycia pamięci
To twardy limit liczby jednocześnie aktywnych workerów. Aby go dobrać, musisz znać przeciętną “wagę” jednego procesu PHP. Zmierz ją poleceniem ps/htop i policz budżet: dostępna RAM / średnia pamięć procesu = górny limit. Przykład: jeśli jeden proces konsumuje 120 MB, a masz 4 GB przeznaczone na PHP, bezpieczny pułap to 4096 / 120 ≈ 34. Zostaw zapas na serwer WWW, bazę i system. Dobre opanowanie pamięć to jedna z najważniejszych kompetencji przy strojeniach FPM.
pm.max_requests i recykling procesów
Po obsłużeniu określonej liczby żądań proces zostanie zastąpiony nowym. Chroni to przed akumulacją fragmentacji pamięci i wyciekami. Umiarkowana wartość (np. 500–5000) bywa sensowna, ale zależy od aplikacji. Zbyt niska – zwiększa koszty restartów, zbyt wysoka – ryzyko narastających wycieków.
request_terminate_timeout i timeouty
Limit czasu przetwarzania pojedynczego żądania pozwala brutalnie przerwać “wiszące” procesy. Chroni przed blokadami I/O i błędami w kodzie, ale wymaga świadomego ustawienia po stronie aplikacji (np. asynchroniczne kolejki dla długich zadań). Ustal rozsądne timeouty i sygnalizuj klientowi błędy w kontrolowany sposób. Uzupełnij to limitem max_execution_time po stronie PHP oraz mechanizmami w serwerze WWW (proxy_read_timeout, idle timeouts).
Slowlog, status i kolejka
Włącz request_slowlog_timeout i slowlog – to bezcenne narzędzie diagnostyczne. Dodatkowo udostępnij pm.status_path (np. /status) za firewallem lub w panelu administracyjnym. Otrzymasz metryki: active processes, idle processes, listen queue, accepted conn, slow requests. Zwracaj uwagę na listen queue – rosnąca kolejka to znak zbyt małej liczby workerów lub wąskiego gardła w aplikacji.
Backlog i bufor socketu
Parametry listen.backlog i kernelowe kolejki wpływają na wchłanianie nagłych pików ruchu. Zbyt niski backlog skutkuje odrzuceniami połączeń i błędami 502/503. Nie zastąpią one jednak właściwego skalowania puli.
Monitoring i obserwowalność procesów
Bez danych trudno podejmować decyzje. Monitoring powinien obejmować zarówno system, jak i samą aplikację.
- Narzędzia systemowe: top/htop, ps, vmstat, iostat, sar – pozwalają ocenić CPU, RAM, I/O, swap, load average. Ważne: obserwuj RSS per proces PHP oraz sumaryczne użycie pamięci.
- Logi: error_log PHP, logi FPM, slowlog, logi serwera WWW. Koreluj timestampy z metrykami systemowymi.
- Opcache: sprawdzaj hit rate, memory usage i fragmentation. Wysoki hit rate poprawia wydajność i zmniejsza narzut startu. Przepełniony opcache potrafi wywołać thrashowanie i skoki CPU.
- Eksportery i APM: Prometheus + exporter FPM, OpenTelemetry, New Relic, Datadog, Blackfire, Tideways. Dają wgląd w czas odpowiedzi, rozkład funkcji, zapytania SQL, zewnętrzne API.
- Kolejki i baza danych: monitoruj czasy transakcji, blokady, pool połączeń, wykorzystanie indeksów. Wąskie gardła często są poza PHP.
Hostingi współdzielone: limity i dobre praktyki
W środowiskach współdzielonych, szczególnie w oparciu o CloudLinux, spotkasz limity LVE: CPU, I/O, IOPS, pamięć, NPROC oraz “Entry Processes” (EP). EP to liczba równoległych wejść do Twojej aplikacji (nowe zapytania). Gdy EP się wyczerpie, kolejne żądania trafiają w kolejkę lub są odrzucane. Znajomość tych limitów pozwala dopasować aplikację do planu hostingowego.
- Włącz pamięciowe cache (np. Redis/Memcached) i unikaj ciężkich operacji w każdej odpowiedzi.
- Wykorzystuj HTTP caching (nagłówki Cache-Control, ETag), CDN i minifikację zasobów.
- Przenieś długotrwałe zadania do CRON/workerów i serwuj szybkie odpowiedzi z kolejką w tle.
- Ogranicz crawlowanie botów, ustaw rate limiting i robots.txt, stosuj WAF.
- Dbaj o indeksy w bazie i unikaj N+1 queries.
W panelach typu cPanel/DirectAdmin liczby “Procesy”, “EP”, “NPROC” czy “Faults” mówią o tym, czy Twoje procesy PHP są dławione przez limity. Jeżeli tak, często szybsza optymalizacja kodu i cache’owanie dają większy efekt niż “dokładanie” workerów.
Diagnostyka najczęstszych problemów
502 Bad Gateway / 503 Service Unavailable
Najczęściej oznaczają brak wolnych workerów (pm.max_children osiągnięte), długie czasy odpowiedzi (timeout), zawieszony FPM lub brak połączenia do socketu. Sprawdź listen queue, slowlog, error_log, a także limity w serwerze WWW (fastcgi_connect_timeout, read_timeout).
504 Gateway Timeout
Proces PHP nie zdążył odpowiedzieć. Przyczyny: wolna baza, zewnętrzne API, blokada pliku, nadmierny I/O, długie generowanie raportu. Rozwiązania: skrócenie pracy żądania (asynchroniczna kolejka), wydzielenie raportów do workerów CLI, lepsze indeksy w bazie, caching.
OOM i zabijanie procesów
Jeśli RAM się wyczerpuje, kernelowy OOM killer może zabijać losowe procesy. W logach systemowych zobaczysz OOM-kills. Zredukuj pm.max_children, zoptymalizuj footprint procesu, zmniejsz memory_limit lub przenieś ciężkie operacje do osobnych maszyn.
Wolne starty i skoki CPU
Najczęściej słaby hit rate w opcache, nadmierny autoload, brak preloading, dynamiczne generowanie klas. Ustaw opcache.validate_timestamps i opcache.max_accelerated_files, rozważ classmap w Composerze i preloading w nowszych wersjach PHP, jeżeli pasuje do Twojej architektury.
Błędy “Too many open files”, “connect() to unix:/… failed”
Zwiększ limity ulimit nofile, parametry rlimit_files w FPM, sprawdź uprawnienia do socketu i backlog. Upewnij się, że procesy mają odpowiednie user/group oraz że serwer WWW ma prawo do socketu.
Bezpieczeństwo i izolacja
Każda pula FPM może działać jako inny użytkownik systemowy (user/group), co zapewnia separację aplikacji. Dodatkowe mechanizmy: chroot, open_basedir, disable_functions, ograniczanie exec. Wartościowe jest czyszczenie zmiennych środowiskowych (clear_env) i kontrola poświadczeń (sekrety w plikach poza repozytorium, menedżery sekretów). Dobrze ustawione bezpieczeństwo nie tylko chroni, ale też ułatwia utrzymanie porządku w konfiguracji.
Optymalizacja kodu i architektury
- Włącz i dopracuj opcache, pilnuj hit rate, unikaj “warm-up” na żywym ruchu – zastosuj prewarming po deployu.
- Używaj pamięciowych warstw cache przy danych powtarzalnych: fragmenty HTML, wyniki zapytań, konfiguracje. Zewnętrzny cache (Redis) odciąża procesy PHP.
- Minimalizuj I/O: logi rotuj i kompresuj, statyczne pliki serwuj poza PHP (przez serwer WWW lub CDN).
- Optymalizuj bazy danych: indeksy, paginacja, unikanie N+1, agregacje przenieś do widoków materializowanych.
- Stosuj lazy loading i cache HTTP. Dla dynamicznych API rozważ ETag/If-None-Match.
- Dbaj o reużywalność połączeń (persistent connections ostrożnie), pooling w bibliotekach i unikaj kosztownego ponownego negocjowania SSL do backendów.
Warto też pamiętać o profilowaniu – Xdebug w trybie development, a w produkcji narzędzia APM i samplingowe profilery. Mierz, gdzie płynie czas, zamiast strzelać na oślep.
Skalowanie i wysoką dostępność
Skalowanie pionowe to podnoszenie zasobów maszyny (CPU/RAM), poziome – zwiększanie liczby replik FPM za load balancerem. W drugim przypadku kluczowe są kwestie stanu: sesje i pliki przesyłane przez użytkowników. Przenieś sesje do Redis/Memcached lub bazy, a uploady do współdzielonego storage’u lub S3, aby uniknąć “lepkości” sesji (sticky sessions) i zyskać prawdziwą elastyczność.
Ustal zdrowe limity per replikę: pm.max_children, backlog, timeouts, i zapewnij mechanizm rolling deploy z warm-upem opcache. Load balancer powinien wykonywać health-check na stronie statusu FPM lub ścieżce technicznej aplikacji (readiness/liveness).
Automatyzacja, deploy i kontrola procesu życia
PHP-FPM obsługuje sygnały: graceful reload (przeładowanie konfiguracji bez przerywania bieżących żądań) i restart. W systemd używaj systemctl reload/restart php-fpm. Dobrym nawykiem jest testowanie konfiguracji (php-fpm -t), a przy deployu – sekwencja: wygeneruj artefakty, zaktualizuj schemat bazy, uruchom warm-up opcache, zrób reload FPM, wykonaj health-check.
Zarządzając zadaniami CLI, rozważ supervisord lub natywny systemd (services/timers). Pilnuj limitów pamięci i czasu – set_time_limit, memory_limit – oraz przechwytywania sygnałów SIGTERM/SIGINT (pcntl), aby procesy kończyły się czysto. To szczególnie ważne przy workerach kolejkowych, które przetwarzają długie zadania.
Przykładowe polecenia i ścieżka diagnostyczna
- Sprawdzenie obciążenia: top/htop, sortowanie po RSS i CPU, obserwacja procesów php-fpm.
- Pamięć na proces: ps -o pid,rss,cmd -C php-fpm | sort -k2 -n – uśrednij RSS dla typowego obciążenia.
- Logi FPM: tail -f /var/log/php-fpm/error.log oraz slowlog zdefiniowany w puli.
- Status FPM: udostępnij pm.status_path za firewallem i sprawdzaj active/idle/listen queue.
- Opcache: użyj skryptu statusowego (np. opcache-gui) do weryfikacji hit rate i fragmentacji.
- Serwer WWW: w Nginx monitoruj upstream_response_time i statusy 499/502/504, w Apache – mod_status.
- Limity systemowe: ulimit -n (pliki), sysctl kern.* / vm.*, RLIMIT_NOFILE w konfiguracji FPM.
- Połączenia do bazy: narzędzia profilujące (EXPLAIN, slow query log), connection pool w driverze.
Perspektywy: procesy krótkotrwałe kontra long-running
Standardowy model “każde żądanie osobnym procesem” jest prosty i stabilny, ale bywa kosztowny w starcie. Alternatywą są serwery aplikacyjne w PHP (Swoole, RoadRunner), które utrzymują długowieczne workery i obsługują wiele żądań w jednym procesie, czasem z event-loop. Zyskujesz niższy narzut i potencjalnie wyższą przepustowość, lecz musisz dbać o brak wycieków, ręczne “odświeżanie” stanu między żądaniami i zgodność bibliotek. Nie każdy hosting to wspiera, dlatego w środowiskach współdzielonych standardowy FPM pozostaje złotym środkiem.
Checklist: kontrola procesów PHP w praktyce
- Zmierz zużycie RAM na proces i wylicz pm.max_children z zapasem.
- Dobierz tryb pm do charakteru ruchu (ondemand dla nieregularnego, static/dynamic dla stabilnego).
- Włącz slowlog i status FPM, patrz na listen queue i slow requests.
- Ustaw racjonalne request_terminate_timeout i max_execution_time.
- Dbaj o procesy kolejkowe: osobne limity, nadzór systemd/supervisord, obsługa sygnałów.
- Dopilnuj warstwy cache (aplikacyjnej i HTTP), CDN dla statyków.
- Monitoruj bazy i zewnętrzne API – wiele problemów nie leży w PHP.
- Automatyzuj deploy: test konfiguracji, warm-up, graceful reload, health-check.
- Na hostingu współdzielonym – pilnuj EP/NPROC i dopasuj aplikację do limitów.
- Zadbaj o bezpieczeństwo i separację użytkowników (user/group, chroot, clear_env).
Równowaga między infrastrukturą a aplikacją
Konfiguracja FPM i serwera WWW może dużo zmienić, ale nie zastąpi mądrych decyzji architektonicznych. Jeśli wąskim gardłem są zapytania do bazy, dołóż indeksy i wprowadź cache warstwy danych. Jeśli problemem jest metryczna liczba żądań, zaangażuj CDN, cache HTTP i edge logic. Czasem lepiej zmniejszyć liczbę workerów i stabilizować opóźnienia, niż “przewentylować” CPU i RAM, powodując lawinę OOM-ów. Świadome kompromisy między przepustowością, opóźnieniami i kosztami to sedno właściwej kontroli procesów PHP.
Podsumowanie: kontrola procesów jako podstawa stabilności
Kontrola procesów PHP obejmuje kilka warstw: planowanie zasobów, ustawienia puli FPM, diagnostykę (status, logi, slowlog), świadome limity czasu i pamięci, rozsądną politykę recyklingu procesów, optymalizację kodu i bazy oraz integrację z infrastrukturą (load balancer, CDN, monitoring, APM). Ostatecznym celem jest przewidywalna praca aplikacji pod obciążeniem, odporność na skoki ruchu i szybka diagnoza problemów. Zadbaj o kluczowe elementy – PHP-FPM, opcache, pamięć, cache, monitoring, wydajność, timeouty, procesy, bezpieczeństwo, skalowanie – a Twoje środowisko będzie nie tylko szybkie, ale i stabilne, także w nieprzewidywalnych warunkach ruchowych.
