Оптимизиране на PHP-FPM за висока производителност

PHP е навсякъде и може би е най-широко използваният език в Интернет.


Той обаче не е точно известен със своите високоефективни възможности, особено когато става въпрос за силно едновременни системи. И това е причината, че при такива случаи на специализирана употреба езици като Node (да, знам, че не е език), Go и Elixir превземат.

Това каза, има много, за да подобрите производителността на PHP на вашия сървър. Тази статия се фокусира върху php-fpm страната на нещата, което е естественият начин да конфигурирате на вашия сървър, ако използвате Nginx.

В случай, че знаете какво е php-fpm, не се колебайте да преминете към секцията за оптимизация.

Какво е php-fpm?

Не много разработчици се интересуват от DevOps от страна на нещата и дори сред тези, които го правят, много малко знаят какво се случва под капака. Интересното е, че когато браузърът изпраща заявка до сървър, работещ с PHP, не първият контакт е PHP; Вместо това това е HTTP сървърът, основните от които са Apache и Nginx. След това тези „уеб сървъри“ трябва да решат как да се свържат с PHP и да предадат на него типа на заявката, данните и заглавките..

Цикълът на отговор на заявката в случай на PHP (кредит на изображение: ProinerTech)

В съвременните PHP приложения частта „намери файл“ по-горе е index.php, който сървърът е конфигуриран да делегира всички заявки на.

Как точно се е развил уеб сървърът към PHP и тази статия ще избухне по дължина, ако се наложи да влезем във всички лакомства. Но грубо казано, по времето, когато Apache доминира като уеб сървър по избор, PHP е модул, включен вътре в сървъра.

И така, всеки път, когато е получена заявка, сървърът ще започне нов процес, който автоматично ще включва PHP и ще го изпълни. Този метод се нарича mod_php, съкратен за „php като модул“. Този подход имаше своите ограничения, които Nginx преодоля с php-fpm.

В php-fpm отговорността за управление на PHP процесите се носи от PHP програмата в рамките на сървъра. С други думи, уеб сървърът (в нашия случай Nginx) не се интересува къде е PHP и как се зарежда, стига да знае как да изпраща и получава данни от него. Ако искате, можете да мислите за PHP в този случай като друг сървър сам по себе си, който управлява някои дъщерни PHP процеси за входящи заявки (така че, заявката достига до сървър, който е получен от сървър и предаван на сървър – доста луд! :-P).

Ако сте направили каквито и да е настройки на Nginx или дори просто да присъствате на тях, ще се натъкнете на нещо подобно:

местоположение ~ \ .php $ {
try_files $ uri = 404;
fastcgi_split_path_info ^ (. + \. php) (/.+) $;
fastcgi_pass unix: /run/php/php7.2-fpm.sock;
fastcgi_index index.php;
включва fastcgi_params;
fastcgi_param SCRIPT_FILENAME $ document_root $ fastcgi_script_name;
}

Линията, която ни интересува, е тази: fastcgi_pass unix: /run/php/php7.2-fpm.sock ;, която казва на Nginx да комуникира с PHP процеса чрез сокета с име php7.2-fpm.sock. Така че за всяка входяща заявка Nginx записва данни през този файл и при получаване на изхода го изпраща обратно в браузъра.

Още веднъж трябва да подчертая, че това не е най-пълната или най-точната картина на случващото се, но е напълно точна за повечето задачи на DevOps.

Като оставим настрана, нека обобщим това, което научихме досега:

  • PHP не получава директно заявки, изпратени от браузъри. Уеб сървъри като Nginx първо ги прихващат.
  • Уеб сървърът знае как да се свърже с процеса на PHP и предава всички данни за заявката (буквално поставя всичко свършено) на PHP.
  • Когато PHP приключи да върши своята роля, той изпраща отговора обратно към уеб сървъра, който го изпраща обратно на клиента (или в браузъра, в повечето случаи).

Или графично:

Как PHP и Nginx работят заедно (Изображение за кредит: DataDog)

Страхотно досега, но сега възниква въпросът за милиона долара: какво точно е PHP-FPM?

Частта „FPM“ в PHP означава „Fast Process Manager“, което е просто фантастичен начин да се каже, че PHP, работещ на сървър, не е един процес, а по-скоро някои PHP процеси, които се пораждат, контролират и убиват изключен от този мениджър на процесите на FPM. Именно този мениджър на процеси предава заявките на уеб сървъра.

PHP-FPM е цяла заешка дупка сама по себе си, така че не се колебайте да проучите, ако желаете, но за нашите цели това много обяснение ще направи. ��

Защо да оптимизирате php-fpm?

Така че защо да се притеснявате за целия този танц, когато нещата работят добре? Защо не оставите нещата такива, каквито са.

