Comments 66
Сейчас это тестовый сервер, в перспективе, если не найду глюков в работе движков и устроит производительность на него переедет около 20 сайтов, все проекты одной компании, движки разные, в том числе на самописных cms (из-за них пока окончательно не переехал, тестирую все опции).
Чтоб все и сразу я не нашел, вот мне понадобилась одновременная работа php и perl скриптов в рамках одного сайта, во всех туториалах, что попались либо то, либо другое. С phpmyadmin была отдельная песня. Это скорее заметка себе на будущее ну и может еще кому пригодится.
Заметка себе на будущее делается в evernote, а не в коллективном блоге.
Если больше никому статья будет не интересна — уберу в черновики, пусть хабраюзеры решат нужна она тут или нет.
У меня для подобных целей есть собственный блог, куда я записываю подобные штуки, дабы что-то не забыть. Кому надо — тот найдет. Хабр для более сложных и интересных вещей.
Буду рад прочесть ваши сложные и интересные статьи. Основной минус собственного блога, если конечно он не раскручен — возможность получения обратной связи. Может я вообще бред написал и в своем блоге об этом даже не узнаю.
Про бред никто не говорил — было сказано, что подобное уже публиковалось.
А если пишете интересный и полезный материал — фидбек гарантирован везде.
# Директива уменьшает разрешение времени в рабочих процессах, за счёт чего уменьшается число системных вызовов gettimeofday().
timer_resolution 100ms;

Нет особого смысла, во всех современных ядрах/дистрибутивах gettimeofday работает не через системный вызов.

#Организовываем кеш для FastCGI сервера, я использую раздел в ram
fastcgi_cache_path /tmp/fcgi-cache/ levels=1:2 keys_zone=one:10m;

10 мегабайт всего? Думаю, для продакшена надо будет увеличить :) Кстати, у вас сейчас в access.log записывается HIT/MISS?

#Расширяем буфера отдачи
output_buffers 32 512k;

Зачем? Много лишней памяти?

#Если не использовать эту опцию — то в форумах все будут сидеть под именем первого вошедшего на форум
fastcgi_hide_header «Set-Cookie»;
#Этот запрос заставит nginx кешировать все что проходит через него
fastcgi_ignore_headers «Cache-Control» «Expires»;

Очень странное сочетание. Сначала заставляете нгинкс кешировать страницы авторизации, которые куки выставляют, а потом тупо запрещаете установку кук. Пользователи не устанут каждый раз логиниться при заходе на сайт?
gettimeofday — убрал.
10 — поставил пока для тестов работы кеша, потом конечно расширю, нет не записываются, включу, как поборю некоторые особенности одной из CMS, тогда полностью займусь тестированием именно кеширования.
output_buffers 32 512k; — советуете уменьшить или не трогать?
По поводу странного сочетания, а как лучше сделать?
output_buffers 32 512k; — почему 32 для начала?

К тому же — обычно output_buffers используется для отдачи больших файлов.
Советую убрать output_buffers и fastcgi_hide_header вместе с fastcgi_ignore_headers, потом попробовать.
Скорее всего для правильного кеширования надо будет попилить csm-ки.
Статью оставьте, но rocket-sience тут и вправду нет.

> worker_rlimit_nofile
ulimit поднимать не забывайте для www-data.
Если я правильно понял имелось в виду
su - www-data
$ ulimit -a
time(seconds)        unlimited
file(blocks)         unlimited
data(kbytes)         unlimited
stack(kbytes)        8192
coredump(blocks)     0
memory(kbytes)       unlimited
locked memory(kbytes) 64
process              unlimited
nofiles              32000
vmemory(kbytes)      unlimited
locks                unlimited
Хм. А чего за ведро и procfs? Раньше ж оно open files звалось. Да и в stable до сих пор именно так.
Да давненько уже не так.
cat /proc/version
Linux version 3.2.0-0.bpo.3-686-pae (Debian 3.2.23-1~bpo60+2) (debian-kernel@lists.debian.org) (gcc version 4.4.5 (Debian 4.4.5-8) ) #1 SMP Thu Aug 23 08:21:41 UTC 2012

