PHP-FPM (Fast Process Manager) – це окрема реалізація обробника FastCGI для виконання PHP скриптів. На базі зв’язки веб-сервера NGINX (який обробляє статику) і PHP-FPM ви можете побудувати більш швидкий і продуктивний веб-сервер для своїх веб-проектів в порівнянні з використанням «класичної» зв’язки NGINX, Apache і модуль mod_php (стек LAMP).

ЛЕМП – набір програмного забезпечення з відкритим вихідним кодом, яка зазвичай встановлюється спільно для запуску на сервері для розміщення веб-сайтів і веб-додатків. Цей абревіатурою обозначающет набір ОС Linux з веб-сервером Nginx (Він замінює Апачі в більш поширеному стеку ЛАМПА), з BD MySQL (MariaDB) та c php для обробки динамічних даних.

У даній статті ми розглянемо установку і оптимізацію стека LEMP для розміщення навантаженого веб-проекту на сервері з CentOS 7 на базі зв’язки NGINX + PHP-FPM + MariaDB / MySQL + встановимо для сайту SSL сертифікату Let’s Encrypt.

Підключення сховища, оновлення сервера

Так як установка проводиться на знову встановленому сервері з CentOS, потрібно підключити популярний репозиторій EPEL і оновити на сервері всі пакети.

# yum install epel-release -y
# yum update -y

Репозиторій встановився, але пакетів для оновлень не знайдено, так як встановлений свіжий образ CentOS.

centos - оновлення сервера

Установка і настройка веб-сервера Nginx

Для установки свіжої версії Nginx, Підключимо репозиторій розробника, виконавши команду:

# rpm -Uvh http://nginx.org/packages/centos/7/noarch/RPMS/nginx-release-centos-7-0.el7.ngx.noarch.rpm

Або створивши конфігураційний файл сховища /etc/yum.repos.d/nginx.repo наступного змісту:

[nginx]
name=nginx repo
baseurl=http://nginx.org/packages/centos/7/$basearch/
gpgcheck=0
enabled=1

Якщо ви використовуєте CentOS 8, змініть версію в URL.

Встановіть пакет веб-сервера Nginx за допомогою менеджера пакетів yum (або dnf):

# yum install nginx -y

установка nginx веб-сервера в centos linux

Тепер можна запустити nginx і додати його в автозавантаження за допомогою systemctl:

# systemctl start nginx
# systemctl enable nginx

Created symlink from /etc/systemd/system/multi-user.target.wants/nginx.service to /usr/lib/systemd/system/nginx.service.

Щоб перевірити, що веб-сервер працює, відкрийте в браузері IP-адреса сервера.

nginx встановлений

Якщо у вас тестова сторінка не відкрилася, перевірте налаштування дозволених служб, портів, зон в firewalld на своєму сервері.

Налаштуємо конфігураційний файл для окремого домену build-centos.info. Створимо для сайту окрему директорію і сам конфігураційний файл:

# mkdir -p /var/www/build-centos.info && mkdir -p /var/www/build-centos.info/log

Відкриємо файл конфігурації:

# nano /etc/nginx/conf.d/build-centos.info.conf

І додамо в нього наступне вміст:

server {
    listen 80;
    server_name build-centos.info;
    root /var/www/build-centos.info;
    index index.php index.html index.htm;
    access_log /var/www/build-centos.info/log/access.log main;
    error_log /var/www/build-centos.info/log/error.log;

    location / {
    return 301 https://build-centos.info$request_uri;
    }

    location ~* ^.+.(js|css|png|jpg|jpeg|gif|ico|woff)$ {
    return 301 https://build-centos.info$request_uri;
    }

    location ~ .php$ {
    return 301 https://build-centos.info$request_uri;
    }

    location = /favicon.ico {
    log_not_found off;
    access_log off;
    }

    location = /robots.txt {
    rewrite ^ /robots.txt break;
    allow all;
    log_not_found off;
    access_log off;
    }

    location ~ /.ht {
    deny all;
    }
}

server {
     listen  80;
     server_name  www.build-centos.info;
     rewrite ^ https://build-centos.info$request_uri? permanent;
}

