Сегодня мы затронем такую интересную тему как повышение скорости работы вашего сайта. Конечно же это и оптимизированный код и оптимизированные sql-запросы. Но есть и еще несколько мест, в которых производительность может падать. Одним из таких мест является http-сервер Apache. Есть целый ряд трюков, которые позволяют повысить пропускную способность этого узкого места. Один из таких трюков - установка вместо Apache более легковесного сервера. Одним из интересных решений может быть использование вместо Apache сервера Nginx, который разрабатывается Игорем Сысоевым.

Этот веб-сервер обладает немалыми возможностями. С полным их списком вы можете ознакомиться на официальном сайте. В данной статье пойдет речь о том как использовать вместо Apache этот замечательный сервер. Если ваш сервер на базе FreeBSD, то вот замечательная инструкция по установке Nginx в связке с php.

А наша статья конечно же для тех у кого Linux. Традиционно пример на основе openSUSE. Если у вас есть положительный или отрицательный опыт по данной теме с другими дистрибутивами, то напишите обязательно об этом в комментариях.

Итак начнем. Основная проблема в том, что у Nginx нет модуля mod_php. Однако он поддерживает технологию FastCGI для работы с внешними серверами и утилитами. PHP также поддерживает FastCGI и может быть использован для обработки FastCGI-запросов от nginx.

Существует 2 подхода

  1. Запуск встроенного в php сервера fastCGI
  2. Запуск php внутри стороннего обработчика запросов

Первый метод проще, а второй более гибок в настройках. Поэтому рассмотрим второй способ с использованием spawn-php.sh из пакета lighttpd.

Собирать все пакеты из исходников нам не придется. Если у кого-нибудь есть такая необходимость, то можете воспользоваться инструкцией для FreeBSD.

Для openSUSE мы возьмем lighttpd из репозитория  openSUSE-11-Updates, а сам nginx из репозитоия gwdg.

После этого нам надо настроить spawn-php.sh как отдельную службу (так как нам весь lighttpd не нужен). Копируем из пакета один только файл в удобное для нас место и задаем права на выполнение:

cp /usr/share/doc/packages/lighttpd/spawn-php.sh /usr/bin/spawn-php
chmod 775 /usr/bin/spawn-php

Теперь нам надо настроить данный скрипт под нашу систему. Поменяйте приведенную часть в соответствии со своими путями

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
#!/bin/bash
 
## ABSOLUTE path to the spawn-fcgi binary
SPAWNFCGI="/usr/sbin/spawn-fcgi"
 
## ABSOLUTE path to the PHP binary
FCGIPROGRAM="/usr/bin/php-cgi"
 
## TCP port to which to bind on localhost
FCGIPORT="1026"
 
## number of PHP children to spawn
PHP_FCGI_CHILDREN=10
 
## maximum number of requests a single PHP 
##     process can serve before it is restarted
PHP_FCGI_MAX_REQUESTS=1000
 
## IP addresses from which PHP should access server connections
FCGI_WEB_SERVER_ADDRS="127.0.0.1,10.1.1.113"
 
# allowed environment variables, separated by spaces
ALLOWED_ENV="ORACLE_HOME PATH USER"
 
## if this script is run as root, switch to the following user
USERID=wwwrun
GROUPID=www