Вот с другого сервера со стейблом
su - www-data
$ ulimit -n
1024
$ ulimit -a
time(seconds)        unlimited
file(blocks)         unlimited
data(kbytes)         unlimited
stack(kbytes)        8192
coredump(blocks)     0
memory(kbytes)       unlimited
locked memory(kbytes) 64
process              unlimited
nofiles              1024
vmemory(kbytes)      unlimited
locks                unlimited
$ cat /proc/version
Linux version 2.6.32-5-amd64 (Debian 2.6.32-45) (dannf@debian.org) (gcc version 4.3.5 (Debian 4.3.5-4) ) #1 SMP Sun May 6 04:00:17 UTC 2012
Ох уж эти девелоперы ядра) Без объявления войны меняют)

Но вообще речь была о том, что у вас в статье про это не упомянуто. А nginx не всегда поднимает их сам, лучше сразу в security.conf писать.
Сокеты не всегда хороши (на linux`ах):

* http://forum.nginx.org/read.php?3,97959,99123#msg-99123
* www.saltwaterc.eu/nginx-php-fpm-for-high-loaded-websites.html

Поэтому гуглим, что такое net.core.somaxconn и почему по дефолту мы будем иметь только 128 конкурентных коннектов. А особенно если мы юзаем только один дефолтный пул, то 502 будет частой гостьей.

Также в php-fpm желательно добавить защиту от криворучия сторонних модулей: pm.max_requests (чтобы «перезагружаться» после стольки-то реквестов) & rlimit_files (лимиты на открытые файлы).
@sее github.com/garex/puppet-module-nginx/commit/700cee70841b9781be77815aa38f4560c34041f7
За ссылку на багтреккер спасибо, nginx сам только осваиваю, тонкостей многих еще не знаю, информация очень полезна. Веб сервера далеко не самое приоритетное направление деятельности и не самое нагруженное, занимаюсь потихоньку когда есть время, вот выкроил время — решил разобраться с nginx. Как оптимально подобрать pm.max_requests и rlimit_files — снять статистику за неделю и увеличить максимум процентов на 30%?
cat /proc/sys/net/core/somaxconn
2048

Стандартный тюнинг от DDoS делается на автомате, не стал углубляться в настройки tcp_syncookies, tcp_max_syn_backlog, tcp_synack_retries настройки фаирвола и прочее, все таки тема была немного другая.
Эт пример коммита из одного из модулей для папета.

По поводу оптимальности — надо смотреть есть ли смысл вообще? Напр., если ничего не течёт, то можно и не делать этого.

Я когда настраивал в одном месте, смотрел и видел, что php-fpm понаоткрывал кучу файлов, а закрыть их не судьба. Это можно lsof`ом посмотреть. Проблема была или в нём, или в одном из модулей php`шных. В общем подобная штука помогает просто делать «reset» и всё. Как грится — не работает? Перезагрузите компутер.

Для более грамотных вариантов надо просто вручную всё собирать и ставить/выбирать версии, которые не текут или уже пофикшены.
Да думал все собрать вручную, но меня за прошлую статью запинали, что не из репозиториев ставил, решил на этот раз обойтись только собранными версиями софта. Поставил сервер на мониторинг, посмотрю по графикам как себя вести будет. Как начал разбирать для себ nginx, решил все записывать по горячим следам, по-этому конфиги могут быть где-то не оптимальны. Просто писать все, что настраивалось месяц назад и уже отлажено и работает часто бывает лень, да и не вспомнишь всех нюансов.
Пиналы идут боком — в результате должен быть качественный продукт. А ставить всё так или эдак — на это нам мозг даден.

С т.з. удобства записывания/запоминания папеты/шефы удобны. Т.к. всё можно в одном месте держать и уже видеть по истории что когда и почему делалось.

Можно даже не юзать спец-модулей — а всё в одном главном делать. Потом уже как опыт будет и рука набьется — перейти на модули. Но это опять не золотая птица щастья.
У меня столько серверов нет, чтоб с папетами/чефами заморачиваться, в основном роутингом занимаюсь, с железками все проще, конфиг перекинул — считай клон. Сервера — так побочный продукт в двойном экземпляре каждый только, когда время есть разбираю поглубже, вдруг работу сменить надумаю. Рука набьется как баги вылазить начнут, пока ровно — черт его знает куда копать.
Плюсы этих штук в том, что всё в одном месте + видно что когда менялось + всё не внутри реальной машинки.

Даже для одной машинки.
Все таки для одной машинки мне кажется это оверхед. Для отслеживания изменений есть и другие средства, например для дебиан использую etckeeper, в крайнем случае есть ежедневные бэкапы на бакуле. Не оспариваю плюсы этих штук, но главный минус их должны использовать все в компании. У меня был опыт внедрения шефа, пока на сервере сам еще удается делать рецепты и как-то следить, когда появляется необходимость отдать временно сервер (переключился на другую задачу, обслуживание текущей работоспособности передал в ТП) часть конфигов правится «по-быстрому» руками, часть в рецептах, часть не пойми как, понимаю что это проблема организации, регламента и прочего, но снова наступить на эти грабли пока не готов. Хотя может еще просто не дорос до необходимости «кукловодства».
Данная операция в php-fpm, на наш взгляд, весьма тривиальна:


Скопировать файл, поправить в нём юзеров и порт — нетривиально? Эээ… Ну тогда пишите скрипты или используйте папеты/шефы.

Напр., в модуле папета это можно сделать так:

nginx::backend::php {"Another site":
    port        => 9001,
    try_files   => '$uri $uri/ $uri/index.html /index.php?url=$uri&$args',
    pool_user   => "www-data2",
    pool_group  => "www-data2",
  }


И вручную или через пол-часа новый пул сам там будет.

Да даже просто ручками — что сложного скопировать *.conf и поправить там 3 значения? Можно вообще заранее себе подготовить шаблон *.conf`а с только нужными значениями, который копи-пастить.

Прям катарсис у меня от такого заявления :)
Ну все верно, тривиальна, останавливаться подробней не стал, я все понимаю праздники на носу, но где вы там прочли НЕ?
Упс… Точно праздники на носу. Я — сам себе злобная буратина :)
Можно еще юзать $pool:
user = $pool
group = $pool
Если listen делается через сокет, то тоже прокатит
Зачем на сервер устанавливать phpmyadmin? Для кого? Пользователям сайта и заказчику он не нужен. А разработчик всегда может пробросить туннель и работать с локальным pma.
Безусловно когда это хостинг, но тут собственный сервер, на собственной техплощадке на который тестово периодически ставятся разные движки, смотрятся, настраиваются, удаляются. Банальный пример, захотел один из сотрудников СТП установить движок одной игры, мне проще ему дать доступ к директории по фтп и пользователя в mysql и пусть ковыряет движок свой как хочет. Естественно что доступ не по имени phpmyadmin (дал стандартное для примера) и в правилах разрешен доступ только с внутреннего диапазона адресов, не суть, инструмент удобный, почему не поставить? Случаи разные бывают, мне удобней когда инструмент есть на сервере и я в дороге с планшета могу зайти при необходимости и глянуть что с базой, а не париться с заходом по ssh и наслаждаться печатанием команд в терминале на сенсорной клавиатуре планшетки, поверьте то еще удовольствие.
тестово периодически ставятся разные движки

Вы нигде не написали про тестовый или dev-сервер. Безусловно, это совсем другой разговор, но статьи с хабра, обычно копипастятся один в один, не сильно задумываясь о том, что и зачем они устанавливают на серваке.
Не думал что важна специфика работы фирмы, всегда думал кому нужно — поставит, кому нет — не будет. (Тем более расписал как сделать отдельным шаблоном, чтоб включать только там, где это нужно) Может чтоб еще какие-либо вопросы исключить, мы ISP и вебсервера далеко не самый приоритетный род занятий, сайт свой развернуть, форум, пару движков личных блогов сотрудников, ERP, игровые движки, несколько параллельных тестовых проектов и все. До этого все крутилось на сборке ZendServerCE и вполне успешно вообще без особой доработки, nginx поставил лично для себя чтоб разобраться, пока перед праздниками по основному роду деятельности почти нет нагрузки.
dotdeb? Сразу отказать. Пробовал заюзать их несколько раз, постоянно возникали траблы.
Просто подключаем testing репозиторий дебиана и имеем все, что есть в дотдебе без лишних проблем.

в /etc/apt/sources.list:
deb ftp.debian.org/debian/ testing main non-free contrib
deb-src ftp.debian.org/debian/ testing main non-free contrib
deb security.debian.org/ testing/updates main contrib non-free
deb-src security.debian.org/ testing/updates main contrib non-free
На вкус и цвет, я готов закрыть глаза на нестабильность некоторых элементов при общей стабильности системы, тестинг часто собран со слишком новыми версиями либ и приходится тянуть пол системы. У меня пока проблем с дотдебом небыло, может не нарывался, зато с тестингом было предостаточно, каждое обновление как русская рулетка. Я с дотдеба беру только php и mysql, может что другое неудачно собирают. Если вдруг столкнуть или пересоберу сам или возьму альтернативу (для mysql например percona), а вот если глюк в тестинге, то только на бэкап откатываться.
Оптимальное число обработчиков зависит от ресурсов сервера, сложности php-скриптов, нагрузки, создаваемой на mysql-сервер и т.д. В любом случае оптимальное число обработчиков нужно подбирать на основе тестирования работы сайта. Методика тестирования неплохо описана тут, повторяться не буду.