server {
    listen 443 ssl http2;
    server_name build-centos.info;
    root /var/www/build-centos.info;
    index index.php index.html index.htm;
    access_log /var/www/build-centos.info/log/ssl-access.log main;
    error_log /var/www/build-centos.info/log/ssl-error.log;

    keepalive_timeout           60;
    ssl_certificate             /etc/letsencrypt/live/build-centos.info/fullchain.pem;
    ssl_certificate_key         /etc/letsencrypt/live/build-centos.info/privkey.pem;
    ssl_protocols               TLSv1 TLSv1.1 TLSv1.2;
    ssl_ciphers 'ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-AES256-GCM-SHA384:DHE-RSA-AES128-GCM-SHA256:DHE-DSS-AES128-GCM-SHA256:kEDH+AESGCM:ECDHE-RSA-AES128-SHA256:ECDHE-ECDSA-AES128-SHA256:ECDHE-RSA-AES128-SHA:ECDHE-ECDSA-AES128-SHA:ECDHE-RSA-AES256-SHA384:ECDHE-ECDSA-AES256-SHA384:ECDHE-RSA-AES256-SHA:ECDHE-ECDSA-AES256-SHA:DHE-RSA-AES128-SHA256:DHE-RSA-AES128-SHA:DHE-DSS-AES128-SHA256:DHE-RSA-AES256-SHA256:DHE-DSS-AES256-SHA:DHE-RSA-AES256-SHA:AES128-GCM-SHA256:AES256-GCM-SHA384:AES128-SHA256:AES256-SHA256:AES128-SHA:AES256-SHA:AES:CAMELLIA:DES-CBC3-SHA:!aNULL:!eNULL:!EXPORT:!DES:!RC4:!MD5:!PSK:!aECDH:!EDH-DSS-DES-CBC3-SHA:!EDH-RSA-DES-CBC3-SHA:!KRB5-DES-CBC3-SHA';
    add_header                  Strict-Transport-Security 'max-age=604800';

    location / {
    try_files $uri $uri/ /index.php?$args;
    }

    location ~* ^.+.(js|css|png|jpg|jpeg|gif|ico|woff)$ {
    access_log off;
    expires max;
    }

    location ~ .php$ {
    try_files  $uri =404;
    fastcgi_pass   unix:/var/run/php-fpm/php-fpm.sock;
    fastcgi_index index.php;
    fastcgi_param DOCUMENT_ROOT /var/www/build-centos.info;
    fastcgi_param SCRIPT_FILENAME /var/www/build-centos.info/$fastcgi_script_name;
    fastcgi_param PATH_TRANSLATED /var/www/build-centos.info/$fastcgi_script_name;
    include fastcgi_params;
    fastcgi_param QUERY_STRING $query_string;
    fastcgi_param REQUEST_METHOD $request_method;
    fastcgi_param CONTENT_TYPE $content_type;
    fastcgi_param CONTENT_LENGTH $content_length;
    fastcgi_param HTTPS on;
    fastcgi_intercept_errors on;
    fastcgi_ignore_client_abort off;
    fastcgi_connect_timeout 60;
    fastcgi_send_timeout 180;
    fastcgi_read_timeout 180;
    fastcgi_buffer_size 128k;
    fastcgi_buffers 4 256k;
    fastcgi_busy_buffers_size 256k;
    fastcgi_temp_file_write_size 256k;
    }

    location = /favicon.ico {
    log_not_found off;
    access_log off;
    }

    location = /robots.txt {
    allow all;
    log_not_found off;
    access_log off;
    }

    location ~ /.ht {
    deny all;
    }
}

server {
     listen  443 ssl http2;
     server_name  www.build-centos.info;
     rewrite ^ https://build-centos.info$request_uri? permanent;
}

Конфігураційний файл містить настройки для доступу по захищеному протоколу https, так як багато популярних CMS в даний момент за замовчуванням працюють через нього. Надалі ми встановимо і налаштуємо безкоштовний SSL сертифікат Let’s Encrypt (по аналогії з установкою Let’s Encrypt сертифіката на IIS сайту в Windows Server).

Установка php-fpm і додаткових модулів php