Впишите свои значения для SPAWNFCGI, FCGIPROGRAM, USERID и GROUPID. И обратите внимание на FCGIPORT. Это порт по которому будут общаться nginx и spawn-php. Его можно менять на свой вкус. Но надо чтобы он совпадал с настройками самого nginx (они будут приведены далее).
Теперь надо сделать чтобы при старте системы скрипт запускался. Конечно мы могли бы сделать очень просто. Поместив вызов скрипта либо в файл /etc/init.d/boot.local , либо в файл /etc/init.d/before.local вы получите его автозапуск. В первом случае скрипт выполняется в самом начале, сразу после запуска скриптов из /etc/init.d/boot.d, а во втором - непосредственно перед началом запуска выбранного runlevel-а. Но вот если вам понадобится перезагрузить или остановить этот fastcgi-сервер, то вам придется вспоминать как называется та программа, которую надо kill-нуть чтобы остановить сервер (Кстати, это php-cgi). Кого этот путь устраивает, те могут перейти уже к настройке nginx.
Мы же пойдем по правильному пути. Обернем скрипт таким образом чтобы он вел себя как демон. Для этого есть заготовка /etc/init.d/skeleton. У шаблона подробные комментарии и простая структура. Но все же я внес несколько изменений, которые ближе к нашей задаче. Вот листинг нашего нового файла /etc/init.d/spawn-php-demon:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
#!/bin/sh
### BEGIN INIT INFO
# Provides:          spawn-php-demon
# Required-Start:    $syslog $remote_fs
# Should-Start: $time ypbind sendmail
# Required-Stop:     $syslog $remote_fs
# Should-Stop: $time ypbind sendmail
# Default-Start:     3 5
# Default-Stop:      0 1 2 6
# Short-Description: spawn-php-demon
# Description:       demon for using php as cgi for nginx
### END INIT INFO
SPAWNPHP_BIN=/usr/bin/spawn-php
PHP_CGI=/usr/bin/php-cgi
test -x $SPAWNPHP_BIN || { echo "Spawn-php not installed"; 
	if [ "$1" = "stop" ]; then exit 0;
	else exit 5; fi; }
 
 
. /etc/rc.status
 
# Reset status of this service
rc_reset
 
case "$1" in
    start)
	echo -n "Starting spawn-php "
	## Start daemon with startproc(8). If this fails
	## the return value is set appropriately by startproc.
	/sbin/startproc $SPAWNPHP_BIN
	/sbin/checkproc $PHP_CGI
	rc_status -v
	;;
    stop)
	echo -n "Shutting down spawn-php "
	## Stop daemon with killproc(8) and if this fails
	## killproc sets the return value according to LSB.
	/sbin/killproc -TERM $PHP_CGI
	# Remember status and be verbose
	rc_status -v
	;;
    restart)
	## Stop the service and regardless of whether it was
	## running or not, start it again.
	$0 stop
	$0 start
	# Remember status and be quiet
	rc_status
	;;
    status)
	echo -n "Checking for service spawn-php "
	## Check status with checkproc(8), if process is running
	## checkproc will return with exit status 0.
	# NOTE: checkproc returns LSB compliant status values.
	/sbin/checkproc $PHP_CGI
	# NOTE: rc_status knows that we called this init script with
	# "status" option and adapts its messages accordingly.
	rc_status -v
	;;
esac
rc_exit

Теперь мы очень удобно сможем останавливать и запускать службу. В openSUSE конечно же есть GUI для этих целей. Но в консоле быстрее.

linux-r2ch:/home/izumeroot # /etc/init.d/spawn-php-demon start
Starting spawn-php spawn-fcgi.c.197: child spawned successfully: PID: 5527
                                                                      done
linux-r2ch:/home/izumeroot # /etc/init.d/spawn-php-demon stop
Shutting down spawn-php                                               done

Теперь нам надо внести в настройки системы необходимость автоматического запуска этой службы. Но об этом позже. Вообще-то есть еще альтернатива. Можно внести вызов spam-php в скрипт демона nginx и туда же /usr/bin/php-cgi. Это позволит нам одной командой выключать и включать оба сервера сразу и не надо создавать обертку. Но мне только сейчас пришла в голову эта идея. Поэтому можете реализовать ее самостоятельно.
Давайте перейдем к настройке nginx. Откроем конфигурационный файл /etc/nginx/nginx.conf и внесем туда настройки двух виртуальных хостов.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
user  nginx;
worker_processes  1;
error_log  /var/log/nginx/error.log;
 
events {
    worker_connections  1024;
}
 
http {
    include       mime.types;
    default_type  application/octet-stream;
    sendfile        on;
    tcp_nopush     on;
    keepalive_timeout  65;
 
     server {
	listen      80;
	server_name  localhost;
        charset utf-8;
 
        access_log  /var/log/nginx/host.access.log;
 
        location / {
            root   /srv/www/htdocs/;
            index  index.html index.htm;
        }
 
        #error_page  404              /404.html;
 
        # redirect server error pages to the static page /50x.html
        #
        error_page   500 502 503 504  /50x.html;
        location = /50x.html {
            root   /srv/www/htdocs/;
        }
    }
 
    # another virtual host using mix of IP-, name-, and port-based configuration  
    server {
        listen       nginx.test:80;
        server_name  nginx.test;
        charset utf-8;
 
        location / {
            root   /home/izumeroot/sites/nginx.test/;
            index  index.html index.htm index.php;
        }
 
	location ~ \.php$ {
            fastcgi_pass   127.0.0.1:1026;
            fastcgi_index  index.php;
            fastcgi_param  SCRIPT_FILENAME  /home/izumeroot/sites/nginx.test$fastcgi_script_name;
            include        fastcgi_params;
        }
    }
 
    server {
        listen       nginx2.test:80;
        server_name  nginx2.test;
        charset utf-8;
 
        location / {
            root   /home/izumeroot/sites/nginx2.test/;
            index  index.html index.htm index.php;
        }
 
	location ~ \.php$ {
            fastcgi_pass   127.0.0.1:1026;
            fastcgi_index  index.php;
 
 
            fastcgi_param  SCRIPT_FILENAME  /home/izumeroot/sites/nginx2.test$fastcgi_script_name;
            include        fastcgi_params;
        }
    }
}

В строке fastcgi_pass 127.0.0.1:1026 прописан тот самый порт, о котором говорилось выше. Секции server содержат настройки виртуальных хостов. Первая для дефолтного, а вторые две для nginx.test и nginx2.test с файлами, которые находятся в /home/izumeroot/sites/nginx.test/ и /home/izumeroot/sites/nginx2.test/. Только для локальной машины надо прописать эти доменные имена также и в /etc/hosts.
Nginx имеет еще массу настроек, о которых можно прочитать на официальном сайте.
А теперь об автозапуске служб. Для их автозапуска нам необходимо создать символические ссылки в определенных каталогах. В openSUSE, правда, есть GUI для этого.

ln -s /etc/init.d/nginx /etc/init,d/rc3.d/S13nginx
ln -s /etc/init.d/spawn-php-demon /etc/init,d/rc3.d/S12spawnphp

Вот и все. Теперь можно поместить в папки /home/izumeroot/sites/nginx.test/ и /home/izumeroot/sites/nginx2.test/ тестовые php-скрипты с любимыми Hello World и phpinfo() и вызывать в браузере nginx.test и nginx2.test. У меня на nginx2.test локально прекрасно работает WordPress!
Жду информации о ваших успехах. На этом мы НЕ заканчиваем разговор о Nginx. Так что, если не хотите пропустить очередную статью, подпишитесь на новые сообщения блога.

Tags: ,

5 Responses to “Запускаем Php-сайт под Nginx”

  1.  Игорь Тельменко Says:

    Теперь и данный сайт работает на Nginx. Вчера настроил его на своем VDS. Может быть для каких-то экспериментов время от времени буду использовать Apache. Сейчас тестирую все функции своего блога. Если кто-нибудь заметит проблему - пишите.
    Спасибо!

  2.  debian-world Says:

    Пример запуска php + nginx под Debian: Настройка nginx с поддержкой PHP

  3.  lion Says:

    Я настроил связку NGinx как Фронтенд для Apache2, стало всё летать … но SMF 2.0 не может получить адрес с которого зашли, слышал что SMF работает на NGinx - хочу попробовать запустить часть сайтов под NGINX а часть под Apache2->NGinx

  4.  Manager Says:

    lion: Ну и как SMF без апачи на NGinx работает?
    У меня к SMF еще движок блогов и википедия прикручена, стоит ли ставить просто NGinx или все же лучше в связке с Apache?
    Вопрос актуальный, очень жду ответа в ближайшее время

  5.  lion Says:

    Всё работает, доказательство на 1clinux.org там же описание как я это делал:
    https://1clinux.org/index.php?topic=532.0