воскресенье, 8 января 2012 г.

Настройки PHP-FPM

(PHP 5.2.17, PHP-FPM 0.5.14)


Глобальные параметры


pid_file - pid файл. По умолчанию: то, что было указано при maleextra компилировании опцией --with-fpm-pid

error_log - файл журнала ошибок. По умолчанию: то, что было указано при компилировании опцией --with-fpm-log

log_level - уровень записываемых в журнал ошибок. По seo India умолчанию: "notice" (TODO: get list)

emergency_restart_threshold - при это числе рабочий процессов завершенных с SIGSEGV или SIGBUS... По умолчанию: 10

emergency_restart_interval - ...менее чем за этот промежуток instant performer времени, php-fpm будет мягко перезапущен. Это необходимо, чтобы исключить случайные повреждения памяти. По умолчанию: "1 минута"

process_control_timeout - время ожидания ответа от рабочий процессов. По умолчанию: "5 секунд"

daemonize - укажите "no" для отладки php-fpm или для его performer5 запуска в диспетчере (runit/sv, daemontools, upstart, etc.) По умолчанию: "yes"

Настройки пулов

Пул естественно может быть не один, а сколько вам потребуется. Это позволяет запускать их под разными системными пользователями, разными chroot'ами и т.д. Вообщем это дает определенною гибкость, так как позволяет в каждом пуле использовать свои собственные настройки под веб-приложение, которое будет его использовать. Улучшает безопасность, так как веб-приложения изолированы друг от друга и при компрометации одного приложения, остальные останутся в относительной безопасности. Кроме того это же и облегчает процесс обнаружения скомпрометированных веб-приложений.

В конфигурационном файле php-fpm.conf объявление 2-3 пулов будет выглядеть примерно так

<?xml version="1.0" ?>
<configuration>
<workers>
<section name="pool">
<value name="name">pool-1</value>
...
...
</section>
<section name="pool">
<value name="name">pool-2</value>
...
...

</section>
<section name="pool">
<value name="name">pool-3</value>
...
...
</section>
</workers>
</configuration>


Но так как PHP-FPM с PHP версий ниже 5.3.3 не поддерживает динамическое число дочерних процессов, то путем разнесения веб-приложений по свои отдельным php-fpm пулам, мы теряем по ресурсам. Связано это с тем что при static style pm кол-во процессов всегда одинаковое и если все процессы в одном пуле и ими пользуются все веб-приложения, то единовременно каждому приложению доступно на порядок большее число php-fpm процессов для обработки запросов, чем если бы у каждого приложения было по собственному персональному пулу.


name - имя пула, используется php-fpm'ом при ведении логов

listen_address - прослушиваемый адрес, здесь можно указать как сетевой адрес и порт, так и файловый сокет, например 127.0.0.1:9000 или tmp/php-fpm.sock, соответственно

owner - владелец, который будет назначен файловому сокету

group - группа, которая будет назначена файловому сокету

mode - права, которые будут выставлены на созданный файловый сокет

php_defines - описание настроек php, которые будут применены к данному пулу, перекрыв настройки указанные в /etc/php.ini. Например задание параметров max_execution_time и upload_max_filesize будет выглядеть вот так


<value name="php_defines">
<value name="max_execution_time">120</value>
<value name="upload_max_filesize">30</value>
</value>


user - системный пользователь из под которого будет работать процесс текущего пула

group - системная группа из под которой будет работать процесс текущего пула

style - задает стиль управления кол-вом рабочих процессов php-fpm. Возможные значения это static и apache-like (для PHP версии 5.2.17 с патчем PHP-FPM 0.5.14 - apache-like скорее всего работать не будет, с PHP версии 5.3.3 значение apache-like переименовано в dynamic и работает)

max_children - максимальное кол-во одновременно обрабатываемых запросов, т.е. кол-во процессов php-fpm которое будет запущено

startservers - кол-во создаваемых рабочих процессов php-fpm при запуске (применяется только при использовании apache-like для style)

minspareservers - минимальное кол-во рабочих процессов php-fpm (применяется только при использовании apache-like для style)

maxspareservers - максимальное кол-во рабочих процессов php-fpm (применяется только при использовании apache-like для style)

request_terminate_timeout - время в секундах на обслуживание одного запроса, по истечение которого рабочий процесс будет остановлен. Используется в том случае когда php параметру max_execution_time по каким либо причинам не удается остановить выполнение скрипта. Значение "0s" отключает использование этой функции.

