Nginx. Использование PHP в режиме FastCGI с помощью php-fpm
У меня стоял Apache 2.2 и mod_php, так как Apache жрет не мало ресурсов, я решил постепенно переводить проекты на сервере на связку Nginx + PHP-FastCGI, а в качестве спаунера php-fpm.
Вкратце, что такое FastCGI и почему он лучше чем mod_php?
FastCGI это высокопроизводительный и масштабируемый интерфейс для взаимодействия web-сервера и приложений, дальнейшее развитие технологии CGI. Ознакомиться с более подробной информацией о FastCGI вы можете на официальном сайте или в Википедии.
Основное преимущество FastCGI в изолировании динамического языка от web-сервера. Например, запуск FastCGI процесса под пользователем, отличным от пользователя web-сервера, а также процесс может находиться в chroot'е, отличном от chroot'а web-сервера. Помимо всего прочего, эта технология позволяет запускать web-сервера и CGI процессы (теже php скрипты) на различных хостах, что улучшает масштабируемость и также способствует безопасности без существенной потери в производительности.
Ну а зачем нам php-fpm, если PHP и так поддерживает работу в режиме FastCGI?
php-fpm - это патч для PHP, для использования PHP как FastCGI процесса в высоконагруженных системах. Устраняет ряд проблем мешающих использовать PHP в режиме FastCGI. Андрей Нигматулин представил набор патчей php-fpm к PHP 4/5, устраняющих ряд проблем, которые мешают использовать PHP в режиме FastCGI на высоконагруженных системах.
Возможности php-fpm:
* Управление процессами. Возможность "плавно" останавливать и перезапускать php воркеры без потери запросов. Возможность плавно обновлять конфигурацию и binary без потери запросов;
* Ограничение ip адресов, с которых могут приходить запросы от web сервера;
* Динамическое количество процессов, в зависимости от нагрузки (TODO);
* Запуск воркеров с разными uid/gid/chroot/environment и разными php.ini опциями;
* Логирование stdout & stderr рабочих процессов;
* Аварийный перезапуск всех процессов при случайном разрушении shared memory opcode cache, если используется акселератор;
* Принудительное завершение подвисших процессов, если set_time_limit() не срабатывает (TODO);Андрей Нигматулин / php-fpm / PHPConf 08 from Mihail Andreev on Vimeo.
Кстати, в видео я тоже поучаствовал, на 5-ой минуте и 20-ой секунде я там прохожу перед камерой в костюме и красной футболке... :D
Установка Nginx
На самом деле Nginx у меня был уже установлен, но для полноты статьи я расскажу как и его установить. В зависимости от необходимого функционала, либо от стабильности версии, вам надо выбрать подходящую версию Nginx. Стабильная находится в каталоге "/usr/ports/www/nginx/", а более новая в "/usr/ports/www/nginx-devel/", у меня стоит именно вторая.
# cd /usr/ports/www/nginx-devel/ # make install clean
Всё, Nginx установлен, добавьте его в автозагрузку:
# echo 'nginx_enable="YES"' >> /etc/rc.conf
Установка php-fpm
Процесс заключается в пропатчивании и переустановки PHP интерпретатора с поддержкой FastCGI и php-fpm.
Установка из сорцов
Заходим на оф. сайт PHP и качаем необходимую версию PHP интерпретатора со страницы , у меня это PHP 5.2.10.
# cd /tmp # fetch
Заходим на оф. сайт проекта php-fpm, в раздел загрузок и выбираем подходящую для вашего PHP интерпретатора версию патча. У меня это PHP 5.2.10, поэтому я буду ставить именно его.
# cd /tmp # fetch # tar -xzf php-5.2.10.tar.gz # gzip -cd php-5.2.10-fpm-0.5.13.diff.gz | patch -d php-5.2.10 -p1 # cd php-5.2.10 # ./configure --enable-fastcgi --enable-fpm # make all install
Теперь, скопируем скрипт инициализации php-fpm в каталог "/usr/local/etc/rc.d" и назначим ему права на запуск:
# cp /tmp/php-5.2.10/sapi/cgi/fpm/php-fpm /usr/local/etc/rc.d/ # chmod +x /usr/local/etc/rc.d/php-fpm
Установка из портов
Тут все намного проще... :)
# cd /usr/ports/lang/ # fetch # tar -xzvf php-5.2.10-fpm-0.5.13.tar.gz # rm php-5.2.10-fpm-0.5.13.tar.gz # cd php5-fpm # make install
Завершение установки
После установки, проверьте версию php:
# php -v PHP 5.2.10 (cli) (built: Sep 2 2009 12:46:58) Copyright (c) 1997-2009 The PHP Group Zend Engine v2.2.0, Copyright (c) 1998-2009 Zend Technologies
Если "built" сегодняшний, то всё оки, если нет - отпишите в комментарии, помогу разобраться.
Я ставил и из сорцов и из портов, так что все проверено на себе! :)
Добавим в автозагрузку:
# echo 'php_fpm_enable="YES"' >> /etc/rc.conf
Настройка Nginx
Теперь настраиваем Nginx, отредактируйте конфиг "/usr/local/etc/nginx/nginx.conf" или свой "vhost":
server { listen 80; server_name demo.adw0rd.ru; location ~* \.(jpg|jpeg|gif|png|ico|css|zip|js|swf)$ { root /home/adw0rd/adw0rd.ru/demo; } location / { fastcgi_pass 82.146.63.195:9000; fastcgi_index index.php; fastcgi_param SCRIPT_FILENAME /home/adw0rd/adw0rd.ru/demo$fastcgi_script_name; include fastcgi_params; } }
Чуть более подробно о конфигурации nginx тут и тут.
Настройка php-fpm
Я покажу части конфига, которые только отличаются от "php-fpm.conf.default", весь конфиг можно взять тут.
<value name="listen_options"> Set listen(2) backlog <value name="backlog">-1</value> Set permissions for unix socket, if one used. In Linux read/write permissions must be set in order to allow connections from web server. Many BSD-derrived systems allow connections regardless of permissions. <value name="owner">www</value> <value name="group">www</value> <value name="mode">0666</value> </value> ... Unix user of processes <value name="user">www</value> Unix group of processes <value name="group">www</value> ... Comma separated list of ipv4 addresses of FastCGI clients that allowed to connect. Equivalent to FCGI_WEB_SERVER_ADDRS environment in original php.fcgi (5.2.2+) Makes sense only with AF_INET listening socket. <value name="allowed_clients">127.0.0.1,82.146.63.195</value>
"82.146.63.195" - это ип моего сервера, на котором крутится nginx. Ему то мы и разрешим доступ.
Запуск
Теперь осталось только запустить nginx и php-fpm:
/usr/local/etc/rc.d/nginx restart /usr/local/etc/rc.d/php-fpm restart
Если не запустилось, то смотрите "/var/log/php-fpm.log". Если нету файла лога вообще, то создайте его и права на запись выставите.
Вот и все, в следующей статье расскажу о spawn-fcgi (раньше входил в lighttpd).

