Пятница, 26.04.2024, 03:06
Приветствую Вас Гость | RSS
Мой сайт
Главная
Регистрация
Вход
Форма входа

Меню сайта

Категории раздела
Об ОС Windows [137]
В категории размещаются статьи, касающщиеся операционных систем от Microsoft.
Об ОС *Nix [198]
В данной категории собраны статьи об ОС семейства Unix/Linux/FreeBSD/...
Справочные материалы [351]
Справка по всему разделу.
Виртуализация и Облака [46]
Networks & Routing [86]
DataBases [22]

Наш опрос
Оцените мой сайт
Всего ответов: 209

Статистика

Онлайн всего: 1
Гостей: 1
Пользователей: 0

Главная » Статьи » Системное администрирование » Об ОС *Nix

Nginx + php-fpm на CentOS 5.3

Nginx + php-fpm на CentOS 5.3

В этой статье я поделюсь собственным опытом построения веб-сервера, работающего на CentOS 5.3.

Что требовалось:
  • Полностью избавиться от Apache. Сервер должен был выдерживать хорошую нагрузку, распределяя статику и динамику.
  • Нужна была поддержка последней версии libxml, малейшее различие в версиях делало сайт абсолютно нерабочим.
  • Нужен был gzip
  • И еще некоторые особенности, о которых я расскажу в самой статье

Предыстория

В качестве «полигона для испытаний» у меня был в наличии физический сервер, на борту которого стояли 2 процессора Xeon и 2 Гб оперативной памяти. Более точный конфиг привести не могу — не помню, да и особо не волновало.

Для работы сайта требовался php ветки 5.2.х. Когда я устанавливал из стандартного репозитория, я столкнулся с такой проблемой, как libxml. По умолчанию он ставился с версией 2.6.24, что делало проект абсолютно нерабочим (требовалась версия 2.6.32). Даже с подключенным репозиторием CentALT проблема не решалась.

Вероятно, можно было пересобрать готовый пакет и установить уже его, но у меня нет в этом никакого опыта, поэтому php я решил собирать вручную.

Правильно собрать php с первого раза мне, разумеется, не удалось :). Проект требовал учета небольшого количества тонкостей. В частности, это поддержка pdo и freetype.

Изначально я решил сделать все на основе связки nginx+apache, процесс установки и настройки ничем не отличался от того, как написано в этой статье. Да и сам процесс мне казался проще, чем настройка работы с php-cgi.

Все работало прекрасно, но я решил не останавливаться на этом, тем более сервер нужно было оптимизировать. Тут и пришла задумка убрать полностью apache, взвесив все это на nginx и php-cgi.

Сборка PHP

Нужно было еще чем-то управлять самим процессами FastCGI, я решил использовать php-fpm — PHP FastCGI Process Manager — это патч для PHP, позволяющий более эффективно управлять процессами FastCGI для обеспечения высокой стабильности работы. Почему именно он? Показался прост в настройке и вообще по отзывам неплох.

Сказано — сделано, тянем последнюю версию с http://php-fpm.org/downloads/. На тот момент у меня стоял php версии 5.2.10, поэтому я тянул php-5.2.10-fpm-0.5.13.diff.gz. Казалось бы, далее все просто. Стягиваем, и делаем все в точности как указано в вики самого проекта. Кратко приведу что нужно было сделать:

$ bzip2 -cd php-5.2.10.tar.bz2 | tar xf -
$ 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


Как видите, ничего хитрого. Далее — я собирал php. Процесс сборки шел с учетом тех тонкостей, которые мне были необходимы:

./configure --enable-fastcgi --enable-fpm --with-zlib --enable-pdo --with-pdo-mysql --with-mysql --with-config-file-path=/etc --enable-calendar --with-iconv --enable-exif --enable-ftp --enable-wddx --with-zlib --with-bz2 --with-gettext --with-xmlrpc --with-xml --enable-soap --enable-filepro --enable-bcmath --enable-trans-sid --enable-mbstring --enable-dbx --enable-dba --with-openssl --with-mhash --with-mcrypt --with-xsl --with-curl --with-pcre-regex --with-gd --enable-gd-native-ttf --with-ldap --enable-pdo --with-pdo-mysql --with-mysql --with-sqlite --with-pdo-sqlite --enable-sqlite-utf8 --with-pear --with-freetype-dir=/usr --with-jpeg-dir=/usr

Болдом помечены обязательные параметры, которые необходимы для работы php-fpm. --with-config-file-path=/etc — решил четко указать где держать php-ini.
Ну, и затем:
make install all
Нужно еще отредактировать файл /etc/php-fpm.conf. В частности, я редактировал:

Pid file 
<value name="pid_file">/var/run/php-fpm.pid</value>
Error log file
<value name="error_log">/var/log/php-fpm.log</value>
В первом случае мы задаем где будет лежать pid-файла процесса, во втором куда писать логи.