request_slowlog_timeout - время в секундах для обработки одного запроса и при превышении которого данные о выполненном php скрипте будут сброшены в slow.log файл (аналог логирования медленных sql запросов Mysql сервера). 
Значение "0s" отключает использование этой функции.

slowlog - лог файл для записи в него информации о медленных запросах

rlimit_files - устанавливает лимит дескрипторов открытых файлов rlimit

rlimit_core - устанавливает максимальное кол-во используемых ядер rlimit

chroot - директория chroot окружения при запуске. Путь должен быть абсолютным

chdir - изменяет текущую директория при запуске

catch_workers_output - перенаправление STDOUT и STDERR рабочего процесса в главный лог ошибок. Если не установлен, STDOUT и STDERR будут перенаправлены в /dev/null в соответствии со спецификацией FastCGI

max_requests - кол-во запросов которое может обработать процесс, по истечению лимита которого он будет перезапущен. Полезно для минимизации негативного эффекта от утечки памяти при использовании сторонних библиотек. Нулевое значение отключает перезапуск

allowed_clients - список IP адресов запросы с которых будут разрешены к обработке, IP адреса перечисляются через запятую. Нулевое значение снимает ограничение на доступ к php-fpm по IP адресу

Переменные окружения

Особо описывать нечего, ниже часть настроек по умолчанию из конфига php-fpm

                        <value name="environment">
                                <value name="HOSTNAME">$HOSTNAME</value>
                                <value name="PATH">/usr/local/bin:/usr/bin:/bin</value>
                                <value name="TMP">/tmp</value>
                                <value name="TMPDIR">/tmp</value>
                                <value name="TEMP">/tmp</value>
                                <value name="OSTYPE">$OSTYPE</value>
                                <value name="MACHTYPE">$MACHTYPE</value>
                                <value name="MALLOC_CHECK_">2</value>
                        </value>

понедельник, 2 января 2012 г.

Сборка PHP-FPM в Deb пакет

Пошаговый мануал по сборке PHP-FPM в Deb пакет


(ОС: Debian GNU/Linux 6.0 amd64, PHP 5.2.17, PHP-FPM 0.5.14)

Устанавливаем пакеты необходимые для работы

apt-get install build-essential dh-make libxml2-dev


Создаем каталог в который будем производить инсталляцию пакета до его сборки в deb пакет

mkdir /tmp/package


Логинимся в систему под обычным пользователем и все дальнейшие действия выполняем из под него. Скачиваем нужную нам версию PHP (в примере это будет PHP версии 5.2.17) и распаковываем ее в домашнем каталоге пользователя, под которым зашли в систему

cd ~
wget http://ru.php.net/distributions/php-5.2.17.tar.gz
tar -xf php-5.2.17.tar.gz


скачиваем PHP-FPM патч для нашей версии PHP, выполняем декомпрессию

wget http://php-fpm.org/downloads/php-5.2.17-fpm-0.5.14.diff.gz
gzip -d php-5.2.17-fpm-0.5.14.diff.gz


проходим в каталог с исходным кодом PHP

cd php-5.2.17


теперь патчим наш PHP патчем PHP-FPM и включаем поддержку FastCGI и собственно PHP-FPM (в ./configure не забываем добавить нужные нам ключи для сборки PHP с необходимыми нам модулями, например поддержка Mysql)

patch -p1 < ../php-5.2.17-fpm-0.5.14.diff
./configure --prefix= --bindir=/usr/bin --sbindir=/usr/sbin --mandir=/usr/share/man --libdir=/usr/lib --includedir=/usr/include --enable-fastcgi --enable-fpm --with-fpm-log=/var/log/php-fpm.log --with-fpm-pid=/var/run/php-fpm.pid --with-mysql --with-zlib --with-config-file-path=/etc


выполняем компиляцию и установку PHP в заранее подготовленный нами каталог /tmp/package. Данный процесс займет некоторое время, зависит от мощности сервера

INSTALL_ROOT=/tmp/package make all install


если все пройдет нормально, то по завершению будет примерно такой вывод

Build complete.
Don't forget to run 'make test'.


Installing PHP SAPI module:       cgi
Installing PHP CGI binary: /tmp/package/usr/bin/
Installing FPM config:            /tmp/package/etc/php-fpm.conf
Installing init.d script:         /tmp/package/sbin/php-fpm
Installing PHP CLI binary:        /tmp/package/usr/bin/
Installing PHP CLI man page:      /tmp/package/usr/share/man/man1/
Installing build environment:     /tmp/package/usr/lib/build/
Installing header files:          /tmp/package/usr/include/php/
Installing helper programs:       /tmp/package/usr/bin/
  program: phpize
  program: php-config