По ирония на съдбата, това е точно съветите, които давам за повечето случаи на употреба. Ако настройката ви работи добре и няма извънредни случаи на използване, използвайте настройките по подразбиране. Ако обаче искате да увеличите мащаба над една машина, изтискането на максимума от една е от съществено значение, тъй като може да намали сметките на сървъра наполовина (или дори повече!).

Друго, което трябва да се осъзнае, е, че Nginx е създаден за работа с огромни натоварвания. Той е в състояние да обработва хиляди връзки едновременно, но ако същото не е вярно за вашата PHP настройка, просто ще хабите ресурси, тъй като Nginx ще трябва да изчака PHP да приключи с текущия процес и да приеме следващо, категорично отрицателни всички предимства, които Nginx е създаден да осигури!

Така че, като избягаме от това, нека разгледаме какво точно ще променим, когато се опитваме да оптимизираме php-fpm.

Как да оптимизираме PHP-FPM?

Местоположението на конфигурационния файл за php-fpm може да се различава на сървъра, така че ще трябва да направите някои изследвания за локализирането му. Можете да използвате команда find, ако е в UNIX. В моя Ubuntu пътят е /etc/php/7.2/fpm/php-fpm.conf. 7.2 е, разбира се, версията на PHP, която пускам.

Ето как изглеждат първите няколко реда на този файл:

;;;;;;;;;;;;;;;;;;;;;
; Конфигурация на FPM;
;;;;;;;;;;;;;;;;;;;;;

; Всички относителни пътища в този конфигурационен файл са относителни към инсталацията на PHP
; префикс (/ usr). Този префикс може да бъде динамично променен с помощта на
; Аргумент ‘-p’ от командния ред.

;;;;;;;;;;;;;;;;;;
; Глобални опции;
;;;;;;;;;;;;;;;;;;

[Глобален]
; Pid файл
; Забележка: префиксът по подразбиране е / var
; Стойност по подразбиране: няма
pid = /run/php/php7.2-fpm.pid

; Файл на журнала за грешки
; Ако е настроено на "Syslog", логът се изпраща до syslogd, вместо да бъде написан
; в локален файл.
; Забележка: префиксът по подразбиране е / var
; Стойност по подразбиране: log / php-fpm.log
error_log = /var/log/php7.2-fpm.log

Няколко неща трябва да бъдат веднага очевидни: ред pid = /run/php/php7.2-fpm.pid ни казва кой файл съдържа идентификатора на процеса на процеса php-fpm.

Също така виждаме, че /var/log/php7.2-fpm.log е мястото, където php-fpm ще съхранява своите регистрационни файлове.

Вътре в този файл добавете още три променливи като тази:

Emergency_restart_threshold 10
авариен_рестарт_интервал 1м
process_control_timeout 10s

Първите две настройки са предупредителни и казват на процеса на php-fpm, че ако десет дъщерни процеса се провалят в рамките на една минута, основният процес на php-fpm трябва да се рестартира.

Това може да не звучи стабилно, но PHP е краткотраен процес, който не пропуска памет, така че рестартирането на основния процес в случаи на голям отказ може да реши много проблеми.

Третата опция, process_control_timeout, казва на дъщерните процеси да изчакат това много време, преди да изпълнят сигнала, получен от родителския процес. Това е полезно в случаите, когато дъщерните процеси са в средата на нещо, когато родителските процеси изпращат KILL сигнал, например. С десет секунди на ръка те ще имат по-голям шанс да завършат задачите си и да излязат грациозно.

Изненадващо, това не е месото на php-fpm конфигурация! Това е така, защото за обслужване на уеб заявки, php-fpm създава нов пул от процеси, който ще има отделна конфигурация. В моя случай името на пула се оказа www и файлът, който исках да редактирам, беше /etc/php/7.2/fpm/pool.d/www.conf.

Нека да видим как започва този файл:

; Стартирайте нов пул с име „www“.
; променливата $ pool може да се използва във всяка директива и ще бъде заменена от
; име на басейн (‘www’ тук)
[WWW]

; Префикс за пул
; Той се прилага само за следните директиви:
; – ‘access.log’
; – „бавен журнал“
; – „слушам“ (unixsocket)
; – „chroot“
; – ‘chdir’
; – ‘php_values’
; – ‘php_admin_values’
; Когато не е зададен, глобалният префикс (или / usr) се прилага вместо това.
; Забележка: Тази директива може да се отнася и за глобалния префикс.
; Стойност по подразбиране: няма
; префикс = / път / до / пулове / $ пул

; Уникс потребител / група процеси
; Забележка: Потребителят е задължителен. Ако групата не е зададена, групата по подразбиране на потребителя
; ще бъде използвано.
потребител = www-data
група = www-данни