По ссылке что-то не то.
Все верно, может чуток сумбурно, попробую объяснить подробней.
1) Строим карту сайта в xml (многие движки умеют или сами или с помощью плагинов)
2) С помощью скрипта по ссылке парсим этот xml в файл линков для Siege
Скрипт
#! /bin/sh
sed -r 's/<loc/\n<loc/g; s!</loc>!</loc>\n!g' $1 | sed -r -n '/<loc>.*?<\/loc>/! D; /<loc>.*?<\/loc>/ s!</?loc>!!g; s!\s+!!g; P'

использование
./sitemap2list.sh sitemap.xml > usrl.txt

3) Устанавливаем для php-fpm в качестве максимального числа обработчиков (параметр pm.max_children) заведомо большое значение (30 например)
4) Производим набор тестов следующего вида:
siege -i -b -t 1m -с <num> -f urls.txt

При каждом новом тесте мы будем увеличивать от 1 и далее с шагом 1. По достижении определённого значения число обработанных запросов в секунду начнёт уменьшаться, значит нам нужно выбрать значении предыдущего тестирования в качестве максимального числа обработчиков.
Мне кажется, что perl надо отделить и поставить для него фронтендом, например, lighthttpd. Нет времени объяснять, всех с наступающим! Ну а если серьезно, будет проще потом разобраться с ошибками, языки разные, задачи, которые они решают — разные и по-разному. Для легких и простых штук, можно вообще попробовать embedded perl.
Было бы неплохо еще подкрутить sysctl на предмет TIME_WAIT — reuse, recycle.
Тут тоже не nginx перлом занимается, а fcgiwrap, не нравится он — отдайте в любой другой, некоторые вообще советуют весь апач притянуть, вариантов много. Еще не понял зачем делать фронтенд для nginx, может как-раз бэкенд?
Хорошо бы еще раскрыть тему open_basedir, иначе любой поломанный сайт открывает буквально все остальные сразу, да и в целом очень много позволяет видеть. Что с этим делать?
Пока из вариантов нашел только на каждого юзера (юзер=домен) поднимать отдельно fastcgi от имени юзера и рулить уже на уровне прав файловой системы, но думаю такой вариант кушать ресурсов будет не слабо. Видел еще решение подправить php.ini так:
[HOST=hostname]
 open_basedir = somedir

, но как себя поведет на реальных движках можно только гадать.
Если кто знает правильный ответ, будет очень полезно услышать.
Как вы сказали, у вас 20 проектов. Нагрузка и правда будет не слабой, если поднимать отдельно fastcgi от имени юзера на каждый проект. Тогда вообще все преимущество в сравнении с apach потеряется. Да и рулить этим будет сложно.

Что с этим делать я пока тоже не разобрался. Поэтому мне больше нравится связка apache + nginx. В этом случае каждый сайт работает под своим юзером и все хорошо.
Ну это классика энжиникс на фронтенд, апач на бэкенд. Если руки дойдут, подыму 3 одинаковых идентичных виртуалки на одной сделаю апач от ZendServer, на второй nginx+php-fpm с отдельными пулами на критичные проекты, на третьем nginx+apache залью наши движки и прогоню ряд нагрузочных тестов. Сейчас тестовый сервер в разы слабее боевого и сложно сказать, что будет быстрее. Рулить врядли будет сложно, не руками же каждый раз делать, разок скрипт набросать и все. Тут я боюсь серебряной пули не будет, как и везде, сильно будет зависеть от конкретных движков на чем будет лучше.
У меня каждый проект на php имеет свой отдельный pool, но работают они из под одного пользователя.
Это и позволяет устанавливать разные настройки на отдельные сайты.

