Настройка связки Nginx Apache FastCGI

В предыдущей статье "Установка и настройка веб сервера Nginx в качестве проксирующего фронтэнда к Apache", был рассмотрен простой вариант установки и использования Nginx, с настройками по-умолчанию, в качестве проксирующего сервера, с сервером Apache в качестве проксиркемого бакэнда.

В данном материале хотелось-бы рассказать о более сложном варианте установки и настройки Nginx, для построения связки Nginx Apache FastCGI. Для организации FastCGI сервера, будет использована утилиты, spawn-fcgi, ранее входившая в состав веб сервера lighttpd, а теперь выделенная в отдельный порт.

Схема работы связки Nginx - Apache - FastCGI, выглядит следующим образом:

схема работы связки nginx -apache - fastcgi

Теперь на словах. Все запросы приходят на адрес, на котором сервер Nginx принимает соединения. Согласно настройкам в конфигурационном файле Nginx:

  • Все статические запросы ( HTML файлы, картинки ), будут обработаны веб сервером Nginx самостоятельно, после чего результат будет выдан клиенту;
  • Запросы к CGI и Perl ( файлы CGI, PL ) скриптам, будут отправлены на обработку Apache, после обработки, результат будет передан в Nginx и отдан клиенту;
  • Все запросы к скриптам PHP, будут перенаправлены на сервер FastCGI, после обработки, результат опять-же будет возвращен в Nginx и выдан клиенту;

Итак, что мы имеем: операционная система FreeBSD 7.1 STABLE ( платформа amd64 ), установленный веб сервер Apache/2.2.9. Установка Nginx производилась со следующими опциями:

vds-admin$ nginx -V
nginx version: nginx/0.7.61
built by gcc 4.2.1 20070719 [FreeBSD]
configure arguments: 
--prefix=/usr/local/etc/nginx 
--sbin-path=/usr/local/sbin/nginx 
--conf-path=/usr/local/etc/nginx/conf/nginx.conf 
--error-log-path=/usr/local/etc/nginx/logs/error.log 
--with-http_stub_status_module 
--user=www

PHP с поддержкой FastCGI интерфейса

Настройку сервера Nginx, сделаем чуть позже, сначала настроим FastCGI сервер, установив все необходимое. Что вообще такое, FastCGI. В общем понимании, это протокол взаимодействия, между веб сервером и приложением, не зависимый от языка приложения и являющийся куда более производительным и безопасным, нежели обычный CGI. Если коротко, обычную CGI программу, веб серверу, приходится запускать на каждый запрос, в то время как FastCGI, постоянно держит запущенный процесс, который и обслуживает приходящие ему запросы. Кроме того веб сервер, связывается с FastCGI сервером, через так называемый "Unix domain socket" или через TCP/IP, в отличии от обычного CGI, который взаимодействует с сервером через стандартный ввод/вывод, что дает возможность располагать FastCGI сервер, не только в рамках одной машины, но и вообще где угодно в сети.

В контексте данного материала, речь идет о языке PHP, собранном с поддержкой FastCGI и запущенном с помощью специального приложения.

Для поддержки данного режима работы, PHP, должен быть скомпилирован с соответствующими опциями и иметь необходимый бинарник ( запускаемый файл, по умолчанию php-cgi.) Следующие опции необходимы для сборки PHP с поддержкой FasCGI и обеспечения необходимого уровня безопасности:

--enable-fastcgi
--enable-force-cgi-redirect
--enable-discard-path

Остальные опции ставите в зависимости от ваших потребностей.

Посмотреть опции, с которыми собран PHP, можно так:

vds-admin$root/ php -i | grep configure Configure Command => './configure' '--with-layout=GNU' '--with-config-file-scan-dir=/usr/local/etc/php' '--disable-all' '--enable-libxml' '--with-libxml-dir=/usr/local' '--enable-reflection' '--program-prefix=' '--enable-force-cgi-redirect' '--enable-discard-path' '--enable-fastcgi' '--with-apxs2=/usr/local/sbin/apxs' '--with-regex=php' '--with-zend-vm=CALL' '--enable-zend-multibyte' '--disable-ipv6' '--prefix=/usr/local' '--mandir=/usr/local/man' '--infodir=/usr/local/info/' '--build=amd64-portbld-freebsd7.1'

Установка и настройка spawn-fcgi для запуска FastCGI сарвера PHP

Процесс сборки и установки длится меньше минуты. По завершению, будет создано несколько файлов:

/usr/local/bin/spawn-fcgi #Запускаемый файл программы
/usr/local/etc/rc.d/spawn-fcgi #Cтартовый скрипт, для запуска FastCGI сервера

Как правило я использую Unix Socket для связи сервера Nginx с FastCGI сервером ( хотя в случае возникновения проблем, можно использовать TCP/IP ), поэтому идем править стартовый скрипт, приведя его переменные к такому виду:

: ${spawn_fcgi_app="/usr/local/bin/php-cgi"}        #Приложение для запуска
: ${spawn_fcgi_pidfile="/var/run/spawn-fcgi.pid"}   #Файл содержащий ID процесса
: ${spawn_fcgi_user="www"}                          #Пользователь, под которым будет выполняться приложение
: ${spawn_fcgi_group="www"}                         #Группа
: ${spawn_fcgi_socket="/tmp/fastcgi_sock"}          #Файл Unix сокета
#: ${spawn_fcgi_bindaddr="127.0.0.1"}               #В данном случае мы не используем TCP/IP
#: ${spawn_fcgi_bindport="9000"}
: ${spawn_fcgi_children="5"}                        #Количество дочерних процессов php-cgi
: ${spawn_fcgi_max_requests="1000"}                 #Количество обслуженных запросов, после которого дочерний процесс будет перезапущен
: ${spawn_fcgi_web_server_addrs=""}
: ${spawn_fcgi_allowed_env=""}
: ${spawn_fcgi_path_env="/sbin:/bin:/usr/sbin:/usr/bin:/usr/games:/usr/local/sbin:/usr/local/bin"}

command="/usr/local/bin/spawn-fcgi"
command_args="-u ${spawn_fcgi_user} -g ${spawn_fcgi_group} -P ${spawn_fcgi_pidfile} -s ${spawn_fcgi_socket} -- ${spawn_fcgi_app}" #Это собственно и есть команда запуска со всеми необходимыми аргументами.

Полный список опций программы spawn-fcgi, приведен тут Spawn-fcgi запуск процессов в FastCGI режиме

Не забываем добавить строку spawn_fcgi_enable="YES" в стартовый скрипт /etc/rc.conf, для запуска FastCGI сервера при старте системы.

vds-admin$ echo "spawn_fcgi_enable=YES" >> /etc/rc.conf

Пробуем запустить spawn-fcgi:

vds-admin/# /usr/local/etc/rc.d/spawn-fcgi start
Starting spawn_fcgi.
spawn-fcgi: child spawned successfully: PID: 33019
#Проверяем наличие запущенных процессов:
vds-admin/# ps aux | grep php
www 33019 0.0 1.5 92332 15832 ?? Ss 5:01PM 0:00.08 /usr/local/bin/php-cgi
www 33020 0.0 1.5 92332 15872 ?? S 5:01PM 0:00.00 /usr/local/bin/php-cgi
www 33021 0.0 1.5 92332 15872 ?? S 5:01PM 0:00.00 /usr/local/bin/php-cgi
www 33022 0.0 1.5 92332 15872 ?? S 5:01PM 0:00.00 /usr/local/bin/php-cgi
www 33023 0.0 1.5 92332 15872 ?? S 5:01PM 0:00.00 /usr/local/bin/php-cgi
www 33024 0.0 1.5 92332 15872 ?? S 5:01PM 0:00.00 /usr/local/bin/php-cgi
#Проверяем наличие соответствующего сокета:
vds-admin$ netstat -Lan
Current listen queue sizes (qlen/incqlen/maxqlen)
Proto Listen Local Address
....................................
unix 0/0/128 /tmp/fastcgi_sock #Наш FastCGI сокет для работы с веб-сервером Nginx
....................................

FastCGI сервер готов к работе

Настройка веб сервера Apache

Настройка сервера Apache, аналогична той, которую мы делали в статье "Установка и настройка веб сервера Nginx в качестве проксирующего фронтэнда к Apache". То есть задача сводится к смене IP адреса и, если необходимо, порта, на которых веб-сервер Apache будет принимать запросы от Nginx и опять-же по мере надобности, настройка виртуальных хостов, так-же затронутая в вышеприведенной статье. Напомню, сервер Apache будет принимать соединения на локальном адресе 127.0.0.1, порт 80. Кроме того, все в той-же статье, мы настроили модуль сервера Apache, mod_rpaf, для передачи в Apache, реальных адресов клиентов, а не внутреннего адреса сервера Nginx.

Настройка веб сервера Nginx, на работу с бакэндами, Apache и FastCGI

Опции с которыми был установлен сервер Nginx, приводились выше, то есть по сути, это "умолчальная" установка, изменены некоторые пути, как мне привычней и включен модуль для просмотра статусной страницы Nginx.

