Debian.pro

Блог для пользователей и администраторов Debian


Debian, nginx + AMP. Настройка в условиях ограниченных ресурсов.

Сегодня мы поговорим о настройке nginx в связке с apache+mysql+php в условиях ограниченных ресурсов. Мне удавалось запустить эту связку на 128 мегабайтах оперативной памяти, хотя в таких условиях она работала нестабильно. На 192 уже было всё в порядке.

Для начала читаем эти статьи:

Таким образом вы установите apache, mysql, php. Точнее вам необходимо выполнить всё то, что в первой статье. С остальным пока что стоит просто ознакомиться.

Теперь нам необходимо изменить настройки apache для того, чтобы он не занимал 80й порт, на который нам и нужно повесить nginx.
Условимся на том, что из статьи /49 вы всё сделали.
В /etc/apache2/ports.conf меняем:
NameVirtualHost *:80
Listen 80

на
NameVirtualHost *:8181
Listen 8181

Теперь собственно поставим nginx:
debian-nginx:~# aptitude install nginx

Далее открываем /etc/nginx/nginx.conf и приводим его к примерно следующему виду:
user www-data;
worker_processes 1;
error_log /var/log/nginx-error.log;
pid /var/run/nginx.pid;
events {
worker_connections 1024;
use epoll;
}
http {
include /etc/nginx/mime.types;
access_log /var/log/nginx-access.log;
sendfile on;
tcp_nodelay on;
keepalive_timeout 4;
client_max_body_size 100m;
gzip on;
gzip_disable «MSIE [1-6]\.(?!.*SV1)»;
gzip_min_length 1024;
gzip_comp_level 4;
include /etc/nginx/conf.d/*.conf;
include /etc/nginx/sites-enabled/*;
}

Теперь нам необходимо создать запись для VirtualHost в nginx.
Создаём, например, файл /etc/nginx/sites-enabled/example.ru (не используйте в названии этих файлов символ -) и запишем в него следующее:
server {
listen 80;
server_name example.ru www.example.ru test.example.ru;
root /var/www/sites/example.ru;
server_name_in_redirect off;
index index.php index.html index.htm;
access_log /var/www/logs/example.ru/access.log;
error_page 500 502 503 504 /50x.html;
location = /50x.html {
root /var/www/nginx-default;
}
location / {
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header Host $host;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_pass http://127.0.0.1:8181;
}
location ~*
^.+\.(jpg|jpeg|gif|png|rar|txt|tar|wav|bz2|exe|pdf|doc|xls|ppt|bmp|rtf|js|ico|css|zip|tgz|gz)$
{
root /var/www/sites/example.ru;
expires 30d;
access_log off;
}
location ~ /\.ht {
deny all;
}
}

Пробежимся по важным моментам конфига:
server_name example.ru www.example.ru test.example.ru; — перечисляем все домены-алиасы для необходимого нам сайта.
root /var/www/sites/example.ru; — корневой каталог сайта
proxy_pass http://127.0.0.1:8181; — IP и порт апача. В нашем случае связь между apache и nginx будет через локальную петлю.

В дальнейшем вы обязательно столкнетесь с проблемой, что nginx не будет передавать IP адреса Апачу. Собственно, лучше учесть это сейчас, чтобы ваши скрипты на сайтах, работа которых основана на IP посетителя работали правильно. Здесь нам поможет mod_rpaf. Установим его:
Debian-nginx:~# aptitude install libapache2-mod-rpaf

В /etc/apache2/apache2.conf должна появиться строчка:
LoadModule rpaf_module libexec/apache22/mod_rpaf.so
Если она не появилась — допишите её, если закоментирована — раскомментируйте.

В конец конфига (apache2.conf), но ДО того, как описываем виртуальные хосты (а значит и до include sites-enabled/*) вписывам следующее:
RPAFenable On
RPAFsethostname On
RPAFproxy_ips 127.0.0.1
RPAFheader X-Forwarded-For #может не работать, если что — комментируйте эту строку

Теперь собственно то, ради чего мы ставили nginx. Он является реверсным прокси, поэтому необходимость держать много запущенных процессов apache отпадает.
Находим строки:
StartServers 1
MinSpareServers 1
MaxSpareServers 5
MaxClients 10
MaxRequestsPerChild 0

Они находятся в секции IfModule mpm_prefork_module. Значения у вас могут быть разные, в том числе и трёхзначные. Нам этого не нужно, поэтому приводим строчки к виду:
StartServers 1
MinSpareServers 1
MaxSpareServers 4
MaxClients 4
MaxRequestsPerChild 2000

И KeepAlive On меняем на KeepAlive Off Обязательно! Иначе apache будет кушать не положенные ему в наших условиях ресурсы.

Теперь создадим VirtualHost для Apache. Например, я создаю файл /etc/apache2/sites-enabled/example (вот по этой ссылке — пример файла)

Собственно всё. Если вы читали мануал внимательно, то всё должно работать. Перезагрузим оба веб-сервера:
Debian-nginx:~# /etc/init.d/nginx restart && /etc/init.d/apache2 restart

Вы можете встретить такую проблему, что php файлы скачиваются, а не отображаются как страницы. В таком случае вам нужно в /etc/apache2/apache2.conf добавить строку:
AddType application/x-httpd-php .php .php3 .php4 .php5 .phtml
Добавлять, опять же, нужно до строки «Include /etc/apache2/sites-enabled/». Не забудьте перезапустить Apache. Случается редко, но бывает, особенно в Убунте.

Теперь немного цифр, дабы не быть голосовным. Для теста я поставил Drupal и дёргал его через siege. Не забудьте создать нужные каталоги для логов nginx, иначе он не запустится.

При наличии 700 мгц, 192 мб RAM такая конфигурация выдеживает 3.20 страниц в секунду.
Потратив 218 мб памяти и 1500 мгц оно выдавало уже 7-8 страниц в секунду.
При 218 мб памяти и 700 мгц получилось 3 страницы в секунду.

Я сознательно не насиловал эти слабые VDSки. Во время тестов я потихоньку дорабатывал сам сайт, активно использовал админку drupal и прочее. То есть указанные цифры — не предел.

Ну а Atom 270 и 1 GB RAM (~500 мб потраченных) выдали мне далеко за 50 запросов в секунду по локальной сети.
Мои любимые VDSки (KVM, 2660 мгц, 1 GB RAM) выдавали около 30. Главное — правильно подобрать MaxSpareServers и MaxClients.

Таким образом вам понадобится неплохой CPU. Если у вас есть свободная память — увеличивайте значения MaxSpareServers и MaxClients. Если есть ошибки Bad Gateways — также увеличивайте эти значения. Также предпочтительно использовать KVM или выделенный процессор, так как у OpenVZ немного странные представления о работе с процессами — из-за этого теряется достаточно много возможностей связки nginx+AMP.

Какие тут могут быть минусы. У недобросовестных хостерах на VDSках считается VIRT память.192мб у таких вам не хватит даже на то, что бы mysql запустить. У некоторых некорректно настроен OpenVZ — из-за этого mysql при нуле свободной RAM падает. На KVM или выделенных серверах я подобных проблем не встречал.


Комментарии (64):

  1. спасибо большое за мануал!
    на RPAFheader X-Forwarded-For у меня конфиг апача косо посмотрел, благодаря подсказке админа сайта я закомментировал эту строку, и все стало на свои места.

  2. mk93 :

    Благодарю за инструкцию. Есть, однако, одна закавыка: nginx отказывается стартовать с диагностикой «[emerg] open() /usr/local/nginx/on — no such file name or directory». Кто его просит читать этот файл/директорию — неясно.

    Запускал под Oracle VirtualBox с Ubuntu Server 10.10.

  3. создайте /usr/local/nginx и дайте здесь доступ на запись пользователю, от которого nginx работает.

  4. mk93 :

    Спасибо, заработало. А что это за лог такой в /usr/local ? Где о нем читать?

  5. ищите в конфигах)

    вообще там ничего не должно быть, если только дистр у вас или пакет странно собран

  6. mk93 :

    В том-то и дело, что не вижу ничего. Дистр из репозитория. Apt-get install nginx…

  7. grep -rn local /etc/nginx
    покажите

  8. mk93 :

    dps@dps:~$ grep -rn local /etc/nginx/
    /etc/nginx/nginx.conf:31:# # auth_http localhost/auth.php;
    /etc/nginx/nginx.conf:36:# listen localhost:110;
    /etc/nginx/nginx.conf:42:# listen localhost:143;
    /etc/nginx/sites-enabled/default:12: server_name localhost;
    /etc/nginx/sites-enabled/default:14: access_log /var/log/nginx/localhost.access.log;
    /etc/nginx/sites-enabled/default:84:#server_name localhost;
    /etc/nginx/sites-available/default:12: server_name localhost;
    /etc/nginx/sites-available/default:14: access_log /var/log/nginx/localhost.access.log;
    /etc/nginx/sites-available/default:84:#server_name localhost;

  9. странно как то… может в инклудах где прописано…

    что в каталоге вообще понасоздавалось то?

  10. У меня на одном сайте домен с www не пингуется, без www работает нормально. Причем на том же сервере другие сайты с аналогичным конфигом (просто копипаст с заменой домена) работают как надо — идет редирект с www на домен без www. На том же сервере, опять же с аналогичным конфигом на одном сайте домены с www и без работают независимо друг от друга (не происходит редирект). В чем может быть косяк? В DNS запись A для http://www.domen.com есть.

  11. С наступившим. Что именно подразумевается под «не пингуется»? Если он действительно не пингуется по icmp — значит либо А запись указывает чертпоймикуда, либо её нет. Если что-то другое — то так и пишите.
    В-общем, на root@vlad.pro скиньте подробности, если разобраться нужно.

  12. Dmitriy :

    Спасибо за мануалы, помогают разобраться. Но есть вопрос: после настройки по инструкции все сайты вроде бы работают нормально, а установленный раньше phpmyadmin (server_ip/phpmyadmin) — нет. Абсолютно не отображаются изображения… Не подскажите, где может быть проблема? При этом корень сервера доступен нормально.

  13. location /phpmyadmin {
    proxy_set_header X-Real-IP $remote_addr;
    proxy_set_header Host $host;
    proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
    proxy_pass http://127.0.0.1:8181;
    }

  14. Dmitriy :

    Спасибо, так не помогает, я прописывал. Из логов вычитал, что изображения ищут не в server_ip/phpmyadmin, а в имя_вирт_домена/phpmyadmin… Изображения появились, когда убрал

    location ~*
    ^.+\.(jpg|jpeg|gif|png|rar|txt|tar|wav|bz2|exe|pdf|doc|xls|ppt|bmp|rtf|js|ico|css|zip|tgz|gz)$
    { … }

    из nginx конфиге этого домена. Причем домена прикрутил уже два, настройки обоих идентичны полностью (кроме самих имен доменов), через ср.

  15. Прописывать первым location, вестимо.

    Логично, что изображения появились, когда вы убрали раздачи статики nginx’ом — апач знает, где корень /phpmyadmin, nginx — нет. Поэтому nginx и ищет их в root.

  16. Dmitriy :

    Хм… А подскажите, я же этот

    location /phpmyadmin {

    в sites-enabled/default должен прописывать? Если да, то как заставить nginx его первым читать? У меня на каждый домен свой файл в sites-enabled заведен.

  17. Если phpmyadmin нужен на каждом домене — то прописывайте в каждый домен.
    include вам в помощь.

  18. Dmitriy :

    Да нет, phpmyadmin хотел оставить только в корне сервера, а его под htaccess спрятать… Просто такое впечатление, что nginx сначала читает конфиг с домен1, потом default, а потом домен2. Я то конфиги для обих одинаковые сделал, а для нормальной работы phpmyadmin достаточно удалить только один из них… Странно.

    Спасибо большое вам за ответы, буду пробовать копать дальше :)

  19. Он читает конфиги по порядку. Вспоминать какому — в лень. По алфавиту, что ли.
    Чтобы default был default там нужно написать
    listen 80 default;

  20. Dmitriy :

    Спасибо вам, теперь работает, после того, как default приписал)) Надо мне внимательней мануалы впредь читать.

  21. Dmitriy :

    В тему поста: подскажите, чем может быть чревато размещение nginx и apache на одном порте (80), если nginx поставить слушать 11.22.33.44:80, а apache 127.0.0.1:80.

  22. Виталий :

    Сделал все точно как написано:
    root@iig:~# /etc/init.d/nginx restart && /etc/init.d/apache2 restart
    Restarting nginx: nginx.
    Restarting web server: apache2[Sat Jul 07 04:16:05 2012] [warn] module rpaf_module is already loaded, skipping
    [Sat Jul 07 04:16:05 2012] [warn] NameVirtualHost *:8181 has no VirtualHosts
    … waiting [Sat Jul 07 04:16:06 2012] [warn] module rpaf_module is already loaded, skipping
    [Sat Jul 07 04:16:06 2012] [warn] NameVirtualHost *:8181 has no VirtualHosts
    .
    root@iig:~# Restarting web server: apache2[Sat Jul 07 04:16:05 2012] [warn] module rpaf_module is already loaded, skipping
    -bash: Restarting: command not found
    root@iig:~# [Sat Jul 07 04:16:05 2012] [warn] NameVirtualHost *:8181 has no VirtualHosts
    -bash: [Sat: command not found
    root@iig:~# ... waiting [Sat Jul 07 04:16:06 2012] [warn] module rpaf_module is already loaded, skipping
    -bash: …: command not found
    root@iig:~# [Sat Jul 07 04:16:06 2012] [warn] NameVirtualHost *:8181 has no VirtualHosts

    Как-то можно проверить работает ли связка?

  23. Виталий :

    php не работает

  24. Статью читали невнимательно. И вхосты создавали не для порта 8181

  25. А как можно измерить скорость и количество загружаемых (отдаваемых) страниц в секунду, если сайт не опубликован наружу? крутится на внутреннем сервере для внутренних нужд…

    И соответственно как измерить параметры производительности сайта, опубликованного наружу ? Например, до установки nginx и после установки ?

  26. siege -c число -b http://кудафигачить.
    Оценивать придется визуально (htop, pv, etc), а siege даст необходимую нагрузку.

  27. А можете пояснить, если не трудно? А то я впервые вижу siege, и вообще с линуксом недавно пытаюсь подружиться..
    Запустил siege со следующими параметрами:

    # siege -c 20 -b http://test1.ru
    (тестирую локальный сервер после настройки nginx по вашей статье. 20 — это что? Количество одновременных коннектов к сайту? Типа 20 одновременных посетителей?)
    подождал несколько секунд и вот получил такой результат:

    Lifting the server siege… done.
    Transactions: 91 hits
    Availability: 100.00 %
    Elapsed time: 40.86 secs
    Data transferred: 1.33 MB
    Response time: 7.95 secs
    Transaction rate: 2.23 trans/sec
    Throughput: 0.03 MB/sec
    Concurrency: 17.70
    Successful transactions: 91
    Failed transactions: 0
    Longest transaction: 9.95
    Shortest transaction: 1.67

    Что можно понять из этой статистики ? Параметры nginx и apache такие же как в Вашей статье. Насколько они оптимальны? Да.. тестирование проходит на виртуалке, созданной в VirtualBox. Параметры процессора не нашел где посмотреть, оперативки 2 Гб выделено.

  28. 20 — это кол-во потоков. Поток получил ответ, потом сразу делает следующий запрос (-b).

    > Longest transaction: 9.95
    > Shortest transaction: 1.67
    Тормозит шоппц. Во что стреляете?

  29. Перед тестированием боевого сервера сделал его копию на VirtualBox, и в него стрелаю.. Возможно тормоза из за того, что я стреляю в сайт, находящийся на localhost, т.е. сервер одновременно и коннектится в 20 потоков и отдаёт контент.. Спасибо большое за вашу статью и за помощь.. Ночью попробую уже удалённый сервер потестировать..

  30. Может перед моими испытаниями посоветуете примерные настройки
    StartServers 1
    MinSpareServers 1
    MaxSpareServers 4
    MaxClients 4
    MaxRequestsPerChild 2000

    ?
    Боевой сервер на XEN, имеет следующие параметры:
    Процессор: 4×2000 МГц
    Память: 4Гб.
    ОС: debian6-x86

  31. > Может перед моими испытаниями посоветуете примерные настройки
    На такой виртуалке можно дефолтные смело оставлять.

    И кэш мускулю покрутите — памяти сильно больше той, под которую дефолтный my.cnf написан.

  32. Ильдус :

    Огромное спасибо за статью.
    Вопрос по поводу комментария «(не используйте в названии этих файлов символ -)», а что делать если в наименовании домена есть символ «-»

    Заранее большое спасибо.

  33. Были в своё время с этим баги — не читались такие конфиги.
    Заменять на _ можно, но в апаче, который в squeeze это починили.

  34. Михаил :

    Здравствуйте , я повстречал 3 проблемы , не знаю как решить. Правда следовал не точно мануалу. Debian Wheezy 3.14.0-bpo-2.rt ядро если как то влияет на исход. После данного мануала поставил apache-itk-mpm (незнаю влияет ли теперь IfModule mpm_prefork_module директива). Раскидал вхосты по пользователям. Конфиг mysql сменил на huge. Собственно проблема 1 — сайт по 8181 порту доступен извне. Не могу решить писать правки в potrs.conf (Listen 127.0.0.1:8181) или в каждый виртуалхост типа . Проблема 2 — изредка при трудоемких операциях на друпале выдает 404 ошибку — вообще не могу понять в чем дело. Проблема 3 на phpmyadmin если зайти по 80 порту то пропадает статика вообще , пока пользуюсь багой №1 хожу через 8181 порт. Подскажите как можно решить проблемы

  35. > сайт по 8181 порту доступен извне.
    Нужно в каждом вхосте написать 127.0.0.1:8181 (и в ports.conf тоже).

    > на друпале выдает 404 ошибку — вообще не могу понять в чем дело
    Скорее всего, в реальности ошибка другая (502 или 504). Просто nginx не может найти файл для ошибки и показывает 404.
    Смотрите, какие именно ошибки в логах.

    > Проблема 3 на phpmyadmin если зайти по 80 порту то пропадает статика вообще
    location ~* ^/phpmyadmin/ {…}

  36. Михаил :

    А после установки мпм итк апач конфигурируеться в той же директиве If_module_mpm_prefork ?

  37. вроде да.

  38. Михаил :

    Судя по логам Connection time out и Can not open file /var/www/nginx-default/50x.html. И в ответ 404 ошибка. Я так понимаю либо оптимизировать сайты , бд , либо увеличивать таймаут.

  39. Уху.
    Это как раз 504.

    Ну и уберите из конфига error_page 500 502 503 504 /50x.html;, раз вам лень положить красивый error_page в правильное место.

  40. Михаил :

    А не подскажите с чем может быть связана потеря производительности , если Siege -b http://mydomain.ru/ дергать довольно длительно (около минуты) на графике видно что использование CPU и Сети идет с провалами.

  41. Вообще — с миллионом причин.
    Смотреть нужно не на использование CPU и сети, а на времена ответа.

  42. Михаил :

    Время ответа не выше секунды на большом друпал сайте. Странно что вы выжали с VDS 2600 1GB RAM 30 страниц , а с Атома выше 50. Я на выделенном Core i5 8 Ram с ссд диском не могу выжать с 7 друпала выше 20 (без кеширования в самом друпале)…

  43. Ну я то стрелял в почти пустой drupal, там статей 20 было.

    Прогоните mysqltuner.pl, он чего-нибудь дельное посоветует.

    > Время ответа не выше секунды на большом друпал сайте.
    Нормально.

  44. Михаил :

    Кстати ptr запись мне все таки удалось достать у Росстелекома, не могли бы вы расписать поподробнее о dmarc,spf как посвободнее будет. И еще в статье про Exim вы так и не написали как заставить php потом слать письма через Exim. В гуглу конечно полно статей. Но что-то они не ахти работают. Друпал иногда ругается что не могёт отправить письмо.

  45. Михаил :

    В логах ошибки вида 2014-11-18 21:21:34 1XqPyG-00046A-Vy Message is frozen
    2014-11-18 21:21:34 1XqQ0q-0004GO-MU Message is frozen
    2014-11-18 21:21:34 End queue run: pid=30134
    2014-11-18 21:29:18 unable to set gid=1001 or uid=0 (euid=0): forcing real = effective
    2014-11-18 21:29:18 unable to set gid=1001 or uid=0 (euid=0): forcing real = effective

  46. > и не написали как заставить php потом слать письма через Exim.
    Вообще-то писал
    php_admin_value sendmail_path «/usr/sbin/sendmail -t -i -f webmaster@example1.ru
    в конфиге апача.

    А про exim пишите в жаббер, что ли. Мы тут диагностировать замучаемся.

  47. В общем, для истории — всё у Михаила правильно настроено, просто он действительно спам рассылал.

  48. Михаил :

    Нет, спам я не рассылал, заметил что начинает отваливаться при apache_mpm_itk, пока вернулся на дефолтную модель. А про /usr/sbin/sendmail -t … это точно ? разве не /usr/bin/exim4 -t?

  49. Михаил :

    в общем в такой конифгурации с сендмеил шлет письма 1шт секунд 10-20 …

  50. Михаил :

    Сейчас затестировал , точно при apache-mpm-itk сыпет в paniclog и в mainlog сообщения вида
    2014-11-18 21:29:18 unable to set gid=1001 or uid=0 (euid=0): forcing real = effective
    и php mail дает ошибку , изза чего в друпале ошибки вида «невозможно отправить почту, обратитесь к системному администратору»

  51. > А про /usr/sbin/sendmail -t … это точно ? разве не /usr/bin/exim4 -t?
    root@master:~# ls -la /usr/sbin/sendmail
    lrwxrwxrwx 1 root root 5 Nov 24 2011 /usr/sbin/sendmail -> exim4

    Пофиг на самом деле. sendmail — это симлинк на установленный MTA всегда.

    > 2014-11-18 21:29:18 unable to set gid=1001 or uid=0 (euid=0): forcing real = effective
    А в assignuserid что написано в апаче?

  52. Михаил :

    AssignUserID altyn altyn

  53. Михаил :

    useradd altyn -b /hdd/ -m -U -s /bin/false
    usermod -aG altyn www-data. И дальше создан вхост.

  54. Группы altyn небось нет
    С /bin/false шеллом работать от пользователя ничерта не должно, если ему шелл не задать при запуске чего либо (а exim этого не делает, да и apache емнип).

  55. Михаил :

    да , вы правы , группы нету) Тоесть чтобы заработало надо добавить группу , добавить пользователя в группу, и usermod altyn -s /bin/bash? Просто во многих гайдах пишут что желательно отключить консоль веб пользователям , в том числе и www-data.

  56. > веб пользователям
    веб-пользователям может быть. Только как он sendmail запустит?

    > надо добавить группу
    Можно просто в AssignUserID группу поменять на www-data

  57. Михаил :

    groups altyn
    altyn : altyn
    /etc/passwd
    altyn:x:1001:1001::/ssd/altyn:/bin/bash
    chmod 750 -R /ssd/altyn/
    ошибка та же (
    2014-12-02 21:57:10 unable to set gid=1001 or uid=0 (euid=0): forcing real = effective

  58. Михаил :

    c группой www-data в виртулхосте
    2014-12-02 22:03:58 unable to set gid=33 or uid=0 (euid=0): forcing real = effective

  59. 2014-12-02 21:57:10 unable to set gid=1001 or uid=0 (euid=0): forcing real = effective

    Где-то куда пролез рут в конфигурации. Там уже глазами смотреть надо. Погрепай
    grep -rni root /etc
    Может что интересного сам найдешь.

  60. Илья :

    ПРавим
    nano /etc/apache2/mods-available/mpm_prefork.conf
    LimitUIDRange 0 2000

  61. Илья, спасибо! Ваш совет помог!

  62. Спасибо Илье очень помог !

Написать комментарий