Хроники переезда: оптимизация (часть1)

Продолжая тему переезда на выделенный сервер.

Т.к. у меня имелось некоторое количество свободного времени, было решено переделать все «с нуля».

В качестве ОС решил установить Ubuntu server 14.04,  т.к. предполагается в дальнейшем установка BigBlueButton, а на Debian-е, в связи с особенностями дистрибутива, установка прерывается на этапе установки ruby gems.

Установка Ubuntu server — процесс несложный. Единственное замечание — если хотите устанавливать с флешки — не пишите её с помощью LiLi. Пишите Unetbootin или UltraISO, и вы сэкономите себе полчаса времени.

После установки системы ставим нужные нам компоненты:

apt-get install mc htop atop apache2 libapache2-mod-php5 nginx php5-gd php5-cgi php5-cli fail2ban

Дальше в принципе можно настраивать по предыдущей статье. Но есть ньюансы!

 

Об особенностях переезда — под катом. »

В Ubuntu server 14.04 по умолчанию установлен Apache 2.4.7, в отличие от 2.2 в Debian. То есть просто копированием старых конфигов нам не обойтись.

Первое, самое неожиданное: апач теперь понимает конфиги сайтов в sites-available только если у них расширение .conf.

Лечится либо переименованием конфигов

mv /etc/apache2/sites-available/sigillite.net /etc/apache2/sites-available/sigillite.net.conf

либо изменением глобальных опций в apache2.conf:

Было:  IncludeOptional sites-enabled/*.conf 
Стало: IncludeOptional sites-enabled/*

Второе — настройки безопасности каталогов. Вместо конструкции

Order deny,allow
Deny from all

теперь исползуется конструкция вида

Require all denied

Третье — изменение механизма работы mod_rpaf, но об этом позже.

Полный список изменений в работе апача 2.4 можно найти здесь.

Итак, индеец поднят, система настроена «как было». Время заняться оптимизацией.

Шаг 1. Мелкие оптимизации.

Много текста под катом »

Оптимизируем расход памяти индейцем:

mcedit /etc/apache2/mods-available/mpm_prefork.conf
<IfModule mpm_prefork_module>
        StartServers              2
        MinSpareServers           5
        MaxSpareServers           10
        MaxRequestWorkers         50
        MaxConnectionsPerChild   200
        ServerLimit      50
</IfModule>

В данном случае у нас используется модуль prefork. Он запускает отдельный процесс под каждое соединение, что не есть хорошо, но пока оставим так.

Закроем apache из мира и разнесем виртуальные хосты по портам.

Apache в нашем случае является back-end-ом nginx-а, соответственно, обращается к нему исключительно nginx. Это значит, что апачу не нужно слушать порты на всех интерфейсах, а достаточно слушать только на локальном.

Кроме того, можно разнести наши виртуальные хосты по разным портам. Это облегчит диагностику в дальнейшем, и немного изолирует сайты друг от друга.

mcedit /etc/apache2/ports.conf
Listen 127.0.0.1:8090 #порт для нашего сайта
Listen 127.0.0.1:8092 #порт для crm
#Listen 127.0.0.1:8094
#Listen 127.0.0.1:8096
#Listen 127.0.0.1:8098

В файле  /etc/apache2/sites-available/sigillite.net.conf заменим

<VirtualHost *:8090>

на

<VirtualHost 127.0.0.1:8090>

И соответственно в /etc/nginx/sites-available/sigillite.net установим параметр proxy_pass в значение

proxy_pass http://127.0.0.1:8090/;

Перезапускаем apache и nginx.

Все, теперь nginx и apache общаются через локальный интерфейс.

Настроим передачу адреса пользователя из nginx в apache.

Если сейчас заглянуть в логи apache, мы увидим примерно следующее:

%127.0.0.1 - - [24/Feb/2015:23:51:22 +0200] "GET / HTTP/1.0" 200 22068 "http://sigillite.net/" 
"Mozilla/5.0 (Windows NT 6.1; WOW64; rv:35.0) Gecko/20100101 Firefox/35.0"

Т.е. вместо IP клиента мы получаем IP nginx-а. Исправить эту ситуацию ранее помогал модуль mod_rpaf.

Попробуем настроить:

В /etc/nginx/sites-available/sigillite.net в секции перенаправления на apache (после proxy_pass) пропишем:

proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $remote_addr;

В /etc/apache2/mods-available/rpaf.conf:

#<IfModule rpaf_module>
<IfModule mod_rpaf-2.0.c> #для корректной работы в apache 2.4.7, не вникал
    RPAFenable On
    RPAFsethostname On
    RPAFproxy_ips 127.0.0.1 your_real_ip
    RPAFheader X-Real-IP
    RPAFheader X-Forwarded-For
</IfModule>
a2enmod rpaf

Перезапустим apache и nginx.

Все, теперь у нас в логах отображается IP клиента.

Для apache 2.2 этого достаточно, но 2.4.7 почему-то продолжает подсовывать 127.0.0.1 в REMOTE_ADDR:

Скриншот 2015-02-26 13.52.07

В принципе, можно оставить и так, если данная переменная нигде не используется. У меня из нее берутся данные для модуля  учета заходивших в гости ботов, поэтому я исправлю.

Чтобы пофиксить это, в 2.4.7 нужно загрузить еще 1 модуль:

a2enmod remoteip

и добавить в apache2.conf:

RemoteIPHeader X-Real-IP

Теперь после перезапуска Apache REMOTE_ADDR отображается правилно

Скриншот 2015-02-26 14.07.38

Шаг 2. Кеширование.

Много текста под катом »

В рамках оптимизации работы блога решил проверить производительность.

Для этого в файл footer.php темы вордпресс достаточно добавить следующий код:

<?php
echo "Статистика:" . get_num_queries() . "/ "; timer_stop(1);
echo "s/ ". round(memory_get_usage()/1024/1024, 2) . " MB ";
?>

теперь в правом нижнем углу футера будет отображаться вот такая информация:

Скриншот 2015-02-26 14.52.18Первый параметр — это количество запросов к БД, второй — время загрузки страницы, и третий — использованная для загрузки память.

Постараемся минимизировать эти данные.

Сначала разберемся — куда уходят наши ресурсы.

WordPress — это по сути набор php-скриптов, который при каждом обновлении страницы извлекает данные из БД, формирует на основании них страницу и отображает ее.

Т.к. РНР — интерпретируемый язык, то он «компилирует» код при каждом его выполнении. Этот процесс занимает время и ресурсы нашего компьютера.

Также при каждом обновлении страницы WordPress извлекает данные для отображения из БД. Т.е. при каждом обновлении страницы у нас:

  • создается форк процесса apache
  • компилируются и выполняются php-скрипты
  • с помощью выполняющегося php-скрипта запрашиваются данные из БД

Т.о. для уменьшения нагрузки нам необходимо:

  • минимизировать количество запросов к БД
  • минимизироват количество компиляций php-скриптов
  • оптимизировать работу apache

Кеширование php с помощью ZendOpCache

Первым этапом мы кешируем php. Т.е. сделаем так, чтобы скрипт компилировался не при каждом обращении к нему, а только при первом, а далее выполнялся из кеша.

Для этого установим Zend OpCache:

apt-get install php-pear
apt-get install build-essential php5-dev
pecl install zendopcache-7.0.3

Настроим его согласно рекомендаций самих разработчиков:

mcedit /etc/php5/mods-available/opcache.ini
zend_extension=opcache.so

opcache.memory_consumption=128
opcache.interned_strings_buffer=8
opcache.max_accelerated_files=4000
opcache.revalidate_freq=60
opcache.fast_shutdown=1
opcache.enable_cli=1

Перезапускаем апач и смотрим:

Скриншот 2015-02-26 15.18.41

Имеем около 60% экономии памяти на каждом обновлении страницы.

Можно также установить OpCache Control Panel, прописать ее на виртуалхост или добавить в папку с вордпресс и наблюдать за состоянием кеша прямо в браузере

Скриншот 2015-02-26 15.51.37

 

 Кеширование запросов в БД

Второй этап — кеширование запросов в БД. В этом нам поможет  плагин для WordPress db-cache-reloaded-fix.

Все просто — установили, активировали, смотрим:

Скриншот 2015-02-26 15.38.07Количество запросов в БД уменьшилось на 90%.

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

Оптимизация работы apache

Много текста под катом »

По умолчанию apache работает в режиме prefork. Это означает, что apache при запуске создает какое-то количество процессов, от которых на каждое соединение создается форк.

Параметры количества создаваемых форков определяется в файле /etc/apache2/mods-available/mpm_prefork.conf

Оптимальные параметры выбираются во многом эмпирически, методом проб. Пример настройки, оптималной для меня, указан выше.

Если данные параметры не устраивают — можно попробовать сконфигурировать apache под использование модуля mpm_worker. В отличии от префорка, воркер не плодит процессы, а открывает потоки в рамках определенного в конфиге количества процессов.

Я решил пропустить этот этап и попытаться выбросить apache из конфигурации вообще, переложив роль back-end на плечи модуля php-fpm. Об этом подробнее — в следующей статье.

Отмечу, что сам я использую не все функции, которые описаны в данной статье.

Например, меня не устроила работа bd-cache-reloaded, поскольку я использую форму входа (данные из которой он также успешно кеширует). Однако, для многих данный плагин будет полезен, поэтому я счел нужным включить его в данную статью.

А в следующем посте мы попробуем выбросить из нашей конфигурации самое святое — апач )

Добавить комментарий

Войти с помощью: