UMGUM.COM (лучше) 

Zabbix + Nginx + PHP + FastCGI ( Оптимизируем работу "web"-интерфейса системы мониторинга. )

2 октября 2010  (обновлено 2 ноября 2014)

OS: Linux Debian Lenny/Squeeze.
Application: Zabbix Server, Nginx, PHP, FastCGI.

Zabbix - прекрасная комплексная система мониторинга, удивляюсь тому, как разработчики умудряются проработать массу взаимосвязей таким образом, что они отлично работают. Вот только интерфейс явно притормаживает даже на самых что ни на есть мощных серверах. "Web"-сервер, предлагаемый разработчиками по умолчанию - Apache, весьма монструозный для достаточно простой задачи, как отрисовка графиков на выделенной физической машине. Нужно что-то пошустрее и полегче. Я остановился на Nginx.

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


Для начала установим PHP с поддержкой технологии FastCGI и запустим его на каком-нибудь TCP локального интерфейса. Получится своего рода PHP FastCGI сервер. После на этот сервер будем переправлять запросы из Nginx.

# aptitude install php5 php5-cgi php5-gd php5-pgsql psmisc

После установки PHP необходимо несколько изменить файл его настройки, адаптируя интерпретатор к условиям эксплуатации в "Linux Debian Lenny/Squeeze" (требуется обеспечить поддержку правильных трансляций "PATH_INFO/PATH_TRANSLATED" в FastCGI) и требованиям Zabbix. Для этого необходимо отредактировать файл "/etc/php5/cgi/php.ini" таким образом, чтобы ряд переменных приняли следующие значения:

....
cgi.fix_pathinfo = 1
....
date.timezone = Country/Town
memory_limit = 256M
post_max_size = 32M
upload_max_filesize = 16M
max_execution_time = 600
max_input_time = 600
....

Значение параметра "date.timezone" берем из системного файла"/etc/timezone".

Теперь можно попробовать запустить PHP-CGI:

# /usr/bin/php-cgi

Если не наблюдается никаких ошибок, то вероятнее всего интерпретатор работает корреткно. Прерываем его работу нажатием комбинации "Ctrl+C", чтобы завершить процесс.

Есть, как минимум, два варианта запуска автономного FastCGI сервера:

Запуск встроенного в интерпретатор PHP сервера FastCGI - метод, не требующий никаких дополнительных утилит;
Запуск PHP внутри какого-либо стороннего обработчика запросов - этот вариант может быть более удобным из-за большей гибкости в настройке.

С учётом того, что я, по возможности, всегда стараюсь не использовать избыточного программного обеспечения - остановимся на запуске встроенного в PHP FastCGI сервера.

Будет проще управлять нашим PHP FastCGI сервером, сославшись на него особенным именем, используемым только в одной схеме:

# ln -s /usr/bin/php-cgi /usr/local/bin/php-cgi-zabbix

Добавим в систему пользователя, от имени которого будем запускать сервер FastCGI:

# groupadd php-fcgi-zabbix
# useradd --home-dir /var/lib/php-fcgi-zabbix --shell /bin/false --gid php-fcgi-zabbix php-fcgi-zabbix

Создадим ему место жительства:

# mkdir -p /var/lib/php-fcgi-zabbix
# chown -R php-fcgi-zabbix:php-fcgi-zabbix /var/lib/php-fcgi-zabbix

Пишем простенький скрипт запуска FastCGI PHP сервера:

# touch /usr/local/bin/php-fcgi-zabbix
# chmod ugo+x /usr/local/bin/php-fcgi-zabbix

#!/bin/bash

# Путь к исполняемому файлу PHP запускаемому как FastCGI сервер
PHPFCGI="/usr/local/bin/php-cgi-zabbix"

# Прослушиваемый CGI сервером адрес
FCGIADDR="127.0.0.1"

# Прослушиваемый CGI сервером порт
FCGIPORT="8888"

# Пользователь, от имени которого мы запускаем CGI сервер
USER="php-fcgi-zabbix"

# Указываем в переменной окружения количество дочерних потоков, запускаемых для обработки запросов
export PHP_FCGI_CHILDREN=8

# Указываем максимальное количество запросов для обработки процессом CGI сервера
export PHP_FCGI_MAX_REQUESTS=1000

/bin/su --preserve-environment --login "${USER}" --command "${PHPFCGI} -b ${FCGIADDR}:${FCGIPORT}" &

exit 0

После запуска скрипта можно наблюдать в списке процессов подтверждение того, что PHP FastCGI сервер успешно запущен:

# ps axu --forest | grep php-cgi

php-fcgi .... S  /bin/su --preserve-environment --login php-fcgi --command /usr/local/bin/php-cgi-zabbix -b 127.0.0.1:8888
php-fcgi .... Ss  \_ /usr/local/bin/php-cgi-zabbix -b 127.0.0.1:8888
php-fcgi .... S       \_ /usr/local/bin/php-cgi-zabbix -b 127.0.0.1:8888
php-fcgi .... S       \_ /usr/local/bin/php-cgi-zabbix -b 127.0.0.1:8888
....

Пишем скрипт автоматического запуска и перезапуска нашего FastCGI сервера:

# touch /etc/init.d/php-fcgi-zabbix-init
# chmod ugo+x /etc/init.d/php-fcgi-zabbix-init

#!/bin/bash

### BEGIN INIT INFO
# Provides:          php-fcgi-zabbix-init
# Required-Start:    $local_fs $network
# Required-Stop:     $local_fs
# Default-Start:     S
# Default-Stop:      0 6
# Short-Description: Start PHP FastCGI daemon for Zabbix
### END INIT INFO

EXEC="php-cgi-zabbix"
WRAPPER="/usr/local/bin/php-fcgi-zabbix"

case "$1" in
  start)
    echo "Initializing PHP-FCGI processes ..."
    ${WRAPPER}
  ;;
  stop)
    echo "Terminating PHP-FCGI processes ..."
    killall ${EXEC}
  ;;
  restart)
    $0 stop
    sleep 3
    $0 start
  ;;
  *)
    echo "Usage: $0 {start|stop|restart}"
    exit 1
  ;;
esac

exit 0

Прописываем наш скрипт для всех уровней исполнения в системе:

# update-rc.d php-fcgi-zabbix-init start 10 2 3 4 5 . stop 10 0 1 6 .

Управление элементарно:

# /etc/init.d/php-fcgi-zabbix-init {start|stop|restart}

Теперь инсталлируем Nginx:

# aptitude install nginx

Общая конфигурация Nginx находится в файле "/etc/nginx/nginx.conf", конфигурации хостов и сайтов описываются в файлах, располагающихся в директориях "/etc/nginx/conf.d." и "/etc/nginx/sites-enabled.", подключаемых с помощью директив "include /etc/nginx/conf.d/*.conf;" и "include /etc/nginx/sites-enabled/*;".

Приведём общий конфигурационный файл "/etc/nginx/nginx.conf" к следующему виду:

# Указываем пользователя и группу, от чьего имени запускается Nginx
user www-data www-data;

# Количество запускаемых рабочих процессов приравняем к количеству процессорных ядер на нашем сервере
worker_processes    4;

# Указываем месторасположение журнального файла сообщений об ошибках
error_log  /var/log/nginx/error.log;
pid        /var/run/nginx.pid;

events {
    worker_connections  1024;
}

http {
    # Подключаем описание типов файлов
    include             /etc/nginx/mime.types;
    default_type        application/octet-stream;

    # Месторасположение журнального файла событий доступа
    access_log  /var/log/nginx/access.log;

    sendfile            on;
    keepalive_timeout   65;
    tcp_nodelay         on;

    # Запрещаем сообщать версию Nginx в ответе клиенту
    server_tokens       off;

    # Подключаем файлы описания дополнительных конфигураций
    include /etc/nginx/conf.d/*.conf;
    include /etc/nginx/sites-enabled/*;
}

Создаем файл конфигурации виртуального хоста "zabbix.local":

# touch /etc/nginx/sites-available/zabbix.local

Приводим его к следующему виду:

server {
    listen      *:80;
    server_name zabbix.local;

    # Указываем кодировку отдаваемых страниц
    charset     utf-8;

    root        /var/www/zabbix.local;
    index       index.php;

    # Запрещаем отдавать кому бы то ни было файлы .htaccess и .htpasswd
    location ~* /\.ht {
        deny  all;
    }

    # Ограничиваем доступ к ряду директорий в соответствии с рекомендациями разработчиков Zabbix
    location ~* /(api|conf|include)/ {
        rewrite ^/(.*)$ http://zabbix.local/index.php permanent;
    }

    # Секция описания перенаправления PHP скриптов на исполнение CGI серверу
    location ~ \.php$ {
        include         /etc/nginx/fastcgi_params;
        fastcgi_param   SCRIPT_FILENAME /var/www/zabbix.local$fastcgi_script_name;
        fastcgi_param   QUERY_STRING    $query_string;
        fastcgi_pass    127.0.0.1:8888;
        # Указываем Nginx передавать ответы FastCGI-сервера с кодом больше или равными "400" директивам "error_page" для дальнейшей отработки
        fastcgi_intercept_errors on;
        # Описываем реакцию на ошибочные ситуации
        error_page      403 404 502 503 504  http://zabbix.local/index.php;
    }

}

Указываем символической ссылкой Nginx на доступную конфигурацию виртуального хоста:

# ln -s /etc/nginx/sites-available/zabbix.local /etc/nginx/sites-enabled/zabbix.local

Удаляем ссылку на конфигурацию виртуально хоста "по умолчанию":

# rm /etc/nginx/sites-enabled/default

Перезапускаем Nginx:

# /etc/init.d/nginx restart

По завершению конфигурирования Nginx закрываем от постороннего взгляда директорию конфигурации:

# chown -R root:root /etc/nginx
# chmod -R o-rwx /etc/nginx

Теперь доля "web"-сервера в потреблении ресурсов существенно уменьшилась. Если раньше в "топе" процессов с максимальным потреблением ресурсов процессора и оперативной памяти Apache присутствовал постоянно, но теперь там "прописался" PHP, который ранее занимал вторые места. Nginx же вообще находится в списке за нижней части экрана.


Заметки и комментарии к публикации:


Оставьте свой комментарий ( выразите мнение относительно публикации, поделитесь дополнительными сведениями или укажите на ошибку )