HostiServer
2026-06-04 15:11
Оптимізація PHP-сервера у 2026: PHP-FPM, OPcache, JIT та профілювання
Оптимізація PHP-сервера у 2026: PHP-FPM, OPcache, JIT та профілювання
PHP запустився у 1995 році як набір CGI-скриптів на Perl для відстеження відвідувачів сторінки. Через тридцять років він обслуговує близько 76% усього вебу (W3Techs, 2026) — від однієї людини, яка веде блог на WordPress, до Slack, Wikipedia і Etsy. Жодна інша мова не пройшла подібний шлях з настільки збереженою сумісністю: код, написаний у 2010-му, у переважній більшості випадків запуститься на PHP 8.4 без правок.
Те, що змінилось драматично — це спосіб запуску PHP на сервері. У 2010-му стандартом був mod_php в Apache: один процес Apache = один інтерпретатор PHP, повільно, споживливо до RAM, але просто. У 2026-му стандарт — PHP-FPM з окремим пулом воркерів, OPcache з прекомпільованим байткодом у пам'яті, JIT-компілятор, що генерує машинні інструкції для гарячих ділянок коду. Усе це разом дає продуктивність у 5-10 разів вищу за mod_php, але вимагає налаштування.
Проблема в тому, що apt пакети ставлять PHP з консервативними значеннями за замовчуванням — такими, щоб запустилось і на VPS з 512 МБ RAM, і на сервері з 64 ГБ. У результаті 90% серверів у Інтернеті працюють із конфігами, які ніяк не відповідають їхньому залізу. Це стаття про те, як виправити цю ситуацію — без академічної теорії, з конкретними числами і реальними прикладами для PHP 8.4 на Ubuntu 24.04 LTS.
ℹ️ Перетин з іншими нашими матеріалами: базове встановлення PHP, Nginx і Apache детально розкрите у статті «Як розмістити PHP-сайт». Тонкощі тюнингу під високе навантаження (CPU vs ядра, NVMe vs SATA, мікро-кешування FastCGI) — у статті «Серверна конфігурація для високонавантажених сайтів». Тут — те, що йде між ними: фактичний тюнинг FPM, OPcache, JIT, профілювання, специфічна для PHP безпека.
Перший крок: знайти, що саме треба правити
Перед будь-якою оптимізацією треба точно знати, які саме файли конфігурації PHP читає на вашому сервері. На Ubuntu їх може бути кілька версій паралельно (PHP 8.1, 8.2, 8.3, 8.4 — все ставиться поряд), і часто-густо ваші зміни летять не туди, куди треба.
Команди, які дають точну відповідь
php -r 'echo php_ini_loaded_file() . PHP_EOL;'
# Виводить шлях до основного php.ini для CLI
php-fpm8.4 -i | grep "Loaded Configuration"
# Шлях до php.ini для FPM (часто це /etc/php/8.4/fpm/php.ini)
php -r 'echo phpversion() . PHP_EOL;'
# Версія PHP, з якою працює CLI
systemctl status php8.4-fpm
# Чи запущений FPM-сервіс і який саме
⚠️ Часта пастка: налаштування для CLI (/etc/php/8.4/cli/php.ini) і FPM (/etc/php/8.4/fpm/php.ini) — це різні файли. Якщо ви правите CLI-конфіг, а ваш сайт працює через FPM, зміни не застосуються. phpinfo() у браузері покаже саме той php.ini, який обслуговує веб.
Структура каталогів PHP на Ubuntu
| Шлях | Що там лежить |
|---|---|
/etc/php/8.4/fpm/php.ini |
Головний конфіг для веб-запитів (FPM) |
/etc/php/8.4/cli/php.ini |
Конфіг для CLI (composer, artisan, wp-cli) |
/etc/php/8.4/fpm/pool.d/www.conf |
Конфіг FPM-пулу — найважливіший файл для тюнингу |
/etc/php/8.4/mods-available/ |
Конфіги розширень (opcache.ini, redis.ini, тощо) |
/var/log/php8.4-fpm.log |
Логи FPM (slow log, помилки запуску воркерів) |
Якщо у вас інша версія PHP — підставте її номер замість 8.4. На старіших Ubuntu (18.04, 20.04) шляхи можуть починатися з /etc/php5 або /etc/php/7.x.
PHP-FPM Pool: ключ до тримання навантаження
FPM-пул — це те, скільки одночасних PHP-процесів сервер може обслуговувати. Якщо налаштовано неправильно, сайт буде або «падати» від нестачі воркерів, або «вбивати» сервер через нестачу RAM. Це найважливіший конфіг для перформансу, і саме тут роблять найбільше помилок.
Три режими роботи: dynamic / static / ondemand
| Режим | Як працює | Для кого |
|---|---|---|
dynamic |
FPM тримає N воркерів готових, створює нові за потребою до max, прибирає неактивні | Більшість сайтів — баланс RAM і чуйності системи |
static |
FPM тримає рівно pm.max_children воркерів увесь час |
Високонавантажені сайти зі стабільним трафіком, де економія RAM не критична |
ondemand |
Воркери створюються тільки коли є запит, помирають після таймауту | Низькотрафічні сайти на VPS з малою RAM |
Як розрахувати pm.max_children
Це число, яке найбільше впливає на стабільність. Формула:
pm.max_children = (Total RAM − RAM зайнята системою) / Середня RAM на один PHP-процес
На практиці один PHP-процес з WordPress і середнім набором плагінів їсть 50-80 МБ RAM під час обробки запиту. Для Laravel-додатків — 80-120 МБ. Magento 2 — 200-300 МБ. Заміряти точно можна командою:
ps -ylC php-fpm8.4 --sort:rss | awk '{sum+=$8; count++} END {print "Average:", sum/count/1024, "MB"}'
⚠️ Завжди залишайте безпечний буфер — 10-15% від отриманого числа pm.max_children на випадок різкого сплеску споживання пам'яті окремими воркерами. Якщо за формулою вийшло 25, виставляйте 20-22. Інакше при піковому трафіку всі воркери одночасно поглинуть залишок RAM, і Linux OOM-killer почне вбивати процеси — інколи саме MySQL або Nginx, бо вони можуть мати вищі OOM-scores.
Приклад розрахунку для типових серверів
| Сервер | Доступно для PHP | RAM на процес | pm.max_children |
|---|---|---|---|
| VPS 2 GB RAM, WordPress | 1.2 GB (бо MySQL+Nginx їдять ~800 MB) | 60 MB | 17 (формула дає 20, мінус 15% буфер) |
| VPS 4 GB RAM, WooCommerce | 2.5 GB | 100 MB | 22 (формула дає 25, мінус буфер) |
| VPS 8 GB RAM, Laravel API | 5.5 GB | 100 MB | 48 (формула дає 55, мінус буфер) |
| Dedicated 32 GB, Magento 2 | 24 GB (велика частина на Redis і MySQL) | 250 MB | 82 (формула дає 96, мінус буфер) |
Оптимальний конфіг пулу для dynamic-режиму
Файл /etc/php/8.4/fpm/pool.d/www.conf:
; Базові налаштування пулу
pm = dynamic
pm.max_children = 25
pm.start_servers = 5
pm.min_spare_servers = 3
pm.max_spare_servers = 8
pm.max_requests = 500
; Slow log — записує запити повільніші за 5 секунд
slowlog = /var/log/php8.4-fpm-slow.log
request_slowlog_timeout = 5s
; Status page для моніторингу — дивіться з 127.0.0.1
pm.status_path = /fpm-status
ping.path = /fpm-ping
ℹ️ Що робить кожен параметр:
pm.start_servers— скільки воркерів запустити при старті FPMpm.min_spare_servers— мінімум вільних (готових прийняти запит) воркерівpm.max_spare_servers— максимум вільних воркерів (понад це — починає вбивати зайвих)pm.max_requests = 500— воркер обслуговує 500 запитів і перезавантажується. Запобігає витокам пам'яті у плагінах третіх сторін
Slow log — недооцінений інструмент
Налаштування request_slowlog_timeout змушує FPM записувати у лог трасу будь-якого запиту, який виконується довше зазначеного часу. Це дозволяє знаходити «вузькі місця» без встановлення складних профайлерів. Приклад того, що з'являється у slow log:
[03-Jun-2026 14:23:15] [pool www] pid 12453
script_filename = /var/www/site/wp-cron.php
[0x00007f5e2c4a8e30] curl_exec() /var/www/site/wp-includes/class-wp-http-curl.php:155
[0x00007f5e2c4a8e30] request() /var/www/site/wp-includes/class-wp-http.php:413
Тут одразу видно: запит висить на curl_exec() у wp-cron — найімовірніше, плагін намагається достукатися до зовнішнього API, який не відповідає. Без slow log ця проблема залишилася б невидимою.
OPcache: каже одне число, що змінює все
OPcache — це вбудований у PHP байткод-кеш. Без нього PHP при кожному запиті заново читає всі .php-файли з диску, парсить їх у байткод і тільки потім виконує. З увімкненим OPcache байткод зберігається в RAM, і повторні виклики того ж файлу читають уже скомпільовану версію.
Це дає прискорення у 3-5 разів для будь-якого PHP-додатку без зміни жодного рядка коду. Це не теоретична цифра — це реальна різниця, яку видно на будь-якому профайлері.
Перевірити, чи OPcache увімкнений
php -r 'echo opcache_get_status() ? "OPcache: ON" : "OPcache: OFF"; echo PHP_EOL;'
Якщо OFF — увімкніть. На Ubuntu пакет називається php8.4-opcache (зазвичай уже встановлений за замовчуванням, але вимкнений у конфізі).
Робочий конфіг OPcache для продакшну
Файл /etc/php/8.4/mods-available/opcache.ini:
opcache.enable=1
opcache.enable_cli=0
opcache.memory_consumption=256
opcache.interned_strings_buffer=16
opcache.max_accelerated_files=20000
opcache.revalidate_freq=2
opcache.validate_timestamps=1
opcache.save_comments=1
opcache.fast_shutdown=1
opcache.jit=tracing
opcache.jit_buffer_size=128M
Що означає кожен параметр
| Параметр | Що робить і як обрати значення |
|---|---|
memory_consumption=256 |
Скільки RAM віддати кешу. 128 МБ вистачає для маленького WordPress, 256 МБ — для звичайного бізнес-сайту, 512 МБ — для Magento або великого Laravel. Якщо мало — у логах буде «opcache.max_accelerated_files reached» |
interned_strings_buffer=16 |
Окремий буфер для кешу повторюваних рядків. 16 МБ — норма для більшості сайтів |
max_accelerated_files=20000 |
Скільки файлів кешувати. Перевірте у моніторингу — якщо досягається ліміт, збільшуйте. WordPress з 30 плагінами легко набирає 8-12 тисяч файлів |
validate_timestamps=1 |
Чи перевіряти, чи файл змінився на диску. 1 — перевіряти, 0 — НЕ перевіряти |
revalidate_freq=2 |
Як часто перевіряти зміни файлів (у секундах). При validate_timestamps=0 цей параметр ігнорується |
Важливий нюанс: validate_timestamps=0 для продакшну
Це найбільш суперечливий параметр. Якщо встановити validate_timestamps=0, PHP перестає перевіряти зміни файлів — і будь-яке оновлення коду треба супроводжувати ручним очищенням OPcache (php8.4-fpm reload або opcache_reset()). Натомість продуктивність зростає ще на 5-10%, бо нема системних викликів stat() при кожному запиті.
Чи варто? Залежить від процесу деплою. Якщо у вас CI/CD pipeline з автоматичним перезавантаженням FPM після релізу — точно так. Якщо ви оновлюєте сайт через FTP вручну і забуваєте перезавантажити сервіс — краще залишити validate_timestamps=1.
⚠️ Парадокс OPcache: після оновлення PHP-коду на диску, OPcache не побачить зміни до перезапуску FPM, якщо validate_timestamps=0. Це регулярно ламає WordPress-сайти у тих, хто читав статтю «як прискорити PHP», скопіював налаштування з продакшну і не зрозумів, що було за ними.
JIT compiler: коли вмикати, а коли — НІ
JIT (Just-In-Time compiler) з'явився у PHP 8.0 і дозволяє компілювати «гарячий» код у машинні інструкції процесора, обходячи інтерпретатор. Звучить як магія прискорення, але на практиці все цікавіше.
Де JIT реально допомагає
- CPU-bound обчислення: рендеринг зображень, криптографія, парсинг великих структур даних, математичні алгоритми. Тут JIT може дати прискорення у 1.5-3 рази.
- CLI-скрипти: довгі обробки даних, фонові обчислення, наукові розрахунки.
Де JIT не допомагає, а інколи шкодить
- Типові веб-додатки (WordPress, Drupal, Laravel): вони I/O-bound (більшість часу проводять у запитах до БД, читанні файлів, очікуванні відповідей API). Прискорення від JIT — у межах 1-3%, що часто непомітно на тлі звичайної дисперсії.
- Сайти з помилками сегментації: JIT у деяких випадках конфліктує зі сторонніми розширеннями. Якщо у логах з'явилися крахи воркерів після увімкнення — це перша гіпотеза.
Налаштування JIT
JIT керується через два параметри в opcache.ini:
opcache.jit=tracing
opcache.jit_buffer_size=128M
| Значення opcache.jit | Що означає |
|---|---|
tracing |
Найагресивніший режим, компілює «гарячі» цикли і функції. Найкраща продуктивність |
function |
Компілює окремі функції. М'якший режим, менше ризику |
disable або 0 |
JIT вимкнений |
Рекомендація: увімкніть tracing, заміряйте продуктивність до і після, тримайте увімкненим тільки якщо різниця помітна. На сайті з типовим CMS-навантаженням JIT може просто з'їсти 128 МБ RAM і нічого не дати в обмін.
Як заміряти ефект від JIT
Найпростіший спосіб — два інструменти разом: Apache Bench для навантажувального тесту і моніторинг через top:
# Тест без JIT (попередньо вимкніть JIT і перезавантажте FPM)
ab -n 1000 -c 10 https://yoursite.com/
# Тест з JIT (увімкніть, перезавантажте FPM)
ab -n 1000 -c 10 https://yoursite.com/
# Порівняйте "Requests per second" і "Time per request"
Якщо різниця менше 5% — JIT для вашого випадку економічно безглуздий, можна вимкнути і повернути 128 МБ RAM у систему.
Realpath cache: маленький параметр, який рятує SSD
Параметр, про який рідко говорять, але який має непропорційно великий ефект на сайтах з великою кількістю файлів (WordPress з 50+ плагінами, Magento, великі Laravel-проєкти).
Кожного разу, коли PHP підключає файл через require або include, він резолвить шлях через серію stat() системних викликів. Для відносного шляху типу ../vendor/symfony/finder/Finder.php це означає декілька десятків викликів до файлової системи. Realpath cache зберігає вже розв'язані шляхи в пам'яті.
Налаштування realpath_cache
У php.ini:
realpath_cache_size = 4096K
realpath_cache_ttl = 600
За замовчуванням стоїть 256K — цього вистачає на ~150 кешованих шляхів. Для WordPress з пристойним набором плагінів треба мінімум 2-4 MB. Перевірити поточне використання:
php -r 'echo realpath_cache_size() / 1024 . " KB used\n";'
# Скільки байтів реально займає кеш на даний момент
php -r 'print_r(realpath_cache_get());'
# Повний список усіх кешованих шляхів (корисно для діагностики)
Якщо число з першої команди близьке до значення realpath_cache_size у php.ini — кеш переповнюється, треба збільшувати ліміт.
💡 З досвіду: на WordPress-сайті з 40 плагінами і WooCommerce збільшення realpath_cache з 256K до 4M зменшує час генерації сторінки приблизно на 15-20% за рахунок самого тільки кешу шляхів. Прихована перемога, яку часто пропускають у гонитві за OPcache і Redis.
Профілювання: знайти, що насправді гальмує
До цього моменту ми тюнили «вгадуючи»: збільшили OPcache, збільшили pool, увімкнули JIT. Але справжня оптимізація починається тоді, коли ви бачите, де саме код проводить час. Без профілювання ви тюните не свій сайт, а абстрактного «середнього сайт».
Інструменти за зростанням складності
| Інструмент | Для чого | Складність |
|---|---|---|
| FPM slow log | Знайти запити-«тормози» без додаткових інструментів | Низька |
| OPcache GUI (opcache-gui) | Подивитись, як саме використовується OPcache, статистика hit ratio | Низька |
| Xdebug profiler | Детальне профілювання з cachegrind-форматом, відкривається у KCachegrind | Середня |
| Blackfire / Tideways | Production-ready APM, працює з мінімальним оверхедом | Висока (комерційні) |
| strace / perf | Системний рівень — що саме PHP робить на рівні OS | Висока |
З чого почати: OPcache GUI
OPcache GUI — це маленький .php-скрипт, який показує детальну статистику використання кешу. Встановлюється за хвилину:
cd /var/www/site/
wget https://raw.githubusercontent.com/amnuts/opcache-gui/master/index.php -O opcache-status.php
Після цього відкрийте у браузері https://yoursite.com/opcache-status.php — побачите memory usage, hit ratio, кількість кешованих файлів і список того, що в кеші. Якщо hit ratio менше 99% — це сигнал, що memory_consumption замалий.
🚨 Не залишайте opcache-status.php у відкритому доступі. Він показує внутрішню структуру файлової системи, версію PHP і список усіх плагінів — інформація, яка значно полегшує життя атакуючому. Або захистіть його nginx-правилом allow/deny з вашого офісного IP, або видаліть після перевірки.
Xdebug profiler — тонке профілювання
Xdebug — це найвідоміший дебагер і профайлер для PHP. Для профілювання його використовують у режимі profile:
; У /etc/php/8.4/mods-available/xdebug.ini
xdebug.mode = profile
xdebug.output_dir = /tmp/xdebug
xdebug.start_with_request = trigger
Після цього додайте параметр ?XDEBUG_TRIGGER=1 до URL — і Xdebug запише профіль виклику у каталог /tmp/xdebug. Відкрийте отриманий cachegrind.out файл у KCachegrind або QCachegrind — побачите ієрархію викликів з часом, відсотками і кількістю викликів.
⚠️ Не залишайте Xdebug в режимі profile на продакшні постійно. Він додає 20-100% оверхеду до часу виконання. Використовуйте тільки на час діагностики, потім вимкніть або переключіть на xdebug.mode = off.
PHP-специфічна безпека: те, що не покривають інші статті
Загальна безпека сервера (HTTPS, fail2ban, security headers) детально розкрита у нашій статті про захист сайту від хакерів. Тут — суто PHP-рівень: параметри, які можна виставити в php.ini і які закривають специфічні для PHP вектори атаки.
expose_php = Off
За замовчуванням PHP додає заголовок X-Powered-By: PHP/8.4.X до кожної відповіді. Це безкоштовна інформація для атакуючого: він точно знає вашу версію і може шукати CVE під неї. Вимкнути просто:
expose_php = Off
Перевірити після перезапуску FPM:
curl -I https://yoursite.com/ | grep -i powered
# Якщо нічого не виводить — заголовок прибраний
disable_functions: що дійсно варто вимикати
Це список PHP-функцій, які ніколи не виконуватимуться. Якщо плагін або вразливість намагається через них вирватися на рівень shell — PHP просто видасть помилку. Розумний мінімум для більшості сайтів:
disable_functions = exec,passthru,shell_exec,system,proc_open,popen,curl_multi_exec,parse_ini_file,show_source,phpinfo
⚠️ Підводний камінь: деякі CMS і плагіни легально використовують ці функції. WordPress може використовувати proc_open для оновлень. Magento використовує shell_exec у деяких сценаріях. Перед застосуванням — перевірте на staging-копії. Якщо щось ламається, прибирайте функції зі списку по черзі, поки не знайдете винуватця.
open_basedir: ізоляція PHP від файлової системи
Цей параметр обмежує, до яких каталогів PHP-скрипт може звертатися. Навіть якщо зловмисник завантажив shell у /uploads, він не зможе через нього прочитати /etc/passwd або /var/log:
open_basedir = /var/www/yoursite/:/tmp/
Усе поза цими каталогами стає недоступним для функцій типу file_get_contents, fopen, include. Це один з найсильніших захистів на рівні PHP, але часто пропускається.
allow_url_fopen = Off (де можливо)
За замовчуванням PHP дозволяє відкривати URL так само як файли: file_get_contents('https://...'). Зловмисник може цим скористатися для:
- SSRF (Server-Side Request Forgery) — змусити сервер ходити по внутрішніх ресурсах
- Remote File Inclusion — підключити шкідливий PHP-код з зовнішнього сервера
Якщо ваш код не звертається до зовнішніх URL через file_get_contents (а замість цього використовує cURL або Guzzle, як прийнято у сучасних додатках) — вимкніть:
allow_url_fopen = Off
allow_url_include = Off
allow_url_include треба вимикати завжди — це окремий вектор для Remote File Inclusion і у 99% випадків нікому не потрібен.
session.cookie_httponly, session.cookie_secure
Налаштування PHP-сесій. Без них JavaScript на сторінці може прочитати session cookie (наприклад, через XSS-вразливість), або session cookie буде передаватися по HTTP в обхід HTTPS:
session.cookie_httponly = 1
session.cookie_secure = 1
session.cookie_samesite = "Strict"
session.use_strict_mode = 1
Топ помилок конфігурації, які я бачу на чужих серверах
- memory_limit = -1 «на всякий випадок». Це означає «без обмежень». Один зациклений скрипт може з'їсти всю RAM сервера. Має стояти конкретне число: 256M, 512M, 1024M.
- max_execution_time = 0. Те саме що вище — скрипт без таймауту може висіти годинами, тримаючи воркер FPM. 60-90 секунд — нормальний діапазон для більшості сайтів.
- display_errors = On у продакшні. Помилки виводяться користувачам у браузер разом зі шляхами до файлів, версіями бібліотек і інколи фрагментами SQL. Видавайте їх тільки на dev-сервері. У продакшн —
display_errors = Off, log_errors = On. - pm.max_children обраний наосліп. Або поставили 5 і сайт «падає» при першому ж сплеску трафіку, або поставили 200 і сервер захлинається. Розрахуйте формулою з секції про FPM.
- OPcache з memory_consumption=64. Стандартне значення з більшості туторіалів. Для будь-якого реального сайту з CMS це замало, кеш постійно переповнюється і скидається. Мінімум 128, реалістично 256-512.
- opcache.validate_timestamps=0 без CI/CD. Після деплою сайт показує стару версію коду, а адміни в розпачі шукають баги. Або ставте 1, або налаштовуйте автоматичний reload FPM після релізу.
- JIT з buffer_size=512M, бо «більше = краще». На сайті з CMS це з'їдає півгігабайта RAM ні за що. JIT використовує тільки те, що йому реально треба — починайте з 64-128M.
- info.php / phpinfo.php залишився у production. Тимчасовий файл, який створили для перевірки, але забули видалити. Атакуючий бачить версію PHP, всі завантажені модулі, шляхи, переменні середовища. Видаляйте відразу після перевірки — детальніше про небезпеку розкриття версій ПЗ і способи приховати їх ми писали у матеріалі про перевірку версії Apache.
🚀 PHP-сервер з правильним налаштуванням «з коробки»
Налаштування FPM, OPcache, JIT і профілювання — це не складно, але вимагає часу і досвіду. На Hostiserver більшість цих речей уже налаштовано за замовчуванням, а решту допомагає поставити техпідтримка під ваш конкретний проєкт і навантаження.
💻 Cloud (VPS) Хостинг
- Від $19.95/міс — KVM-ізоляція, повний root-доступ
- PHP 8.4 і 8.5 з оптимізованим php.ini для CMS і фреймворків з коробки
- OPcache і JIT увімкнені та налаштовані під ваш профіль навантаження
- PHP-FPM pool tuning — допомога з розрахунком pm.max_children під вашу RAM і CMS
- Slow log і моніторинг — інженери допоможуть знайти вузькі місця у вашому коді
- 24/7 інженерна підтримка — <10 хв відповідь, реальні DevOps-інженери
🖥️ Виділені Сервери
- Від $90/міс — повна ізоляція, ресурси тільки для вашого проєкту
- Тюнинг під високе навантаження — Magento, WooCommerce, великі Laravel-проєкти
- Безкоштовна міграція з іншого провайдера з перевіркою конфігурації
- Профілювання і аудит вашого PHP-стеку при онбордингу
- SLA 99.9% uptime з гарантією у договорі
💬 Не впевнені, який варіант вам необхідний?
💬 Напишіть нам і ми зі всім допоможемо!
Часті питання
- На яку версію PHP оновлюватися у 2026 році?
Мінімальна підтримувана версія — PHP 8.3 (підтримка завершується наприкінці 2026). Оптимальна для більшості проєктів — PHP 8.4, як стабільна, з активним security-супроводом. PHP 8.5 — поточна актуальна версія для тих, хто стежить за релізами і хоче нові фічі мови (property hooks, asymmetric visibility). До кінця року очікується реліз PHP 8.6. Все, що нижче PHP 8.2, не отримує security-патчів і несе ризики.
- Чи варто переходити з mysqli на PDO?
Обидва розширення підтримуються і не deprecated. PDO дає переваги, якщо вам важлива портабельність між БД (MySQL, PostgreSQL, SQLite одним кодом) або зручність prepared statements у named-параметрах. mysqli залишається швидшим на 5-10% для чистих MySQL-запитів і має деякі MySQL-специфічні фічі (наприклад, multi-query, async queries). Для нового коду рекомендую PDO; для існуючого — не варто переписувати тільки заради переходу. Окремо про захист БД на серверному рівні і налаштування користувачів — у нашій статті про безпеку MySQL на хостингу.
- Що пріоритетніше: OPcache чи Redis для кешування?
Це різні рівні кешу. OPcache кешує скомпільований байткод — без нього PHP читає і парсить .php файли при кожному запиті. Redis кешує дані додатку — результати SQL-запитів, рендеринг шаблонів, об'єкти. OPcache має бути увімкнений завжди — це базова річ. Redis додається після OPcache, коли вже бачите, що вузьке місце — це БД-запити. Не «один замість іншого», а «обидва послідовно».
- Як зрозуміти, що сервер тримає поточне навантаження, чи треба апгрейдити?
Кілька маркерів. У логах FPM з'являється «WARNING: server reached pm.max_children setting» — пул переповнений, треба або апгрейдити RAM і збільшувати max_children, або шукати, чому запити такі повільні. У
topпоказник Load Average наближається до кількості ядер або перевищує її — сервер працює на межі. Slow log регулярно записує запити >5 секунд — є код, який треба профілювати.opcache_get_status()показує hit_ratio менше 99% — OPcache замалий. Якщо все це лікується тюнингом, апгрейд не потрібен. Якщо параметри вже на стелі — час до більшого тарифу; вибір між VPS, виділеним і керованим сервером ми розбирали у окремому матеріалі про вибір типу сервера.
- Чи потрібно щось окремо налаштовувати для Laravel або Symfony?
Базовий PHP-стек однаковий. Специфіка для фреймворків зводиться до чотирьох речей. По-перше, OPcache preloading (PHP 7.4+) — для Laravel і Symfony дає помітне прискорення, бо фреймворкове ядро завантажується у пам'ять один раз при старті FPM. По-друге, кеш конфігурації самого фреймворка:
artisan config:cache,artisan route:cache,artisan view:cacheдля Laravel;console cache:warmup --env=prodдля Symfony. По-третє, переконайтеся, щоAPP_DEBUG=falseу продакшні — інакше всі помилки показуються клієнтам, а сам debug-режим серйозно сповільнює роботу. По-четверте,memory_limitдля CLI має бути вищим, ніж для FPM — консольні команди (міграції, черги, генерація профілів, експорт даних) часто потребують 512M-1G, тоді як веб-запитам вистачає 256M.
- Чому після оновлення коду сайт показує стару версію?
Майже завжди — це OPcache з
validate_timestamps=0або великимrevalidate_freq. PHP кешує скомпільований байткод і не помічає, що файли на диску змінилися. Рішення:sudo systemctl reload php8.4-fpmпісля кожного релізу, або викликатиopcache_reset()з PHP-скрипта (можна зробити hook у CI/CD), або встановитиvalidate_timestamps=1з малимrevalidate_freq(наприклад, 2 секунди — мінімальний штраф продуктивності і автоматичне підхоплення змін).
- Чи безпечно вмикати JIT на бойовому сервері?
Майже завжди так, але з застереженнями. JIT у PHP 8.4 уже стабільний і використовується у продакшні великими компаніями. Але є ситуації, де його краще не вмикати: якщо у вас сторонні бінарні розширення (особливо самописні), які не тестувалися з JIT; якщо у логах після увімкнення з'являються segfault'и воркерів; якщо ви бачите, що ваш сайт I/O-bound (більшість часу у запитах до БД) — JIT просто з'їсть RAM без віддачі. Стандартна порада: увімкніть на staging, навантажувальний тест, моніторинг — якщо все добре протягом тижня, виносіть на продакшн.