Перейдем к конфигурационному файлу.

Хотелось-бы отметить, что окончательный вид конфигурационного файла Nginx, зависит от вашей конкретной системы, то есть например, различные таймауты, размеры и количество буферов, передаваемые заголовки и т.д., должны быть установлены, исходя из задач, решаемых на данном сервере. Поэтому давать рекомендации в стиле, "поставьте этого столько а того столько и напишите это.. потому что у меня это работает.. ", считаю неуместным.

Здесь у нас рабочий вариант конфигурационного файла nginx, так сказать, без наворотов, лишь необходимый минимум. Выглядит он у нас следующим образом:

user  www;
worker_processes  1;

error_log  logs/error.log;
#error_log  logs/error.log  notice;
#error_log  logs/error.log  info;

#pid        logs/nginx.pid;

events {
    worker_connections  1024;
}

http {
    include       mime.types;
    default_type  application/octet-stream;

    log_format  main  '$remote_addr - $remote_user [$time_local] "$request" '
                      '$status $body_bytes_sent "$http_referer" '
                      '"$http_user_agent" "$http_x_forwarded_for"';

    #access_log  logs/access.log  main;

    sendfile        on;
    tcp_nopush      on;

    #keepalive_timeout  0;
    keepalive_timeout  65;
    reset_timedout_connection  on;

    #gzip  on;

    server {
        listen       192.168.50.20:80;     # Внешний IP адрес, на котором Nginx принимает соединения
        server_name  nginxhost;            # Имя хоста

        #charset koi8-r;

        access_log  logs/host.access.log  main;

        root /home/nginxhost/public_html;

##############################################
        location / {                            
            index  index.html index.htm;
        }

        location ~* \.(jpeg|jpg|png|gif){
            expires max;
        }
# Данные две секции Location, будет обрабатывать Nginx

#############################################

#################  Apache  #####################
        location ~ \.(pl|cgi)$ {
            proxy_pass   http://127.0.0.1;
            proxy_redirect     off;
            proxy_set_header Host $host;
            proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        }
# Запросы соответствующие этому Location, будут переданы на обработку веб серверу Apache

#############################################

################## FastCGI #####################
        location ~ \.php$ {
            fastcgi_pass   unix:/tmp/fastcgi_sock;        # Сокет для связи с FastCGI
            fastcgi_index  index.php;                     # Индексный файл
            fastcgi_param  SCRIPT_FILENAME  $document_root$fastcgi_script_name;
#Переменная $document_root, содержит путь к корневой папке дерева документов
#переменная $fastcgi_script_name, содержит имя запрошенного файла скрипта
            include        fastcgi_params;                # Включение файла с fastcgi параметрами, передаваемыми fastcgi серверу
        }
# Эти запросы будут переданы для обработки FastCGI серверу

#############################################

        location ~ /\.ht {
            deny  all;
        }

        error_page  404              /404.html;
        error_page   500 502 503 504  /50x.html;
        location = /50x.html {
            root   html;
        }
    }
}

Проверяем правильность файла конфигурации:

vds-admin$ nginx -t the configuration file /usr/local/etc/nginx/conf/nginx.conf syntax is ok configuration file /usr/local/etc/nginx/conf/nginx.conf test is successful 

Все в порядке, можно запускать

vds-admin$ nginx 

Проверим что у нас там показывает netstat:

vds-admin$ netstat -Lan
Current listen queue sizes (qlen/incqlen/maxqlen)
Proto Listen Local Address
tcp4 0/0/128 192.168.50.20.80 #Cервер Nginx ( фронтэнд )
.........................
tcp4 0/0/128 127.0.0.1.80 #Сервер Apache ( бакэнд 1 )
.........................
unix 0/0/128 /tmp/fastcgi_sock #Сервер FastCGI ( бакэнд 2 )
.........................

Теперь все это можно проверить через браузер, набрав имя хоста Nginx или IP адрес. Что-бы убедиться что PHP скрипты обрабатываются нашим FastCGI сервером, можно создать файл следующего содержания:

  1. <?php
  2. phpinfo();
  3. ?>

и положить его в корневую директорию документов сайта. Теперь запросив его через браузер, мы увидим страницу PHP, с кучей различной технической информации, включая опции сборки, настройки, модули, расширения, конфигурационные файлы и т.д. Находим строку Server API, и видим в каком режиме работает PHP на данном хосте, это у нас, CGI/FastCGI, то есть, то что нам и было нужно.