<value name="listen_address">127.0.0.1:9000</value>
Адрес и порт где будет слушать php. Это мы и будем использовать при кофигурировании nginx. Либо, тут указывается путь к сокету — например:
<value name="listen_address">/tmp/php-fpm.sock</value>

И необходимо задать от чьего имени запускать сам процесс:
<code>Unix user of processes 
<value name="user"></value>
Unix group of processes
<value name="group"></value>

Это уже на ваше усмотрение, главное, чтобы права были соответствующие.
Можно еще покопать конфиг, каждая строчка снабжена комментарием, разобраться несложно.

Nginx

Как я уже говорил выше, установка и установка nginx практически не отличается от того, что написано в статье, ссылку на которую я указал выше. Единственный момент — мы не используем проксирование, так как apache у нас нет, соответственно строчки proxy_* не имеют для нас никакого значения. Ну и сама специфика настройки, к примеру worker_connections или worker_processes и т.п. зависит конкретно от ваших нужд. Разумеется, я собирал вручную, потому что и тут нужно было учесть некоторые тонкости. Без них было бы вполне достаточно:

yum install nginx

Приведу пример части конфига из ветки http:
include /etc/nginx/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"'
'"$gzip_ratio"'
'"$got" "$sent_http_set_coockie"';

access_log /var/log/nginx/access.log main;

'"$got" "$sent_http_set_coockie"'; — это мне требуется для логгирования с установленным модулем custom-nginx-session-module (Модуль для определения куки и установки уникальной сессии). О процессе установки и настройки могу рассказать позже, если кому-то будет интересно. А то, что выше — обычное логгирование.