У Nginx немає вбудованого обробника PHP, тому ми повинні встановити php-fpm і ряд модулів php, які будуть використовуватися для обробки PHP скриптів.

Php-fpm це дуже легкий і швидкий менеджер процесів PHP. Він не використовує HTTP протокол (як apache), і працює зі спеціальним протоколом FastCGI. За рахунок легковажності і простоти FPM дозволяє набагато швидше обробляти PHP запити. При цьому, в порівнянні з аналогічною конфігурацією з apache, пам’яті буде використовуватися набагато менше.

Nginx в свою чергу дає суттєвий виграш при віддачі статики. В нашій конфігурації ngnix виступатиме проксі-сервером (Кешуються і front-end сервером), а в якості бекенд буде працювати php-fpm.

Для установки свіжих версій php, використовуємо репозиторій REMI:

# rpm -ivh http://rpms.famillecollet.com/enterprise/remi-release-7.rpm

Після установки, відредагуйте файл /etc/yum.repos.d/remi-php74.repo:

настройка сховища remi для php

запустіть установку php-fpm і популярних модулів php:

# yum install php-fpm php-cli php-mysql php-gd php-ldap php-odbc php-pdo php-opcache php-pear php-xml php-xmlrpc php-mbstring php-snmp php-soap php-zip

установка php-fpm і популярних модулів php

запустіть сервіс php-fpm і добавити його в автозавантаження:

# systemctl start php-fpm
# systemctl enable php-fpm

Created symlink from /etc/systemd/system/multi-user.target.wants/php-fpm.service to /usr/lib/systemd/system/php-fpm.service.

Щоб перевірити, запустився чи сервіс, можна виконати команду:

# lsof -i:9000

COMMAND PID USER FD TYPE DEVICE SIZE/OFF NODE NAME
php-fpm 1551 root 7u IPv4 2078435 0t0 TCP localhost:cslistener (LISTEN)
php-fpm 1552 apache 9u IPv4 2078435 0t0 TCP localhost:cslistener (LISTEN)
php-fpm 1553 apache 9u IPv4 2078435 0t0 TCP localhost:cslistener (LISTEN)
php-fpm 1554 apache 9u IPv4 2078435 0t0 TCP localhost:cslistener (LISTEN)
php-fpm 1555 apache 9u IPv4 2078435 0t0 TCP localhost:cslistener (LISTEN)
php-fpm 1556 apache 9u IPv4 2078435 0t0 TCP localhost:cslistener (LISTEN)

сервіс php-fpm потрібно запустити через unix-сокет. У файлі конфігурації /etc/php-fpm.d/www.conf видаліть рядок listen = 127.0.0.1:9000 і додайте:

listen = /var/run/php-fpm/php-fpm.sock
listen.mode = 0660
listen.owner = nginx
listen.group = nginx

Щоб запускати php-fpm немає від користувача apache (за замовчуванням), вкажіть наступні параметри в файлі конфігурації:

user = nginx
group = nginx

Після зміни конфігураційного php-fpm потрібно перезапустити сервіс:

# systemctl restart php-fpm

Установка Let’s Encrypt і підключення сертифіката

Щоб випустити безкоштовний сертифікат Let’s Encrypt, потрібно встановити потрібне certbot.

# yum install certbot

Потім виконайте:

# certbot certonly

Після запуску команди, вам потрібно буде заповнити всі дані, вказавши поштову скриньку, домен і так далі:

# certbot certonly

