25 ноября 2010 г. FastCGI Nginx PHP spawn-fcgi

Nginx. Использование PHP в режиме FastCGI с помощью spawn-fcgi

php-fastcgi

В прошлой статье о FastCGi - Nginx. Использование PHP в режиме FastCGI с помощью php-fpm я рассказал как использовать php-fpm спаунер (надо сказать, что с тех времен все сильно поменялось, например вышел php 5.3.3 и php-fpm стал входить в дистрибутив php, а так же поменялся формат конфига php-fpm). Сегодня расскажу как использовать spawn-fcgi, некогда входивший в дистрибутив lighttpd, а ныне являющийся отдельным проектом.

Установка

Перед установкой спаунера убедимся, что PHP собран с поддержкой CGi:

[X] CGI        Build CGI version

Далее заходим в порты и устанавливаем spawn-fcgi:

cd /usr/ports/www/spawn-fcgi
make install clean

Настройка

Отредактируйте "nginx.conf" и добавьте upstream:

upstream spawn-fcgi {
    server unix:/tmp/spawn-fcgi.sock;
}

Откройте на редактирование файл "/etc/rc.conf" и укажите необходимые настройки:

# При запуске системы загружать spawn-fcgi
spawn_fcgi_enable="YES"

# Пользователь от которой работать будет php-cgi
spawn_fcgi_username="www"

# Группа
spawn_fcgi_groupname="www"

# Путь до unix-сокета, именно его мы используем
spawn_fcgi_bindsocket="/tmp/spawn-fcgi.sock"

# Количество запущенных php-cgi процессов
spawn_fcgi_children="5"

# Кол-во запросов, после которых перезагружается процесс (для предотвращения утечек памяти)
spawn_fcgi_max_requests="1000"

Полный перечень допустимых настроек можно посмотреть в "/usr/local/etc/rc.d/spawn-fcgi", вот некоторые из них, о которых я не упоминал выше:

# Путь до php-cgi приложения
spawn_fcgi_app="/usr/local/bin/php-cgi"

# Дополнительные аргументы для php-cgi (их можно узнать командой "php-cgi -h")
spawn_fcgi_app_args=""

# Вы можете указать путь до песочницы
spawn_fcgi_chroot_dir=""

# IP адрес, который будет слушать демон
spawn_fcgi_bindaddr="127.0.0.1"

# Соответственно порт
spawn_fcgi_bindport="9000"

# Путь до PID файла
spawn_fcgi_pidfile="/var/run/spawn-fcgi.pid"

# Права на файл unix-сокета
spawn_fcgi_bindsocket_mode="0777"

Запуск

Запускаем spawn-fcgi и перезагружаем nginx:

/usr/local/etc/rc.d/spawn-fcgi start
nginx -s reload

Используемая версия spawn-fcgi - 1.6.3

Комментарии

Ай-ай-ай! Зачем людей плохому учишь?))) Кто-же это редактирует rc-скрипт когда все переменные можно по-нормальному задать в rc.conf?
Захочешь вот обновить spawn - а после переустановки все настройки в этом скрипте будут затерты свежеустановленной версией скрипта.

Да, ты прав, поначалу я так и сделал, но потом меня что-то перемкнуло, сейчас поправлю :)

А в чем разница php-fpm и spawn? Где скорость больше?

spawn-fcgi vs php-fpm
http://www.twitpic.com/1dxswp/full

Спасибо, почитаю. А по личным ощущениям как?

Мне по функциональности нравится больше php-fpm, посмотрите его конфиг и станет понятно почему, думаю. А со spawn-fcgi я мало работал, ничего не могу сказать

php-fpm 5.3.3 я сейчас и использую, просто думал раз вы про spawn написали, то может есть какие-то преимущества;)

php-fpm прикольная вещичка...

А при такой настройке как настраивать в nginx.conf location'ы, где идут php скрипты?

так же как и в fpm, меняется только значение директивы fastcgi_pass с php-fpm на spawn-fcgi

вы не в курсе, если ставить spawn-fcgi, он с eaccelerator так же хорошо работает как и fpm?

так, взялся я за этот, ставится он проще..
значит пишу
upstream spawn-fcgi {
server unix:/tmp/spawn-fcgi.sock;
}

а потом в локэйшн

location / {
            fastcgi_pass   spawn-fcgi;
            fastcgi_index  index.php;
            fastcgi_param  SCRIPT_FILENAME  /home/user/www/site$fastcgi_script_name;
            include        fastcgi_params;
        }

все верно?

да, все верно с виду, выполните nginx -t

окей, спасибо. помогите еще пожалуйста с одним моментом.. если запросить скрипт, который не существует, выводится
No input file specified.

не получается составить правило

location ~ .php$ {
try_files $uri 404;
}

даже существующие файлы распознаются как несуществующие...

Попробуйте:

try_files $uri =404;

http://sysoev.ru/nginx/docs/http/ngx_http_core_module.html#try_files

пробовал, читал... на все выдает 404

уже решил проблему.

а вы не в курсе, можно как-то переопределить $_SERVER['DOCUMENT_ROOT']? а то он неверный

В Nginx это называет $document_root. Задается через директиву root, либо так:

fastcgi_param  DOCUMENT_ROOT /path/to/;

...не работает allow по айпи, хотя deny all работает. Что это может быть?

пример

location /dir/ {
allow 11.11.11.11;
eny all;
}

постоянно выдает форбайдн

Что такое "eny"? Если просто опечатка, то приведите настоящий конфиг