Проверить, что и остальные Location, отрабатывают должным образом, передавая запросы бакэндам, можно так, создать необходимый файл, запросить его через строку браузера и проверить лог файлы. То есть, запрос к файлу test.pl, можно будет обнаружить в файле access.log, виртуального хоста, сервера Apache, а запрос к файлу test.html, в лог файле веб сервера Nginx.

На этом пока хотелось-бы закончить. Удачи.

Комментарии

.htaccess будит работать при такой связке??

в той части, которую обрабатывает апач, да

У меня нивкакую не хочет работать .htaccess при такой связке, может подскажете где грабли могут быть, ну или мелкие фишки?

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

можно как нибудь в асю пообщаться?

Не обрабатывает правила

Options -MultiViews
RewriteEngine On
RewriteBase /
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule . /index.php [L]

Как быть?

Статья толковая и мне понравилась.

Но никак не могу заставить свою связку nginx/fastcgi работать.

nginx работает, отдаёт статичные файлы и бэкэнд к apache работает хорошо. Хочу поднять php/fpm.
fastcgi занимает сокет или порт, но не возвращая контент в nginx, возвращает статус 200.
$document_root и $fastcgi_script, судя по логам, возвращают корректные значения.
Доступ к корневой папке сервера для nobody на чтение есть.

access.log

127.0.0.1 - [25/May/2011:00:54:48 +0400] 
  REQUEST: "GET /index.php HTTP/1.1" 200 160 
  ROOT: "/var/www/localhost/htdocs" 
  SCRIPT: "/index.php"

error.log

2011/05/25 00:54:48 [info] 16375#0: *1 client 127.0.0.1 closed keepalive connection

nginx.conf

worker_processes 1;

user nginx nginx;

pid /var/run/nginx.pid;
error_log /var/log/nginx/error_log info;

events {
  worker_connections 1024; # increase if you have lots of clients
  accept_mutex off; # "on" if nginx worker_processes > 1
  use epoll; # enable for Linux 2.6+
}

http {
  include /etc/nginx/mime.types;

  default_type application/octet-stream;

  log_format test
    '$remote_addr $remote_user [$time_local] '
    '\n  REQUEST: "$request" $status $bytes_sent '
    '\n  ROOT: "$document_root" '
    '\n  SCRIPT: "$fastcgi_script_name" ';

  sendfile on;

  tcp_nopush on; # off may be better for *some* Comet/long-poll stuff
  tcp_nodelay off; # on may be better for some Comet/long-poll stuff

  gzip on;
  gzip_http_version 1.0;
  gzip_proxied any;
  gzip_min_length 500;
  gzip_disable "MSIE [1-6]\.";
  gzip_buffers 4 8k;
  gzip_types text/plain text/xml text/css
             text/comma-separated-values
             text/javascript application/x-javascript;

   server { # localhost test
    listen 80;
    server_name localhost;

    access_log /var/log/nginx/localhost-access.log test;
    error_log /var/log/nginx/localhost-error.log info;

    location / {
      root /var/www/localhost/htdocs;
      index index.php;
    }

    location ~ \.php$ {
      root /var/www/localhost/htdocs;
      fastcgi_pass unix:/var/run/fpm.sock;
      fastcgi_index index.php;
      include fastcgi_params;
    }


}

php-fpm.conf

pid = /var/run/php-fpm.pid
error_log = /var/log/php-fpm/error.log
log_level = notice
[www]
  listen = /var/run/fpm.sock
  user = nobody
  group = nobody

  pm = static
  pm.max_children = 20

Gentoo, php собран с cli, cgi, fpm, apache2

попробуйте с дебагом собрать, думаю там видней будет

Не знаю зачем тебе, но вот тут - http://joomlaforum.ru/index.php/topic,35335.150.html
конфигурация гникса описана с отрабатывающим .htaccess

там все запросы кроме картинок, летят на апач, поэтому там htaccess и работает
а тут на апач уходит только perl/cgi, ПХП обрабатывается на fastcgi сервере, все остальное nginx

Дань скорости обработки запроса... увы

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

Содержание этого поля является приватным и не предназначено к показу.
Регистр имеет значение
 ooooooooo.    ooooo     ooo    .oooooo.              ooooo      ooo        .o8  
`888 `Y88. `888' `8' d8P' `Y8b `888b. `8' "888
888 .d88' 888 8 888 oooo d8b 8 `88b. 8 .oooo888
888ooo88P' 888 8 888 `888""8P 8 `88b. 8 d88' `888
888 888 8 888 888 8 `88b.8 888 888
888 `88. .8' `88b ooo 888 8 `888 888 888
o888o `YbodP' `Y8bood8P' d888b o8o `8 `Y8bod88P"


Введите код, изображенный в стиле ASCII-арт.