Saving debug log to /var/log/letsencrypt/letsencrypt.log
How would you like to authenticate with the ACME CA?
-------------------------------------------------------------------------------
1: Spin up a temporary webserver (standalone)
2: Place files in webroot directory (webroot)
-------------------------------------------------------------------------------
Select the appropriate number [1-2] then [enter] (press 'c' to cancel): 1
Plugins selected: Authenticator standalone, Installer None
Enter email address (used for urgent renewal and security notices) (Enter 'c' to cancel): test@gmail.com
Starting new HTTPS connection (1): acme-v01.api.letsencrypt.org
-------------------------------------------------------------------------------
Please read the Terms of Service at
https://letsencrypt.org/documents/LE-SA-v1.1.1-August-1-2016.pdf. You must agree in order to register with the ACME server at https://acme-v01.api.letsencrypt.org/directory
-------------------------------------------------------------------------------
(A)gree/(C)ancel: A
-------------------------------------------------------------------------------
Would you be willing to share your email address with the Electronic Frontier Foundation, a founding partner of the Let's Encrypt project and the non-profit organization that develops Certbot? We'd like to send you email about EFF and our work to encrypt the web, protect its users and defend digital rights.
-------------------------------------------------------------------------------
(Y)es/(N)o: N
Please enter in your domain name(s) (comma and/or space separated) (Enter 'c' to cancel): build-centos.info
Obtaining a new certificate
Performing the following challenges:
tls-sni-01 challenge for build-centos.info
Waiting for verification...
Cleaning up challenges
IMPORTANT NOTES:
- Congratulations! Your certificate and chain have been saved at:
/etc/letsencrypt/live/build-centos.info/fullchain.pem
Your key file has been saved at:
/etc/letsencrypt/live/build-centos.info/privkey.pem
Your cert will expire on 2018-01-24. To obtain a new or tweaked version of this certificate in the future, simply run certbot again. To non-interactively renew *all* of your certificates, run "certbot renew"

- Your account credentials have been saved in your Certbot configuration directory at /etc/letsencrypt. You should make a secure backup of this folder now. This configuration directory will also contain certificates and private keys obtained by Certbot so making regular backups of this folder is ideal.

Щоб сертифікат був коректно випущений, ваш домен повинен бути існуючим і спрямований на відповідний веб-сервер.

Після випуску сертифіката, виконайте перезавантаження веб-сервера nginx і перевірити результат.

# systemctl restart nginx

ssl СЕРТФІКАТА для сайту

З’єднання в браузері захищено!

Для автоматичного продовження сертифікатів змініть конфігураційний файл /etc/letsencrypt/renewal/build-centos.info.conf наступним чином:

# renew_before_expiry = 30 days
version = 0.18.1
archive_dir = /etc/letsencrypt/archive/ build-centos.info
cert = /etc/letsencrypt/live/build-centos.info/cert.pem
privkey = /etc/letsencrypt/live/build-centos.info/privkey.pem
chain = /etc/letsencrypt/live/build-centos.info/chain.pem
fullchain = /etc/letsencrypt/live/build-centos.info/fullchain.pem

# Options used in the renewal process
[renewalparams]
authenticator = webroot
installer = None
account = e9c86e6aa57b45f9614bc7c0015927a5
post_hook = nginx -s reload
[[webroot_map]]
www.build-centos.info = /var/www/build-centos.info
build-centos.info = /var/www/build-centos.info

Після зміни файлу, додайте в крон завдання:

30 2 * * * root /usr/bin/certbot renew --post-hook "nginx -s reload"

Щоб перевірити, що nginx працює з php, я створив файл index.php і додав в нього:

<?php phpinfo(); ?>

nginx + php-fpm перевірка роботи php скрипта

Установка MySQL / MariaDB на веб сервері

Даний крок ми повністю пропустимо, так як на сайті вже є стаття по установці і тюнінгу MariaDB. Скористайтеся ним.

Налаштування Nginx і PHP-FPM для високонавантажених проектів

Щоб ваш веб-сервер працював з високою продуктивністю і міг обробити велику кількість запитів від клієнтів, одного заліза недостатньо. Важливо правильно налаштувати роботу зв’язки nginx і php-fpm.

Налаштування nginx

Відкрийте файл /etc/nginx/nginx.conf і змінить конфігурацію Nginx наступним чином:

  • worker_processes 2; – статутом кількість робочих процесів рівною кількості ядер на сервері.
  • worker_connections 1024; – визначає кількість з’єднань одного робочого процесу. Виставляйте значення від 1024 до 4096.
  • use epoll; – оптимальний варіант методу з’єднань для Linux.
  • multi_accept on; – nginx буде приймати максимальну кількість з’єднань.

Блок http:

  • tcp_nodelay on; – відправляє заголовки і початок файлу в одному пакеті.
  • tcp_nopush on;

Для проектів в яких міститься велика кількість статичних файлів, обов’язково включайте gzip стиск:

gzip on;