location / {
    allow 127.0.0.1;
    deny all;
    ...
}

Вот так у меня работает прекрасно

извиняюсь, у меня в конфиге deny
просто мне нужно, чтоб если по правилу подходит

location /dir/ {
allow 11.11.11.11;

deny all;
}

искались локэйшэны дальше, а этого судя по всему не происходит...

и еще можете пожалуйста помочь сформировать правило location, которое будет на себя брать ВСЕ файлы кроме *.php ну и косой черты */

просто мне нужно, чтоб если по правилу подходит
location /dir/ {
allow 11.11.11.11;
deny all;
}
искались локэйшэны дальше, а этого судя по всему не происходит...

Мне кажется вы не верно используете location. Думаю вам надо использовать if:


if ($remote_addr != '11.11.11.11') {
    return 403;
}
и еще можете пожалуйста помочь сформировать правило location, которое будет на себя брать ВСЕ файлы кроме *.php ну и косой черты */

наверное как-то так:


location / {
    if ($request_uri !~ (\.php|/)$) {
        ...
    }
}

но мне кажется вы что-то не так спроектировали :)

хм, а я не совсем понял, в if'ах поддерживаются andы? например чтоб проверить и айпи и директорию

Насколько я помню - не поддерживаются. Но никто не отменял использование вложенных if'ов

if ... {
    if ... {
        #...
    }
}

неа, вложенные не кушает. а так же это if ($remote_addr != '11.11.11.11') неправильно

У вас какая версия nginx?

извиняюсь, if ($remote_addr != '11.11.11.11') работает, а вот вложенные ифы запрещенны

syntax: if (условие) { ... } default: нет context: server, location

Ссори, наверное я попутал с чем-то другим. Но location точно есть вложенные

вопрос конкретно по php-fpm, но spawn-fcgi он в теории тоже касается. каждый воркер может одновременно обрабатывать только 1 запрос? т. е. если у меня 100 воркеров

<value name="max_children">100</value>

одновременно могут выполняться только 100 запросов, так? если их будет больше, будет вылетать 502?

мде... и тишина.

В документацию не пробовали сходить? Там вроде как все написано

А как можно сделать несколько локейшенов для обработки index.php с различными параметрами, при том что правило rewrite(аналогично .htacces) стоит перед этими правилами,
суть:
location / {
root /.../httpdocs;
index index.php;
if (!-e $request_filename) {
rewrite ^/(.*) /index.php last;
}
}

    location ~ \.php$ {
        root /.../httpdocs;
        fastcgi_pass 127.0.0.1:9000;

        fastcgi_cache mainzone;
        fastcgi_cache_valid 200 302 304 15m;
        fastcgi_cache_valid 301 1h;
        fastcgi_cache_valid any 5m;
        fastcgi_cache_min_uses 1;

        fastcgi_connect_timeout 5m;
        fastcgi_read_timeout 5m;
        fastcgi_send_timeout 5m;

        fastcgi_cache_key "$request_method|$http_if_modified_since|$http_if_none_match|$host|$request_uri";
        fastcgi_cache_bypass $cookie_COOKIE;
        fastcgi_no_cache $cookie_COOKIE;
            fastcgi_hide_header "Set-Cookie";
        fastcgi_ignore_headers "Cache-Control" "Expires" "Set-Cookie";
        fastcgi_cache_use_stale updating error timeout invalid_header http_500;
        fastcgi_temp_path  /var/www/nginx/temp/ 1 2;

        include /etc/nginx/fastcgi_params;
        fastcgi_index index.php;
        fastcgi_param SCRIPT_FILENAME /.../httpdocs$fastcgi_script_name;
    }

в location / передаются параметры запроса для обработки SEF урл-ов
надо, чтобы часть url-ов не кешировалась,
часть кешировалась, как это сделано в location ~ .php$

Сразу, хочу поблагодарить за ваш столь информационный, познавательный сайт!
Помогите мне плз с проблемой, третий день бьюсь, никак не могу решить...
Поставить и наладить работу nginx + php-cgi через spawn-fcgi удалось довольно таки быстро,
проблемы начались с подключения к PHP xcache.
После подключения nginx на каждый второй запрос начал отвечать 502-ым bad gateway даже чаще,
в логах nginx
"upstream prematurely closed connection while reading response header from upstream" ?

В чем может быть проблема, запускаю какой-нить скрипт php-cgi -f phpinfo.php норм запускается? это значит проблема
spawn-fcgi?

2Loki
Там аутентификацию нужно выключить в xcache.ini

!/bin/sh

Местоположение бинарного файла php-cgi

PHP=/usr/local/bin/php-cgi

Местоположение PID-файла

PHP_PID=/tmp/php.pid

Привязка к адресу

FCGI_BIND_ADDRESS=10.0.1.1:10000

Привязка к сокету

FCGI_BIND_ADDRESS=/tmp/php.sock

PHP_FCGI_CHILDREN=16
PHP_FCGI_MAX_REQUESTS=10000

env -i PHP_FCGI_CHILDREN=$PHP_FCGI_CHILDREN \
PHP_FCGI_MAX_REQUESTS=$PHP_FCGI_MAX_REQUESTS \
$PHP -b $FCGI_BIND_ADDRESS &

echo $! > "$PHP_PID"

далее в nginx
fastcgi_pass 127.0.0.1:9000;
fastcgi_param SCRIPT_FILENAME /.../httpdocs$fastcgi_sсript_name;

Оставьте свой комментарий

Markdown