Бърз поглед в края на фрагмента по-горе решава загадката защо сървърният процес работи като www-data. Ако срещнете проблеми с разрешенията на файлове при настройването на уебсайта си, вероятно сте променили собственика или групата на директорията в www-data, като по този начин позволявате на процеса на PHP да може да пише в лог файлове и да качва документи и т.н..

Накрая стигаме до източника на въпроса, настройката на мениджъра на процесите (pm). Като цяло ще видите настройките по подразбиране като нещо подобно:

pm = динамичен
pm.max_children = 5
pm.start_servers = 3
pm.min_spare_servers = 2
pm.max_spare_servers = 4
pm.max_requests = 200

И така, какво прави “динамичен“Тук означава ли? Мисля, че официалните документи най-добре обясняват това (искам да кажа, това вече трябва да е част от файла, който редактирате, но аз го възпроизведох тук само в случай, че не е):

; Изберете как мениджърът на процеси ще контролира броя на дъщерните процеси.
; Възможни стойности:
; static – фиксиран брой (pm.max_children) на детски процеси;
; динамичен – броят на дъщерните процеси се задава динамично на базата на
; следващи директиви. С това управление на процесите ще има
; винаги най-малко 1 деца.
; pm.max_children – максималният брой деца, които могат
; бъдете живи едновременно.
; pm.start_servers – броят на децата, създадени при стартиране.
; pm.min_spare_servers – минималният брой деца в „празен ход“
; състояние (изчакване за обработка). Ако числото
; на „празните“ процеси е по-малко от това
; номер, тогава ще бъдат създадени някои деца.
; pm.max_spare_servers – максималният брой деца в „празен ход“
; състояние (изчакване за обработка). Ако числото
; на процесите на празен ход е по-голям от този
; номер, тогава някои деца ще бъдат убити.
; ondemand – при стартиране не се създават деца. Децата ще бъдат раздвоени кога
; ще се свържат нови заявки. Използва се следният параметър:
; pm.max_children – максималният брой деца, които
; може да бъде жив едновременно.
; pm.process_idle_timeout – Броят секунди след това
; бездействащ процес ще бъде убит.
; Забележка: Тази стойност е задължителна.

Така че виждаме, че има три възможни стойности:

  • статичен: Фиксиран брой PHP процеси ще се поддържа независимо от всичко.
  • динамичен: Ще уточним минималния и максималния брой процеси, които php-fpm ще поддържа жив във всеки даден момент от време.
  • OnDemand: Процесите се създават и унищожават, добре, при поискване.

И така, как имат значение тези настройки?

Казано по-просто, ако имате уебсайт с нисък трафик, „динамичната“ настройка е загуба на ресурси през повечето време. Ако приемем, че сте задали pm.min_spare_servers на 3, три PHP процеса ще бъдат създадени и поддържани, дори когато няма трафик на уебсайта. В такива случаи „търсенето“ е по-добър вариант, оставяйки системата да решава кога да стартира нови процеси.

От друга страна, уебсайтовете, които обработват големи количества трафик или трябва да реагират бързо, ще бъдат наказани в тази настройка. Създаването на нов процес на PHP, превръщането му в част от пула и наблюдението му е допълнителна режийна работа, която е най-добре да се избягва.

Използването pm = статично фиксира броя на дъщерните процеси, позволявайки максимални системни ресурси да се използват за обслужване на заявките, а не за управление на PHP. Ако все пак тръгнете по този маршрут, внимавайте, че той има своите указания и клопки. Доста гъста, но много полезна статия за това е тук.

Заключителни думи

Тъй като статиите за уеб изпълнение могат да разпалят войни или да служат за объркване на хората, усещам, че няколко думи са в ред, преди да затворим тази статия. Настройката на производителността е толкова много за догадките и тъмните изкуства, колкото и за системното познание.

Дори ако знаете всички настройки на php-fpm наизуст, успехът не е гарантиран. Ако не сте имали представа за съществуването на php-fpm, не е нужно да губите време да се притеснявате за това. Просто продължавайте да правите това, което вече правите и продължавайте.

В същото време, избягвайте края да бъдете наркоман. Да, можете да постигнете още по-добра производителност, като прекомпилирате PHP от нулата и премахнете всички модули, които няма да използвате, но този подход не е достатъчно разумен в производствената среда. Цялата идея за оптимизиране на нещо е да погледнете дали вашите нужди се различават от настройките по подразбиране (което рядко правят!) И да направите малки промени, ако е необходимо.

Ако не сте готови да отделите време за оптимизиране на вашите PHP сървъри, тогава можете да помислите за използване на надеждна платформа като Kinsta които се грижат за оптимизирането на работата и сигурността.

Jeffrey Wilson Administrator
Sorry! The Author has not filled his profile.
follow me
    Like this post? Please share to your friends:
    Adblock
    detector
    map