Файл пула при это выглядит минималистично:

[example.com]
include=/etc/php-fpm.d/default


В default содержится единый для всех код. Среди прочих его настроек для примера можно выделить следующие:

listen =  /var/run/php-fpm/$pool.socket
slowlog = /var/www/$pool/logs/slow.log
php_admin_value[open_basedir] = /var/www/$pool
php_admin_value[upload_tmp_dir] = /var/www/$pool/tmp


Как мы видим, тут и basedir свой и tmp и логи.
Nginx, при этом, работает с php через сокеты, что, как я надеюсь, исключает вероятность увеличения нагрузки из-за использования разных пулов. Если в этом своём предположении я ошибаюсь, то прошу указать мне на это и устыдить.

Если интересно, то подобный подход с шаблоном, применяю и в настройках nginx.
Файл одного сайта выглядит так:

server {
    set $domain example.com;
    server_name example.com www.example.com;

    include php.conf;
}


В php.conf, естественно, содержаться все общие настройки. Демонстрируют работу с пулом следующие:

fastcgi_pass unix:/var/run/php-fpm/$domain.socket;
access_log  /var/www/$domain/logs/nginx.access.log;
root /var/www/$domain/www;

Хороший подход, интересно было-бы сравнить нагрузку когда 1 пул и много для одинакового количества хостов, если разница не очень большая для меня такое решение будет оптимальным.
Классная статья, спасибо! Есть один вопрос.
В файле /etc/nginx/templates/php параметр
fastcgi_pass unix:/tmp/wwwpool.sock;
этот конфиг подходит, если nginx стоит на той же машине, где и php-fpm. Если php-fpm на другой машине, то нужно писать
fastcgi_pass 10.0.0.1:9000;

А что делать, если используется несколько машин с php через upstream? Можно ли написать так:
upstream backend-php {
server 10.0.0.1:9000;
server 10.0.0.2:9000;
}

fastcgi_pass backend-php;
Вопрос по статье, у вас в конфиге /etc/nginx/nginx.conf
2 раза строка error_log /var/log/nginx/error.log; — так и надо или один раз лишний?
# Рекомендуется устанавливать по числу ядер
worker_processes 4;
pid /var/run/nginx.pid;
worker_rlimit_nofile 8192;
error_log /var/log/nginx/error.log; — тут и:

# Настройка логов
access_log /var/log/nginx/access.log;
error_log /var/log/nginx/error.log; — тут.
##
Большое спасибо автору! Пара мелких ошибок:
«chomod» вместо chmod в двух местах
«sige» вместо siege
Наверное стоило бы написать, что nginx будет подхватывать конфигурацию дефолтового сайта из /etc/nginx/conf.d/default и пока мы его не удалим, он будет перекрывать описанный в статье default. Наши тестовые файлы просто не там будут искаться!
Спасибо подправил, похоже сначала хотел написать chown потом решил первым вписать chmod получился такой гибрид.
Прекрасная статья до сих пор настраиваю многие свои VPS по ней.
Хотелось бы добавить.
Часто мучался, что после рестарта файл /tmp/wwwpool.sock; создается под пользователем root, и соответственно nginx не может его слушать т.к. permission denied.
Часто решал вопрос просто прописывая после рестарта комнаду
chown www-data:www-data /tmp/wwwpool.sock

но это сильно напрягало, т.к. требовало ручками каждый раз так делать.
Короче в /etc/php5/fpm/pool.d/www.conf есть такие строки
listen.owner = www-data
listen.group = www-data
listen.mode = 0660

их надо раскомментить и вопрос решен.
Да давненько это добавили, инструкция писалась еще в 2013 году и тогда эта опция не требовалась, с того времени произошло много изменений и в самом nginx, как добавились разные плюшки, так и подогнаны дефолтные параметры под большинство серверов, что требует меньше лезть в базовый конфиг, если конфигурация близка к стандартной.
Only those users with full accounts are able to leave comments. Log in, please.