Комментарии
Блииин, че нету в пакетах nginx и php шоле?
Я не понял вопроса.
Хай) Мы в последнее время используем spawn-fcgi - он есть в портах и с ним не надо патчить PHP и, соответственно, можно завести с любой версией. Конфиг nginx я обычно стараюсь писать как то так (с try_files):
server {
listen 80;
server_name demo.adw0rd.ru;
}
Плюсы:
- не надо заморачиваться на расширения файлов. Можно указать expires и т.п.
Минусы:
- надо следить чтобы try_files не отдал .php как статику. Решается легко - в директории, указанной в root, не должно быть .php файлов. У меня обычно в проекте есть папка public где лежит только статика. Все .php файлы лежат в другом месте (см. конфиг выше). Вот :)
Еще я обычно задаю SCRIPT_FILENAME жестко. Ну это от проекта конечно зависит.
Смысл то не в том же, что fastcgi много лучше модуля (в основной массе всем на chroot, других пользователей и другие хосты наплевать), а в том что апач прожорлив слишком, нужно от него избавляться.
ash2k, я под убунтой на работе юзаю spawn-fcgi, скоро и про него напишу. Думаю даже что он побыстрее должен быть... Надо бы его потестить с fpm
Ну в моей конструкции тоже можно, я так и юзаю, но в примере не показал :)
У меня она называется "static" :)vasa_c, ну а я о чем?)
Жду когда php-fpm, вмерженная в PHP, стабилизируется и будет уже в релизе вместе с PHP идти. Вот тогда будет действительно клево. Ты ведь в курсе, что патч php-fpm приняли в основной реп PHP?
p.s. а вообще мы тут планируем на Python перейти :) задолбал PHP костылями!
у тебя кстати тут коменты глючили несколько дней назад - не смог сразу ответ написать. сейчас вот нормально с первого раза отправилось. тогда писало что-то типа "ничего не найдено" если я правильно помню.
ash2k, я не в курсе был что fpm патчи внесут в core. Ты кстати слышал о Facebook и перепатчиваниие PHP ими?
Камменты глючили из-за того, что я переводил свой блог на fpm )
А вот и про фейсбуковский HipHop http://rmcreative.ru/blog/post/hiphop
да я читал про этот хипхоп. интересно что быстрее - написаное на пхп и "скомпиленное" этим хипхопом или напимер джава.
Думаю скоро бенчмарки появятся.
Наверное, имелось ввиду:
Спасибо что заметили, исправил
нужно в конфиге php-fpm.conf прописать
где x.x.x.x ваш ip адрес
Строка номер 41 Это типа на каком адресе слушать
А это вы на видео?)
Это все конечно хорошо, вот заинтересовался полным отказом от апача, но вот такой вопрос меня интересует, будет ли nginx распознавать .htaccess файлы? интересует deny,allow и мод реврайт. заранее спс.
На видео не я.
.htaccess - это только для апач, конечно nginx не будет их обрабатывать из коробки. Погуглите расширение для nginx которое нечто подобно делает.
По поводу рерайтов - это есть, deny/allow тоже, читайте документацию на http://sysoev.ru/nginx/docs/
Походу .htaccess читаться не будет... а что же тогда делать, прописывать подобные вещи
неудобно
да, спасибо, вот уже читаю доки (не прочитал пред. ваш пост, слишком быстро ответили :) )... еще такой вопрос, а подобным образом пропатченный php будет работать как mod apache?
Погуглите apache php fastcgi
а при использовании php-fpm как описано в этой статье будут идти ероры согласно параметру в php.ini?
Еще подскажите пожалуйста, как сделать короче такие правила
то есть в 1 location это можно записать?
так правильно?
Правильно так, как вы написали в посте от 03.01.2011.
Работать будет и второй вариант, но такого написания лучше избегать.
Очень рекомендую посмотреть http://video.yandex.ru/users/ibondarets/view/1/
Fighter,
1. Тут про error.log - http://adw0rd.ru/2010/ubuntu-php53/
2. Лучше делать на каждое событие свой location, как и сказал ash2k: "в посте от 03.01.2011". Когда будет много location - вы сами запутаетесь, я сталкиваюсь постоянно с этим на работе, постепенно переделывая location из регулярок в просто location, если конечно это возможно... Так что посмотрите видео и избегайте регулярок и if'ов
Да просто правил море :)
а в инклуд не хочется выносить...
еще такой вопрос, вот в апаче когда php как модуль можно указать эти переменные
а где их указать когда используется PHP-FPM? нужно чтоб сендмаил работал...
извиняюсь, про сендмаил уже нашел здесь http://adw0rd.ru/2010/ubuntu-php53/ :)
я так полагаю это необходимо раскомментировать
<!-- /usr/sbin/sendmail -t -i -->
еще вопрос насчет этих настроек
нужно указать по аналогии с php_admin_value open_basedir
если эти параметры не указаны, тогда какой дир берется за "изоляцию"?
не зпускается(
пишет
/usr/local/etc/rc.d/php-fpm start
Starting php_fpm ................................... failed
а в логе
Перезагрузите систему
можно как-то из портов поставить php-5.2.10? а то у меня более поздняя, тогда я смогу портом поставить патч...
зачем перезагрузить, без этого никак?
можно "5.2.*", смотрите /usr/ports/lang/php52/
почему не поставите "более позднюю"?
Сейчас уже не надо ничего патчить, так как c версией php 5.3 - fpm внесли в состав дистрибутива php.
И через порты он ставится путем указания галочки в make config
Также есть пункт и для php 5.2
Комментарии закрываю в силу того, что:
* у PHP-FPM изменился формат конфига
* теперь можно ставить из портов (см. выше комментарий), а не патчить
Возможно вас заинтерисует:
http://adw0rd.ru/tag/nginx/
http://adw0rd.ru/tag/php-fpm/
http://adw0rd.ru/tag/fastcgi/
http://adw0rd.ru/tag/php/
Блииин! Ребята, низкий поклон и огромнейшее спасибо за статью и обзор!
Недавно столкнулся с переносом корявоработающего сайта на новый сервер, где уже крутится nginx и php 5.5
Уже все настроено работает как часики. Но корявый сайт работает ТОЛЬКО под php 5.2, написан невероятно криворуко левой рукой из под правой коленки, а на переписывание времени нет. Было выбрано решение поставить параллельно с 5.5 5.2. Долго мучился с настройками пока не наткнулся на эту статью! На все вопросы в раз нашлись ответы!
Все не нарадуюсь этим строчкам:
[root@web:chroot websrv]# ll
srw-rw-rw- 1 root root php-fpm52.sock
srw-rw-rw- 1 root root php-fpm55.sock
adw0rd, спасибо вам! =)
С уважением, Val Man
Не за что, статья правда уже устарела, конфиги fpm уже давно в ini-формате)
Оставьте свой комментарий