У меня стоял 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);
from on .
Кстати, в видео я тоже поучаствовал, на 5-ой минуте и 20-ой секунде я там прохожу перед камерой в костюме и красной футболке... :D
Итак, приступим!
Установка Nginx
На самом деле Nginx у меня был уже установлен, но для полноты статьи я расскажу как и его установить. В зависимости от необходимого функционала, либо от стабильности версии, вам надо выбрать подходящую версию Nginx. Стабильная находится в каталоге «/usr/ports/www/nginx/», а более новая в «/usr/ports/www/nginx-devel/», у меня стоит именно вторая.
# make install clean
Всё, Nginx установлен, добавьте его в автозагрузку:
Установка php-fpm
Процесс заключается в пропатчивании и переустановки PHP интерпретатора с поддержкой FastCGI и php-fpm.
Установка из сорцов
Заходим на оф. сайт PHP и качаем необходимую версию PHP интерпретатора со страницы , у меня это PHP 5.2.10.
# fetch http://ru2.php.net/get/php-5.2.10.tar.gz/from/ru.php.net/mirror
Заходим на оф. сайт проекта php-fpm, в раздел загрузок и выбираем подходящую для вашего PHP интерпретатора версию патча. У меня это PHP 5.2.10, поэтому я буду ставить именно его.
# 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» и назначим ему права на запуск:
# chmod +x /usr/local/etc/rc.d/php-fpm
Установка из портов
Тут все намного проще... :)
# fetch http://php-fpm.org/downloads/freebsd-port/php-5.2.10-fpm-0.5.13.tar.gz
# 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 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» сегодняшний, то всё оки, если нет — отпишите в комментарии, помогу разобраться.
Я ставил и из сорцов и из портов, так что все проверено на себе! :)
Добавим в автозагрузку:
Настройка Nginx
Теперь настраиваем Nginx, отредактируйте конфиг «/usr/local/etc/nginx/nginx.conf» или свой «vhost»:
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», весь конфиг можно взять тут.
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/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;
location / {
root /home/adw0rd/adw0rd.ru/demo/public;
expires 7d;
try_files $uri @php;
}
location @php {
expires off;
fastcgi_pass 82.146.63.195:9000;
fastcgi_param SCRIPT_FILENAME /home/adw0rd/adw0rd.ru/demo/index.php;
include fastcgi_params;
}
}
Плюсы:
— не надо заморачиваться на расширения файлов. Можно указать 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 )
да, меня тоже достал PHP и я перешел на Python :) но по работе все еще приходится иметь дело с PHP, а также некоторые свои проекты на PHP поддерживаем/дорабатываем
А вот и про фейсбуковский HipHop
да я читал про этот хипхоп. интересно что быстрее — написаное на пхп и «скомпиленное» этим хипхопом или напимер джава.
Думаю скоро бенчмарки появятся.
Наверное, имелось ввиду:
# tar -xzf php-5.2.10.tar.gz
Спасибо что заметили, исправил
нужно в конфиге php-fpm.conf прописать
Address to accept fastcgi requests on.
Valid syntax is 'ip.ad.re.ss:port' or just 'port' or '/path/to/unix/socket'
х.х.х.х:9000
где x.x.x.x ваш ip адрес
Строка номер 41 Это типа на каком адресе слушать
А это вы на видео?)
Это все конечно хорошо, вот заинтересовался полным отказом от апача, но вот такой вопрос меня интересует, будет ли nginx распознавать .htaccess файлы? интересует deny,allow и мод реврайт. заранее спс.
На видео не я.
.htaccess — это только для апач, конечно nginx не будет их обрабатывать из коробки. Погуглите расширение для nginx которое нечто подобно делает.
По поводу рерайтов — это есть, deny/allow тоже, читайте документацию на
Походу .htaccess читаться не будет... а что же тогда делать, прописывать подобные вещи
location / {
deny 192.168.1.1;
allow 192.168.1.0/24;
allow 10.1.1.0/16;
deny all;
}
неудобно
да, спасибо, вот уже читаю доки (не прочитал пред. ваш пост, слишком быстро ответили :) )... еще такой вопрос, а подобным образом пропатченный php будет работать как mod apache?
Погуглите
а при использовании php-fpm как описано в этой статье будут идти ероры согласно параметру в php.ini?
; Log errors to specified file.
error_log = /file.log
Еще подскажите пожалуйста, как сделать короче такие правила
location /page1.php {
deny all;
}
location /page2.php {
deny all;
}
то есть в 1 location это можно записать?
так правильно?
deny all;
}
Правильно так, как вы написали в посте от 03.01.2011.
Работать будет и второй вариант, но такого написания лучше избегать.
Очень рекомендую посмотреть
Fighter,
1. Тут про error.log — adw0rd.ru/2010/ubuntu-php53/
2. Лучше делать на каждое событие свой location, как и сказал ash2k: «в посте от 03.01.2011». Когда будет много location — вы сами запутаетесь, я сталкиваюсь постоянно с этим на работе, постепенно переделывая location из регулярок в просто location, если конечно это возможно... Так что посмотрите видео и избегайте регулярок и if'ов
Да просто правил море :)
а в инклуд не хочется выносить...
еще такой вопрос, вот в апаче когда php как модуль можно указать эти переменные
php_admin_value sendmail_path "/usr/sbin/sendmail -t -i -f webmaster@host"
php_admin_value session.save_path "/home/user/data/mod-tmp"
php_admin_value upload_tmp_dir "/home/user/data/mod-tmp"
а где их указать когда используется PHP-FPM? нужно чтоб сендмаил работал...
извиняюсь, про сендмаил уже нашел здесь adw0rd.ru/2010/ubuntu-php53/ :)
я так полагаю это необходимо раскомментировать
<!-- /usr/sbin/sendmail -t -i -->
еще вопрос насчет этих настроек
<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.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)
Перезагрузите систему
можно как-то из портов поставить php-5.2.10? а то у меня более поздняя, тогда я смогу портом поставить патч...
зачем перезагрузить, без этого никак?
можно «5.2.*», смотрите /usr/ports/lang/php52/
почему не поставите «более позднюю»?
Сейчас уже не надо ничего патчить, так как c версией php 5.3 — fpm внесли в состав дистрибутива php.
И через порты он ставится путем указания галочки в make config
Также есть пункт и для php 5.2
Комментарии закрываю в силу того, что:
* у PHP-FPM изменился формат конфига
* теперь можно ставить из портов (см. выше комментарий), а не патчить
Возможно вас заинтерисует:
adw0rd.ru/tag/nginx/
adw0rd.ru/tag/php-fpm/
adw0rd.ru/tag/fastcgi/
adw0rd.ru/tag/php/