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);
Кстати, в видео я тоже поучаствовал, на 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 интерпретатора со страницы http://www.php.net/downloads.php, у меня это PHP 5.2.10.
Заходим на оф. сайт проекта php-fpm, в раздел загрузок http://php-fpm.org/download и выбираем подходящую для вашего PHP интерпретатора версию патча. У меня это PHP 5.2.10, поэтому я буду ставить именно его.
# cd /tmp
# fetch http://php-fpm.org/downloads/php-5.2.10-fpm-0.5.13.diff.gz
# 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" и назначим ему права на запуск:
Если "built" сегодняшний, то всё оки, если нет - отпишите в комментарии, помогу разобраться.
Я ставил и из сорцов и из портов, так что все проверено на себе! :)
Добавим в автозагрузку:
# echo 'php_fpm_enable="YES"' >> /etc/rc.conf
Настройка Nginx
Теперь настраиваем Nginx, отредактируйте конфиг "/usr/local/etc/nginx/nginx.conf" или свой "vhost":
Чуть более подробно о конфигурации 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. Ему то мы и разрешим доступ.
Если не запустилось, то смотрите "/var/log/php-fpm.log". Если нету файла лога вообще, то создайте его и права на запись выставите.
Вот и все, в следующей статье расскажу о spawn-fcgi (раньше входил в lighttpd).
Хай) Мы в последнее время используем spawn-fcgi - он есть в портах и с ним не надо патчить PHP и, соответственно, можно завести с любой версией. Конфиг nginx я обычно стараюсь писать как то так (с try_files):
Плюсы:
- не надо заморачиваться на расширения файлов. Можно указать expires и т.п.
Минусы:
- надо следить чтобы try_files не отдал .php как статику. Решается легко - в директории, указанной в root, не должно быть .php файлов. У меня обычно в проекте есть папка public где лежит только статика. Все .php файлы лежат в другом месте (см. конфиг выше). Вот :)
Еще я обычно задаю SCRIPT_FILENAME жестко. Ну это от проекта конечно зависит.
Смысл то не в том же, что fastcgi много лучше модуля (в основной массе всем на chroot, других пользователей и другие хосты наплевать), а в том что апач прожорлив слишком, нужно от него избавляться.
Жду когда php-fpm, вмерженная в PHP, стабилизируется и будет уже в релизе вместе с PHP идти. Вот тогда будет действительно клево. Ты ведь в курсе, что патч php-fpm приняли в основной реп PHP?
p.s. а вообще мы тут планируем на Python перейти :) задолбал PHP костылями!
у тебя кстати тут коменты глючили несколько дней назад - не смог сразу ответ написать. сейчас вот нормально с первого раза отправилось. тогда писало что-то типа "ничего не найдено" если я правильно помню.
p.s. а вообще мы тут планируем на Python перейти :) задолбал PHP костылями!
да, меня тоже достал PHP и я перешел на Python :) но по работе все еще приходится иметь дело с PHP, а также некоторые свои проекты на PHP поддерживаем/дорабатываем
Это все конечно хорошо, вот заинтересовался полным отказом от апача, но вот такой вопрос меня интересует, будет ли nginx распознавать .htaccess файлы? интересует deny,allow и мод реврайт. заранее спс.
На видео не я.
.htaccess - это только для апач, конечно nginx не будет их обрабатывать из коробки. Погуглите расширение для nginx которое нечто подобно делает.
По поводу рерайтов - это есть, deny/allow тоже, читайте документацию на http://sysoev.ru/nginx/docs/
да, спасибо, вот уже читаю доки (не прочитал пред. ваш пост, слишком быстро ответили :) )... еще такой вопрос, а подобным образом пропатченный php будет работать как mod apache?
Fighter,
1. Тут про error.log - http://adw0rd.ru/2010/ubuntu-php53/
2. Лучше делать на каждое событие свой location, как и сказал ash2k: "в посте от 03.01.2011". Когда будет много location - вы сами запутаетесь, я сталкиваюсь постоянно с этим на работе, постепенно переделывая location из регулярок в просто location, если конечно это возможно... Так что посмотрите видео и избегайте регулярок и if'ов
Chroot to this directory at the start, absolute path
<value name="chroot"></value>
Chdir to this directory at the start, absolute path
<value name="chdir"></value>
нужно указать по аналогии с php_admin_value open_basedir
если эти параметры не указаны, тогда какой дир берется за "изоляцию"?
не зпускается(
пишет
/usr/local/etc/rc.d/php-fpm start
Starting php_fpm ................................... failed
а в логе
Jan 04 15:15:35.042340 [NOTICE] fpm_got_signal(), line 56: received SIGTERM
Jan 04 15:15:35.042369 [NOTICE] fpm_pctl(), line 256: switching to 'terminating' state
Jan 04 15:15:35.042389 [NOTICE] fpm_pctl_kill_all(), line 172: sending signal 15 SIGTERM to child 50506 (pool default)
Jan 04 15:15:35.042397 [NOTICE] fpm_pctl_kill_all(), line 172: sending signal 15 SIGTERM to child 50505 (pool default)
Jan 04 15:15:35.042405 [NOTICE] fpm_pctl_kill_all(), line 172: sending signal 15 SIGTERM to child 50504 (pool default)
Jan 04 15:15:35.043023 [NOTICE] fpm_pctl_kill_all(), line 172: sending signal 15 SIGTERM to child 50503 (pool default)
Jan 04 15:15:35.043031 [NOTICE] fpm_pctl_kill_all(), line 172: sending signal 15 SIGTERM to child 50502 (pool default)
Jan 04 15:15:35.043441 [NOTICE] fpm_pctl_kill_all(), line 181: 5 children are still alive
Jan 04 15:15:35.043486 [NOTICE] fpm_got_signal(), line 48: received SIGCHLD
Jan 04 15:15:35.043611 [WARNING] fpm_children_bury(), line 215: child 50506 (pool default) exited on signal 15 SIGTERM after 764.874366 seconds from start
Jan 04 15:15:35.043659 [WARNING] fpm_children_bury(), line 215: child 50505 (pool default) exited on signal 15 SIGTERM after 764.875014 seconds from start
Jan 04 15:15:35.043676 [WARNING] fpm_children_bury(), line 215: child 50504 (pool default) exited on signal 15 SIGTERM after 764.875615 seconds from start
Jan 04 15:15:35.043690 [WARNING] fpm_children_bury(), line 215: child 50503 (pool default) exited on signal 15 SIGTERM after 764.876131 seconds from start
Jan 04 15:15:35.043703 [WARNING] fpm_children_bury(), line 215: child 50502 (pool default) exited on signal 15 SIGTERM after 764.876558 seconds from start
Jan 04 15:15:35.043720 [NOTICE] fpm_pctl_exit(), line 81: exiting, bye-bye!
Jan 04 15:16:02.249955 [NOTICE] fpm_unix_init_main(), line 284: getrlimit(nofile): max:200000, cur:200000
Jan 04 15:16:02.250074 [ERROR] fpm_sockets_new_listening_socket(), line 221: bind() for address '127.0.0.1:9000' failed: Address already in use (48)
а то у меня более поздняя, тогда я смогу портом поставить патч...
почему не поставите "более позднюю"?
Сейчас уже не надо ничего патчить, так как c версией php 5.3 - fpm внесли в состав дистрибутива php.
И через порты он ставится путем указания галочки в make config
Также есть пункт и для php 5.2
Блииин! Ребята, низкий поклон и огромнейшее спасибо за статью и обзор!
Недавно столкнулся с переносом корявоработающего сайта на новый сервер, где уже крутится nginx и php 5.5
Уже все настроено работает как часики. Но корявый сайт работает ТОЛЬКО под php 5.2, написан невероятно криворуко левой рукой из под правой коленки, а на переписывание времени нет. Было выбрано решение поставить параллельно с 5.5 5.2. Долго мучился с настройками пока не наткнулся на эту статью! На все вопросы в раз нашлись ответы!
Комментарии
Блииин, че нету в пакетах 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-формате)
Оставьте свой комментарий