Еще подразумевалось использование виртуальных хостов, поэтому для удобства я решил вынести это в отдельные файлы:
include /etc/nginx/sites-enabled/*;

Приведу пример — файл /etc/nginx/sites-enabled/example.com:
server {
listen 80;
server_name example.com www.example.com;
# Разумеется, мне нужен лог для каждого виртуального хоста
access_log /var/log/examplecom-access.log;
error_log /var/log/example.com-error.log;

# Указываем корень где будет лежать сайт
root /path/to/www;

# Всю статику отдаем nginx
location ~* ^.+\.(jpg|jpeg|gif|png|ico|css|js|bmp)$ {
root /path/to/www;
}

UPD: Замечание от хабраюзера AlexeyK:
строчки не имеют смысла, если у вас один и тот же root, да и вообще nginx отдаст эти файлы так сказать по дефолту, если вы на них handler не повесите :) имеет смысл поставить expires побольше в этот location и возможно настроить размер буферов для отдачи (если статических файлов действительно много)

# Помните прикол с свн? :) На всякий случай учел
location ~ /.svn/ {
deny all;
}

# Переписывание всех запросов к несуществующему документу на index.php,
if (!-e $request_filename) {
rewrite ^.*$ /index.php last;
}

# Передача файлов, имена которых заканчиваются на .php на интерфейс fastCGI (php-fpm)
location ~ \.php$ {

# Адрес и порт, который мы указали в конфиге php-fpm.conf
fastcgi_pass 127.0.0.1:9000;
fastcgi_index index.php;
fastcgi_param script_FILENAME /path/to/www$fastcgi_script_name;
include fastcgi_params;
}
}

UPD: Или, как подсказал хабраюзер darivush:

fastcgi_pass 127.0.0.1:9000; заменить на fastcgi_pass unix:/tmp/fastcgi_sock;, так как юникс сокеты предпочительнее 127.0.0.1. Ну, и соответственно путь /tmp/fastcgi_sock должен быть правильным, конфигурится в /etc/php-fpm.conf в разделе
<value name="listen_address">


Разумеется, это пример стандартного минимального конфига, все остальное вписывается\убирается\редактируется в зависимости от поставленных задач.

Вроде ничего не забыл. Запускаем php-fpm и nginx:
/etc/init.d/php-fpm start
/etc/init.d/nginx start


И тут я столкнулся с проблемой — php у меня не пропатчился как нужно, в итоге php-fpm напрочь отказывался запускаться, ругаясь на неверный параметр при запуске php-cgi. Решение этой проблемы я так и не смог найти на тот момент. Все решилось некоторое время спустя, когда вышла версия php 5.2.11, которую я пропатчил тем же патчем, сконфигурировал и установил так, как описано выше. После чего все запустилось и заработало без проблем.

Так как мне нужно было собирать php вручную (из-за всех тонкостей, о которых я писал выше), то я не пытался решать задачу установкой всего необходимого из стандартных репозиториев. Возможно, это работает и процесс установки становится проще.

Спасибо за внимание. Статью разместил у себя в блоге, потому что ни в коем случае я не претендую на изобретение велосипеда в плане поставленной задачи. Это больше вспомогательный мануал для меня, который может понадобиться в случае необходимости. Ну, и ее окажется вполне достаточно для новичков. Но, если статья покажется вам полезной, с удовольствием перенесу это в блог nginx. В планах — рассказать о настройке custom-nginx-session-module (я позже расскажу зачем он мне нужен), а так же memcached, и pinba.

И да, пожелания, замечания и ценные советы приветствуются.

UPD: перенесено в nginx.

комментарии (22)

  • # Указываем корень где будет лежать сайт
    root /path/to/www;

    # Всю статику отдаем nginx
    location ~* ^.+\.(jpg|jpeg|gif|png|ico|css|js|bmp)$ {
    root /path/to/www;
    }

    строчки не имеют смысла, если у вас один и тот же root, да и вообще nginx отдаст эти файлы так сказать по дефолту, если вы на них handler не повесите :) имеет смысл поставить expires побольше в этот location и возможно настроить размер буферов для отдачи (если статических файлов действительно много)
    • Спасибо, добавил в топик.
    • А, и да, конфиг брал очасти свой, а на проекте как-раз таки и есть хендлер, поэтому пришлось уточнять.
      • * отчасти
      • могу еще одну вещь неявную сказать, если соберешься ставить expires на статические файлы, то лучше убрать оттуда js/css, либо придется прописывать в проекте включение их следующим образом:

        и при изменении lib.js менять версию, чтобы браузеры перечитывали содержимое

        это из собственных наблюдений :)
        • html tag схавало :(

          script type=«text/javascript» src=«js/lib.js?1.0»

          вот так
    • А можно узнать, причем тут размеры буферов для отдачи? Я вот, всю жизнь, считал, что лучше отдавать через sendfile.
  • Перенесите лучше в «серверную оптимизацию» :)
    • Думаете? Мне кажется, это больше затрагивает настройку nginx. Выслушаю все мнения, спасибо :)
  • Эээх, опять сборка из исходников, вместо нормальных srpm/deb-src и прочих…
    • Да я бы и сам рад был собрать из готовых пакетов — думаю, процесс намного бы упростился, но, как я упомянул выше, мне это не подходило. Я думаю остальным ничего не мешает все поставить из репозиториев, а настройка ничем не отличается.
    • из личных наблюдений — проще скомпилить и выставить свои опции, чем искать какие есть в пакете, а потом если не хватает — пересобирать пакет, да и бывает, что забываешь что-то включить, поставить тот же статус для графиков или с дебагом собрать в особо тяжелых случаях
      • И в этом вы правы :)
      • Ну дык, собери свой пакет? В чем проблема-то?
  • location ~ \.php$ {
    fastcgi_pass 127.0.0.1:9000;
    }

    лучше

    location ~ \.php$ {
    fastcgi_pass unix:/tmp/fastcgi_sock;
    }
    и в пхп соответственно поправить.
    • А почему, кстати?
      • Обращения к сокету проходят быстрее обращений по tcp, даже на локальный хост.
        • А вы имеете тесты или это только мысли?
          • Конечно тесты, даже вот фрагмент объяснения из рассылки FreeBSD (если вы по логике вещей не можете или не хотите понимать, что установление соединения по tcp протоколу, который, кстати, с проверками, занимает больше времени, нежели работа с локальным сокетом).

            UNIX domain sockets have explicit knowledge that they're executing on
            the same system. They avoid the extra context switch through the
            netisr, and a sending thread will write the stream or datagrams directly
            into the receiving socket buffer. No checksums are calculated, no
            headers are inserted, no routing is performed, etc.

            IP sockets over localhost are basically looped back network on-the-wire
            IP. There is intentionally «no special knowledge» of the fact that the
            connection is to the same system, so no effort is made to bypass the
            normal IP stack mechanisms for performance reasons. For example,
            transmission over TCP will always involve two context switches to get to
            the remote socket, as you have to switch through the netisr, which
            occurs following the «loopback» of the packet through the synthetic
            loopback interface.

            Полное объяснение здесь: lists.freebsd.org/pipermail/freebsd-performance/2005-February/001143.html
  • Внезапно: www.forum.searchengines.ru/showthread.php?t=403787
  • if (!-e $request_filename) {
    rewrite ^.*$ /index.php last;
    }


    Очень плохо. Идите читайте про try_files.


Источник: http://habrahabr.ru/blogs/nginx/71062/
Категория: Об ОС *Nix | Добавил: admin (18.12.2010)
Просмотров: 2403 | Теги: PHP, nginx, php-fcgi, ceontos, php-fpm | Рейтинг: 0.0/0
Всего комментариев: 0
Имя *:
Email *:
Код *:
Поиск

Друзья сайта
  • Официальный блог
  • Сообщество uCoz
  • FAQ по системе
  • Инструкции для uCoz


  • Copyright MyCorp © 2024