Додайте велику кількість типів файлів, щоб всі перевірки на googlespeed проходили:
gzip_types application/atom+xml application/javascript text/javascript application/json application/ld+json application/manifest+json application/rss+xml application/vnd.geo+json font/ttf application/x-font-ttf application/vnd.ms-fontobject application/font-woff application/font-woff2 application/x-web-app-manifest+json application/xhtml+xml application/xml font/opentype image/bmp image/svg+xml image/x-icon text/cache-manifest text/css text/plain text/vcard text/vnd.rim.location.xloc text/vnd.wap.wml text/vtt text/x-component text/x-cross-domain-policy;

Налаштування стиснення дозволить прискорити ваш проект.

  • keepalive_timeout 30; – веб-сервер очікуватиме 30 секунд, перш ніж закрити keepalive з’єднання
  • keepalive_requests 100; – максимальна кількість keepalive запитів від одного клієнта
  • reset_timedout_connection on; – включіть даний параметр, якщо не хочете, щоб з’єднання від клієнта, який перестав відповідати, скидалися.
  • client_body_timeout 10; – веб-сервер буде чекати 10 секунд підтвердження запиту від клієнта, по закінченню цього часу, з’єднання скинеться.
  • send_timeout 2; – якщо клієнт припиняє читання відповіді від веб-сервера, nginx скине з’єднання з ним.

Якщо на вашому сайті не передбачена завантаження великих файлів, обмежте це за допомогою nginx:

  • client_max_body_size 2m; – сервер не прийме запити більше 2 Мб.

оптимізація конфігурації nginx для навантажених проектів

Якщо контент на вашому проекті змінюється не так часто, ви можете використовувати кешування «закінчується максимум;»Або додайте відповідну опцію в конфігураційний файл вашого хоста для потрібного типу файлів, наприклад:

location ~* ^.+.(js|css|png|jpg|jpeg|gif|ico|woff)$ {
expires 7d;
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

Кеш для зазначених типів файлів буде зберігається 7 днів. Ви можете управляти кешем за допомогою даної функції. Після всіх модифікацій, не забувайте виконувати перезапуск nginx:

# systemctl restart nginx

Налаштування php-fpm

При установці php-fpm ви відразу перевели його на unix-сокет. Це дає істотних приріст в продуктивності. За оцінками продуктивність зростає в 2-3 рази. Решта ж параметри php-fpm потрібно налаштовувати під кожен проект окремо, розглянемо приклад налаштування для сервера з 1024 Мб пам’яті.

Для php-fpm ми можемо виділити приблизно 512 мб, залишивши інше під БД і nginx.

У конфігураційний файл /etc/php-fpm/www.conf, Додамо:

  • pm.max_children = 18 – максимальне число дочірніх процесів
  • pm.start_servers = 6 – число дочірніх процесів, створюваних при запуску
  • pm.min_spare_servers = 4 – мінімальне число неактивних процесів сервера
  • pm.max_spare_servers = 16 – максимальне число неактивних процесів сервера
  • pm.max_requests = 400 – число запитів дочірнього процесу, після якого процес буде перезапущений.

Всі параметри потрібно змінювати при аналізі навантаження на ваш проект, дані значення теоретичні.

На поточний сервер я відразу ж встановив останню версію CMS Bitrix, для перевірки продуктивності. На мій погляд це сама ресурсномістка CMS і результати вийшли непогані, якщо враховувати, що це віртуальна машина на KVM з одним ядром (vCPU) і 1024 ОЗУ:

тест продуктивності bitrix на nginx + php-fpm

Оптимізацію налаштувань MariaDB я не розписував, так як є відповідна стаття на сайті. Я сформував параметри для my.cnf за статтею і база показала відмінний результат.

При запуску сайті ви помітите неозброєним поглядом, що nginx + php-fpm буде набагато швидше обробляти ваші запити і повертати сторінки, ніж apache2 + mod_php. Якщо у вас є можливість провести навантажувальні тести під час налаштування сервера, то це безсумнівно буде плюсом, якщо ж такої можливості немає, ви можете змінити параметри для своїх ресурсів виходячи з нашого мануала.

Leave a Reply

Your email address will not be published. Required fields are marked *