Installing man pages:             /tmp/package/usr/share/man/man1/
  page: phpize.1
  page: php-config.1
Installing PEAR environment:      /tmp/package/usr/lib/php/
[PEAR] Archive_Tar    - installed: 1.3.7
[PEAR] Console_Getopt - installed: 1.2.3
[PEAR] Structures_Graph- installed: 1.0.3
[PEAR] XML_Util       - installed: 1.2.1
warning: pear/PEAR requires package "pear/Archive_Tar" (recommended version 1.3.7)
warning: pear/PEAR requires package "pear/Structures_Graph" (recommended version 1.0.3)
warning: pear/PEAR requires package "pear/Console_Getopt" (recommended version 1.2.3)
warning: pear/PEAR requires package "pear/XML_Util" (recommended version 1.2.1)
[PEAR] PEAR           - installed: 1.9.1
Wrote PEAR system config file at: /tmp/package//etc/pear.conf
You may want to add: /usr/lib/php to your php.ini include_path
Installing PDO headers:          /tmp/package/usr/include/php/ext/pdo/


(в корне каталога /tmp/package удаляем все файлы и каталоги имя которых начинается на точку)


В каталоге /tmp/package создаем подкаталог DEBIAN, в нем файл control с примерно таким содержимым

Package: php-5.2.17-fpm-0.5.14
Architecture: amd64
Depends:
Provides:
Priority:
Version: 5.2.17
Maintainer: nobody
Description: PHP 5.2.17 with PHP-FPM 0.5.14


в этом же каталоге создаем еще один файл c именем preinst (выставляем ему права 775). Этот файл выполняется перед разворачиванием пакета в системе, в нашем случае это простой скрипт, который создаст системного пользователя php-fpm из под которого будет работать PHP-FPM. Выглядит скрипт вот так

#!/bin/sh -e


id php-fpm >/dev/null 2>&1 || addgroup --system php-fpm && \
adduser --system --no-create-home --disabled-password --ingroup php-fpm php-fpm

теперь создаем файл postinst (выставляем ему права 775), это скрипт запускается после разворачивания пакета. Он копирует php-fpm скрипт к init скриптам, делает его исполняемым и прописывает в автозагрузку

#!/bin/sh -e

cp /sbin/php-fpm /etc/init.d/ && \
chmod +x /etc/init.d/php-fpm && \
/usr/sbin/update-rc.d -f php-fpm defaults

и последний файл имеющий отношение к pre, post, rm скриптам Deb пакета это prerm. Он запускается перед удалением пакета из системы, у нас он останавливает PHP-FPM, удаляет системного пользователя php-fpm, убирает php-fpm из автозагрузки и удаляет init скрипт. Как обычно права на него 775

#!/bin/sh -e

/usr/sbin/invoke-rc.d php-fpm stop && \
userdel php-fpm && \
/usr/sbin/update-rc.d -f php-fpm remove && \
rm -f /etc/init.d/php-fpm

В файле /tmp/package/sbin/php-fpm корректируем путь к php-cgi

php_fpm_BIN=/usr/bin/php-cgi


в /tmp/package/etc/php-fpm.conf выставляем пользователя из под которого будет работать PHP-FPM, эту часть конфига:

                        Unix user of processes
                <!--    <value name="user">nobody</value>                               -->

                        Unix group of processes
                <!--    <value name="group">nogroup</value>             -->

меняем на такую:

                        Unix user of processes
                        <value name="user">php-fpm</value>

                        Unix group of processes
                        <value name="group">php-fpm</value>

из под root пользователя меняем владельца и группу для всех файлов в каталоге /tmp/package

chown -R root:root /tmp/package


и из под обычного пользователя выполняем сборку Deb пакета


cd ~
dpkg-deb -b /tmp/package/ php-5.2.17-fpm-0.5.14-amd64.deb


будет аналогичное сообщение

dpkg-deb: building package `php-5.2.17-fpm-0.5.14' in `php-5.2.17-fpm-0.5.14-amd64.deb'.


и в текущем каталоге появится собранный Deb пакет php-5.2.17-fpm-0.5.14-amd64.deb

Теперь из под root пользователя можем установить собранный нами пакет

dpkg -i php-5.2.17-fpm-0.5.14-amd64.deb


(конфигурационный файл php.ini размещаем в каталоге /etc)