Целью этой и предыдущей статей является моё желание показать возможность оптимизации сайтов не только на WordPress, а вообще любого веб-приложения. Поэтому я использую такое количество инструментов, и так детально разбираю их конфигурацию. Если же Вам просто нужно ускорить WordPress — установите плагин WP Super Cache. Если Вас, как и меня, интересуют технологии, позволяющие оптимизировать любой сайт, а также Вам интересно, что стоит учитывать при разработке веб-приложений, рассчитанных на высокие нагрузки — прошу под кат, но только после прочтения первой части — дорабатывать я буду ту же систему.
Отключаем лишнее
Рекомендации в данном разделе многим могут показаться банальными, но обещаю вам, чем дальше мы будем продвигаться, тем интереснее будут пункты. Данный пункт привёл к значительному ускорению работы сайта, и я считаю, что это должно быть здесь.
Итак, среднее время генерации динамической страницы для залогиненного пользователя — 770 мс. Время генерации измерялось путём добавления в исходник index.php строчек:
<?php
$t = microtime(1);
//содержимое index.php
echo '<!--Сгенерировано за: ' . (microtime(1) - $t) . 's' . '-->';
?>
Далее я провёл предварительный стресс-тест: 50 пользователей одновременно обращаются к динамически генерируемой странице, как только загрузка страницы завершена — тут же идёт следующий запрос.
Максимальное время ответа в данном случае составило 45.721 секунды.
Следуем распространённому совету, в кругах оптимизаторов WordPress, а именно — отключаем ненужные плагины. В моём блоге практически в каждой статье приводятся листинги кода/конфигурации. Для этих целей я использовал плагин Crayon Syntax Highlighter, рекомендуемый чуть ли не каждым блогером как лучшее средство для подсветки синтаксиса в листингах. Однако, сама подсветка мне была не столь уж и нужна, главное — аккуратно оформленное окошечко со скролл-баром с поддержкой табуляции. В целях тестирования попробовал отключить этот плагин. Результат — вместо 770 мс генерация страницы происходила в среднем за 170 мс, что в 4.5 раза быстрее. Однако, листинги теперь не были оформлены — текст статей сливался с кодом. Далее в поисках замены я наткнулся на плагин wp-syntax, который имел не такой богатый функционал как Crayon Syntax Highlighter, но со своей главной задачей — подсветкой синтаксиса, справлялся на ура. Среднее время генерации страницы с этим плагином составило в среднем 235 мс, что, в общем-то, приемлемо. Здесь я повторно провёл стресс-тест. Результаты следующие:
Максимальное время ответа теперь составило 9.897 секунды. Разница колоссальная.
Однако, как я уже говорил выше, подсветка для меня была не так уж и важна. Поэтому я решил удалить и этот плагин тоже, а вместо этого в стилях темы для тега <pre> (в него заключались листинги кода в вышеописанных плагинах) прописать следующие стили:
pre {
max-height: 700px;
margin-bottom: 20px;
overflow: auto;
background: #f0f0f0;
padding: 10px;
-webkit-box-shadow: 0px 0px 3px 0px rgba(0,0,0,0.75);
-moz-box-shadow: 0px 0px 3px 0px rgba(0,0,0,0.75);
box-shadow: 0px 0px 3px 0px rgba(0,0,0,0.75);
}
Листинги приняли следующий вид:
Этого мне было достаточно. Время генерации страницы на сервере — 170 мс. Проводим стресс-тест:
Максимальное время ответа теперь 7.002 секунды. Разница ощутима, оставляю этот вариант.
Далее я убрал из футера 2 виджета — последние комментарии и облако тегов. За счёт уменьшения количества запросов к БД среднее время генерации страницы на сервере сократилось до 155 мс. Результаты стресс-теста потерял, но максимальное время ответа составляло примерно 6.5 секунды.
Выбор движка таблиц в MariaDB
В комментариях к предыдущей статье мне указали на то, что использование MyISAM в качестве движка таблиц в СУБД MariaDB необоснованно. Согласен, исправляюсь. Выбирать буду между MyISAM, Aria, XtraDB.
Конфигурация my.cnf в случае с MyISAM и Aria будет одинаковой, и не отличается от конфигурации, приведённой в первой статье. Однако, для Aria следует использовать директиву default-storage-engine=Aria.
Для XtraDB следует задать следующие директивы (привожу только то, что изменил по сравнению с конфигурацией в предыдущей статье):
key_buffer = 32M #Уменьшаем буфер для ключей таблиц MyISAM и Aria
#skip-innodb #Включаем обратно движок XtraDB
#default-storage-engine=MyISAM #По-умолчанию теперь будет XtraDB
innodb_buffer_pool_size = 128M #Размер буфера для кэширования данных и индексов XtraDB
innodb_flush_method = "O_DIRECT" #Выбираем более надёжный метод сброса данных из памяти на диск
В качестве критерия выбора я сначала хотел использовать время генерации страниц, однако все типы движков при простом запросе страницы показывали одни и те же результаты, поэтому было решено произвести стресс-тесты с нагрузкой в 100 пользователей. Мой тестовый аккаунт не позволял запускать стресс-тесты с количеством пользователей более 50, однако, как было выяснено опытным путём, было возможно запускать несколько тестов из разных вкладок браузера одновременно, чем я и воспользовался. Проверяем MyISAM. Пользователей: 100 (в другой вкладке чуть раньше запущен такой же тест):
Максимальное время ответа: 17.473 секунды.
Проверяем Aria. Пользователей: 100 (в другой вкладке чуть раньше запущен такой же тест):
Максимальное время ответа: 14.223 секунды. При этом более плавное изменение времени ответа.
Проверяем XtraDB. Пользователей: 100 (в другой вкладке чуть раньше запущен такой же тест):
Максимальное время ответа: 14.355 секунды.
Так как результаты на XtraDB и на Aria оказались почти одинаковыми, оставив при этом позади MyISAM, я решил пойти дальше и увеличивать число запросов, пока сайт на ляжет. На каком движке выдержит большую нагрузку — тот и выберу.
Снова тестируем Aria. Пользователей: 150 (в других двух вкладках чуть раньше запущены такие же тесты):
Упало на 148 пользователях. Время ответа: 19.311 секунды.
Тестируем XtraDB. Пользователей: 150 (в других двух вкладках чуть раньше запущены такие же тесты):
Упало на 150 пользователях. Время ответа: 20.963 секунды. В целом, результаты на Aria и XtraDB почти одинаковые. Но я решил выбрать XtraDB, потому что в дальнейшем хочу реализовать запрос данных для страниц со статьями с помощью NoSQL-решения HandlerSocket, работающее только с InnoDB/XtraDB. В данный момент существует расширение, компилируемое для PHP (php-handlersocket) и библиотека, написанная на PHP (HSPHP). Расширение я успел попробовать совместно с PHP5.6. С его помощью я сделал выборку из БД по PRIMARY KEY примерно в 2.5 раза быстрее, чем с помощью SQL-запроса. Но под PHP7 оно компилироваться отказывается (а следующим шагом у нас будет именно переход на новую версию). Что касается библиотеки HSPHP — замерив время получения выборки с её помощью и с помощью SQL-запроса (с учётом времени на подключение библиотеки), я выяснил, что при одиночном запросе в БД прироста она не даёт. Поэтому от её использования я отказался и теперь жду версии расширения, совместимой с PHP7.
Установка и настройка PHP7 + php-fpm
3 марта состоялся релиз новой версии PHP7.0.4. Её и будем ставить. Для начала удалим предыдущую версию PHP и php-fpm:
apt-get purge php5 php5-fpm
Скачиваем и распаковываем архив с исходниками:
mkdir /usr/local/src/php7-build
cd /usr/local/src/php7-build
curl -O http://se1.php.net/get/php-7.0.4.tar.bz2/from/this/mirror
tar jxf php-7.0.4.tar.bz2
cd php-7.0.4/
Устанавливаем всё необходимое для компиляции:
apt-get install build-essential libfcgi-dev libfcgi0ldbl libjpeg62-turbo-dbg libmcrypt-dev libssl-dev libc-client2007e libc-client2007e-dev libxml2-dev libbz2-dev libcurl4-openssl-dev libjpeg-dev libpng12-dev libfreetype6-dev libkrb5-dev libpq-dev libxml2-dev libxslt1-dev
Создаём симлинк, иначе не сможем скомпилить php с поддержкой imap.
ln -s /usr/lib/libc-client.a /usr/lib/x86_64-linux-gnu/libc-client.a
Создаём папку для установки:
mkdir /opt/php-7.0.4
Конфигурируем:
./configure --prefix=/opt/php-7.0.4 --with-pdo-pgsql --with-zlib-dir --with-freetype-dir --enable-mbstring --with-libxml-dir=/usr --enable-soap --enable-calendar --with-curl --with-mcrypt --with-zlib --with-gd --with-pgsql --disable-rpath --enable-inline-optimization --with-bz2 --with-zlib --enable-sockets --enable-sysvsem --enable-sysvshm --enable-pcntl --enable-mbregex --enable-exif --enable-bcmath --with-mhash --enable-zip --with-pcre-regex --with-pdo-mysql --with-mysqli --with-mysql-sock=/var/run/mysqld/mysqld.sock --with-jpeg-dir=/usr --with-png-dir=/usr --enable-gd-native-ttf --with-openssl --with-fpm-user=www-data --with-fpm-group=www-data --with-libdir=/lib/x86_64-linux-gnu --enable-ftp --with-imap --with-imap-ssl --with-kerberos --with-gettext --with-xmlrpc --with-xsl --enable-opcache --enable-fpm
Компилируем и устанавливаем (если у Вас VDS с теми же характеристиками, как у меня, можете смело идти пить кофе):
make
make install
Копируем конфиги:
cp /usr/local/src/php7-build/php-7.0.4/php.ini-production /opt/php-7.0.4/lib/php.ini
cp /opt/php-7.0.4/etc/php-fpm.conf.default /opt/php-7.0.4/etc/php-fpm.conf
cp /opt/php-7.0.4/etc/php-fpm.d/www.conf.default /opt/php-7.0.4/etc/php-fpm.d/www.conf
В файле /opt/php-7.0.4/etc/php-fpm.conf раскомментируем следующие строки:
pid = run/php-fpm.pid
events.mechanism = epoll
В файле /opt/php-7.0.4/etc/php-fpm.d/www.conf задаются те же настройки для воркеров, что и в первой статье. Директиву listen = 127.0.0.1:9000 Заменяем следующими строками:
listen = /var/run/php7.0.4-fpm.sock
listen.owner = www-data
listen.group = www-data
Соответственно, в настройках nginx'а в файле /etc/nginx/conf.d/backend.conf стоит указать директиву:
fastcgi_pass unix:/var/run/php7.0.4-fpm.sock;
При этом необходимо увеличить максимальное количество разрешенных подключений к Unix-сокету в системе, добавив в конец файла /etc/sysctl.conf директиву:
net.core.somaxconn = 65535
После этого необходимо перечитать конфиг:
sysctl -p /etc/sysctl.conf
В файле /opt/php-7.0.4/lib/php.ini задаём те же настройки, как и в первой статье. Для включения OPcache помимо этого добавляем строку:
zend_extension=opcache.so
Создаём симлинки для PHP и утилит:
ln -s /opt/php-7.0.4/bin/pear /bin/pear
ln -s /opt/php-7.0.4/bin/peardev /bin/peardev
ln -s /opt/php-7.0.4/bin/pecl /bin/pecl
ln -s /opt/php-7.0.4/bin/phar /bin/phar
ln -s /opt/php-7.0.4/bin/phar.phar /bin/phar.phar
ln -s /opt/php-7.0.4/bin/php /bin/php
ln -s /opt/php-7.0.4/bin/php-cgi /bin/php-cgi
ln -s /opt/php-7.0.4/bin/php-config /bin/php-config
ln -s /opt/php-7.0.4/bin/phpdbg /bin/phpdbg
ln -s /opt/php-7.0.4/bin/phpize /bin/phpize
Теперь создаем файл юнита systemd /etc/systemd/system/php-7.0.4-fpm.service:
[Unit]
Description=The PHP 7 FastCGI Process Manager
After=network.target
[Service]
Type=simple
PIDFile=/opt/php-7.0.4/var/run/php-fpm.pid
ExecStart=/opt/php-7.0.4/sbin/php-fpm --nodaemonize --fpm-config /opt/php-7.0.4/etc/php-fpm.conf
ExecReload=/bin/kill -USR2 $MAINPID
[Install]
WantedBy=multi-user.target
Активируем сервис и перезапускаем systemd:
systemctl enable php-7.0.4-fpm.service
systemctl daemon-reload
Осталось только запустить php-fpm:
systemctl start php-7.0.4-fpm.service
Проверяем скорость генерации страницы на сервере: 45 мс. По сравнению с предыдущим шагом производительность выросла в 3.4 раза. Проводим нагрузочное тестирование. 150 пользователей оказалось недостаточно, чтобы сайт упал. Открываем ещё одну вкладку с тестом. На 179 пользователях проскакивает ошибка (не полный крах), останавливаю тест. Максимальное время ответа: 8.966 секунды. В общем, переходите на PHP7.
Настройка Edge Side Includes (ESI) в Varnish
ESI — это язык для включения фрагментов веб-страниц в другие страницы. Это позволяет использовать кэшированные страницы, с использованием в них динамических элементов, сократив за счёт этого время генерации. Это аналог SSI.
В WordPress я решил это использовать для реализации следующей схемы: если пользователь залогинен, то генерировать на бэкенде для него только header, содержащий верхнее пользовательское меню. Для страниц с записями также динамически генерировать блок с комментариями. Всё остальное берётся из кэша. Также для сохранения высокой скорости отдачи для незалогиненных пользователей для каждой странички генерируется статический header и в последующем используется из кэша.
Так как теперь всё, что ниже header'а кэшируется, определить скорость генерации страницы с помощью PHP не получится. Для этого я использовал сервис Pingdom Tools, позволяющий оценить скорость загрузки сайта в целом, так и каждого документа. Выбрал я его по причине того, что у них возможно запустить тестирование с сервера, расположенного в Амстердаме, где и расположен мой VDS. За счёт этого время на установление соединения было в районе 20 мс и время генерации страницы после отправки запросу серверу при нескольких подряд отправленных запросах практически не менялось (± 5 мс). Перед активацией ESI я замерил скорость загрузки сайта с помощью этого сервиса. Вот результаты:
Сайт полностью загрузился за 360 мс, а время генерации самой страницы составило 135 мс. Приступим к настройке.
Немного изменим файл конфигурации VCL /etc/varnish/default.vcl, приведенный в первой части.
После блока в секции vcl_backend_response, описывающего работу со статическими файлами
# Для статических файлов, которые отдаёт бэкенд...
{
...
}
Добавляем следующий блок:
# Включаем обработку ESI для всех запросов, в URL которых отсутствует слово dynamic, можно сделать что-то более уникальное, так как такой запрос вполне уже может существовать
if (!(bereq.url ~ "dynamic")) {
set beresp.do_esi = true;
}
Включение обработки будет включено только для тех случаев, для которых в секции vcl_recv не указан запрет обработки с помощью директивы set req.esi = false;
Блок кода в секции vcl_recv, отправляющий на бэкенд залогиненного пользователя
if (req.http.Cookie ~ "wordpress_" || req.http.Cookie ~ "comment_") {
return (pass);
}
заменяем на блок:
# Для незалогиненных пользователей отключаем ESI.
if (!(req.http.Cookie ~ "wordpress_" || req.http.Cookie ~ "comment_")) {
set req.esi = false;
}
А в самое начало секции vcl_recv помещаем следующий блок:
# Пропускать запросы, содержащие слово dynamic
if (req.url ~ "dynamic") {
return (pass);
}
Теперь нужно заставить WordPress работать нужным нам образом. Но для начала расскажу о тегах, используемых в ESI, позволяющих сформировать 2 разные страницы в браузере, в зависимости от того, включена обработка ESI или нет.
- Тэг комментария <!--esi… --> — при условии включенной обработки ESI эти комментарии убираются, а то, что было ими закомментировано, при этом выполняется. Если же ESI отключено, то в браузере клиента данный участок кода будет интерпретирован как простой HTML-комментарий и будет проигнорирован;
- <esi:include src=«адрес/страницы»/> — если включено ESI, будет произведен инклуд этой страницы в данном месте. Если ESI выключено, будет передано в браузер в исходном виде. Поэтому заключается в вышеописанный тэг комментария;
- <esi:remove> ... </esi:remove> - если включено ESI, будет произведено удаление данного участка кода. Если ESI выключено, будет передано в браузер в исходном виде. Поэтому так же заключается в вышеописанный тэг комментария.
Итак, настраиваем WordPress. Код верхней пользовательской панели генерируется, как правило, в файле header.php. Однако в моём случае часть стилей была перемещена в footer.php в целях ускорения загрузки страницы и генерировалась при вызове функции wp_footer(). Первым делом я перенёс вызов этой функции в файл header.php, поместив после открывающего тэга <body> код:
<?php wp_footer(); ?>
и убрал его в файле footer.php.
Теперь отредактируем файл темы index.php. Вместо кода
<?php get_header(); ?>
напишем:
<?php
$beforeHeader = '?';
if(isset($_GET['dynamic-header']) || isset($_GET['static-header']))
{
get_header();
die();
}
elseif ($_SERVER['QUERY_STRING'] != '')
{
$beforeHeader = '&';
}
?>
<!--esi <esi:include src="<?php echo $_SERVER['REQUEST_URI'] . $beforeHeader; ?>dynamic-header"/>
<esi:remove> -->
<?php echo file_get_contents('http://webshake.ru'.$_SERVER['REQUEST_URI'] . $beforeHeader .'static-header'); ?>
<!--esi </esi:remove> -->
Если не поняли, поясню, как это работает. В переменной $beforeHeader лежит символ, который будет поставлен перед параметром в URL. Если строка запроса пуста, добавляем после адреса вопросительный знак и параметр, если нет — символ '&' и параметр. Если методом GET была установлена переменная dynamic-header или static-header, то выдать заголовок и умереть. Иначе, в случае включенного ESI (а для нас это означает, что перед нами залогиненный пользователь), запросить текущую страницу с добавлением ?dynamic-header. Так как в URL содержится слово dynamic, Varnish направит запрос на бэкенд. Затем будет загружена текущая страница с ?static-header на конце при помощи функции file_get_contents(), при этом никакие cookies от пользователя не дойдут до этой страницы и будет сформирован статический заголовок, предназначенный для гостей, который ввиду отсутствия в URL слова dynamic отправится в кэш.
В случае, если ESI отключено (зашёл гость), инклуда динамического заголовка не произойдёт, и будет отправлен закомментированный код. Теги <esi:remove> и </esi:remove> так же будут отправлены закомментированными, а код статического заголовка будет подгружен из кэша, либо сгенерируется и сохранится в кэш, если обращение к странице произошло впервые.
Производим аналогичную замену кода <?php get_header(); ?> во всех страницах темы, где он имеется.
Осталось только реализовать динамическую работу с комментариями на страницах записей. Для этого открываем шаблон single.php и ищем функцию, отвечающую за выдачу кода комментариев. В моём случае это функция comments_template(); и в начало кода помимо уже добавленного нами пишем:
<?php
if(isset($_GET['dynamic-comments']))
{
comments_template( '', true );
die();
}
А вместо вызова функции
<?php comments_template( '', true ); ?>
Пишем:
<!--esi <esi:include src="<?php echo $_SERVER['REQUEST_URI'] . $beforeHeader; ?>dynamic-comments"/>
<esi:remove> -->
<?php echo file_get_contents('https://webshake.ru'.$_SERVER['REQUEST_URI'] . $beforeHeader .'dynamic-comments'); ?>
<!--esi </esi:remove> -->
Работает всё точно так же как и в случае выше, только комментарии всегда будут выдаваться динамически, потому что если кто-то добавит комментарий, PURGE-запрос будет отправлен только на страницу, но не на page?static-comments и комменты для незалогиненных не обновятся, а так всё работает.
Перезапускаем varnish:
service varnish restart
Замеряем скорость загрузки сайта с включённым ESI:
Общее время загрузки сайта — 289 мс. Время генерации страницы составило при этом 65 мс. Таким образом, с помощью ESI мы ускорили генерацию страницы для пользователя чуть больше чем в 2 раза.
После этого я провёл финальное нагрузочное тестирование. Пользователей: 300 (в других пяти вкладках чуть раньше запущены такие же тесты):
Сервер упал при нагрузке в 276 залогиненных пользователей. Время ответа при этом составило 7.155 секунды.
Эффективное сжатие
В комментариях к предыдущей статье мне указали на то, что сжатие на выходе nginx со степенью сжатия 9 будет давать лишнюю нагрузку на процессор, при этом файлы сожмутся сильнее примерно на 5 процентов, по сравнению со степенью сжатия 1, дающей гораздо меньшую нагрузку на процессор.
Собственно, пришла мысль для сжатия статических файлов (.css, .js) использовать 9 степень и сжимать их на стороне бэкенда, после чего они будут попадать в кэш Varnish'а и уже без последующей нагрузки на процессор за счёт операции сжатия передаваться пользователю, а саму генерируемую страничку сжимать на фронтенде со степенью сжатия 1.
Таким образом и место в кэше сэкономим, и отдавать пользователям будем более мелкие файлы.
Для этого нужно в конфиге фронтенда nginx /etc/nginx/conf.d/frontend.conf прописать следующие директивы:
gzip on;
gzip_comp_level 1;
gzip_min_length 512;
gzip_buffers 8 64k;
gzip_types text/plain;
gzip_proxied any;
А в конфиге бэкенда /etc/nginx/conf.d/backend.conf:
gzip on;
gzip_comp_level 9;
gzip_min_length 512;
gzip_buffers 8 64k;
gzip_types text/css application/json application/x-javascript text/xml application/xml application/xml+rss text/javascript application/javascript image/svg+xml;
gzip_proxied any;
Никаких ощутимых результатов в скорости загрузки мне не дало, но размеры статических файлов всё же поуменьшились на несколько Кб. На супер-нагруженной системе это даст свои плоды.
Заключение
Помимо всего перечисленного можно дождаться выхода memcache для PHP7 и кэшировать запросы к БД с помощью плагина W3 Total Cache или какого-либо подобного. Также хотелось бы увидеть расширение php-handlersocket для PHP7, попробовать использовать для получения материалов по ID. Скорость доступа к этим данным должна возрасти раза в 2 точно. Большую часть советов, которые были даны в комментариях к прошлой статье выполнил. Спасибо большое комментаторам, благодаря Вам удалось разогнать сайт так, как я и не мечтал. Благодарю за прочтение.
Комментарии (44)
KriMs
09.03.2016 22:16+2> gzip_comp_level 9;
Лучше не ставить больше 6. Процессор на 9-ке грузится сильнее, а эффект сжатия после 6-ки минимальный.ivashkevitch
09.03.2016 22:35-1Раз в сутки можно и "нагрузить". Файлов-то не более 10, не думаю, что это в данном примере вообще нагрузить процессор.
NorthDakota
10.03.2016 01:05-1Ну так дело в том что gzip юзается перед отдачей контента конечному пользователю
Как результат, каждый запрос будет нагружать процесорInSys
10.03.2016 01:13+1Ну насколько я понял, мысль у человека следующая — сжимать с 9 level и кешировать этот ответ в Varnish:
Собственно, пришла мысль для сжатия статических файлов (.css, .js) использовать 9 степень и сжимать их на стороне бэкенда, после чего они будут попадать в кэш Varnish'а и уже без последующей нагрузки на процессор за счёт операции сжатия передаваться пользователю, а саму генерируемую страничку сжимать на фронтенде со степенью сжатия 1.
в принципе в этом есть доля логики.NorthDakota
10.03.2016 01:26-1Хм, интересно,
хотя мне кажется отдавать статику через nginx будет быстрее
минифицировать и отдавать, вот и весь секрет.
Я так понимаю варниш слушает 80й порт?
в таком случае ставим nginx на 80й, варниш например на 81
и через nginx проксируем не статический трафик на варниш,
варниш если нету готового кеша лезет в бекенд на 82й порт, на котором nginx уже дёргает пых и возвращается всё по цепочке вверх
Как ни странно видел такую (бредовую) связку на одном хайлоад проекте, правда там вместо nginx был апачivashkevitch
10.03.2016 04:33-1Нет, схема следующая: nginx(установка SSL-соедиения + сжатие HTML со сжатием 1) — varnish — nginx (отдача статики со сжатием 9, .php передается на обработку fpm). Вот первая часть — https://habrahabr.ru/post/278189/
Как мне кажется, получение фронтендом уже сжатых файлов из кэша Varnish'а будет происходит быстрее, чем сжатие и отдача nginx'ом каждый раз. Ну или добавить при этом кэширование сжатого nginx'ом в самом nginx'е (фронтенде). Вроде как говорят, будет ещё шустрее.igordata
15.03.2016 15:15Не хочу портить наслаждение строительством мега-связок, но есть же gzip_static http://nginx.org/ru/docs/http/ngx_http_gzip_static_module.html
просто рядом с каждым файлом должен лежать на харде файл с тем же именем и добавленным расширением .gz
Возможно даже есть модуль для WP, который автоматом будет жмакать статику при изменении.
sepich
10.03.2016 00:24+1Создаём init-скрипт /etc/init.d/php-7.0.4-fpm:
chmod 755 /etc/init.d/php-7.0.4-fpm
insserv php-7.0.4-fpm
Теперь создаем файл юнита systemd /lib/systemd/system/php-7.0.4-fpm.service:
systemctl enable php-7.0.4-fpm.service
systemctl daemon-reload
Вы уж определитесь, вы хотите sysv инит-скрипт или systemd юнит ;)
В том виде, в котором вы написали, запускаться будет php-7.0.4-fpm.service и в /etc/init.d/php-7.0.4-fpm нет смысла.
А так же неоднократно говорилось что не надо трогать грязными руками файлы в /lib/systemd/ — это место хранения вендор конфигов.
Свои надо создавать в /etc/systemd/system где они будут иметь больший приоритет и оверрайдить вендор-дефоулт
flyaway
10.03.2016 03:41+5Зачем тестировать скорость генерации страницы с внешнего сервера, если можно делать это с локалхоста?
Задержки, вызванные сетью/ядром можно считать постоянными
Зачем запускать вдобавок к nginx еще и varnish?
Последний может иметь смысл на супернагруженом фронтенде, через который проходят терабайты трафика, но не на чахлом VDS с единственным сайтом. Тут одного nginx вполне достаточно, он к тому же сам умеет и SSI, и кеширование.
Зачем собирать php7 из сырцов и руками изобретать симлинки/стартовые скрипты?
https://www.digitalocean.com/community/tutorials/how-to-upgrade-to-php-7-on-ubuntu-14-04
Первая же ссылка в гугле — установка через ppa в пару команд.
В остальном хорошо, пытливость имеется, остается овладеть матчастью.ivashkevitch
10.03.2016 04:54-1Спасибо за советы, о переносе на локалхост думал, но железо, в частности частота процессора, будет другим, хотя, для того чтобы показать разницу с ESI и без него, вполне подойдёт. Буду разбираться с кэшированием и SSI в nginx. Почему-то он мне показался более сложным в плане этих настроек, по сравнению с Varnish.
P.S. PHP зато 7.0.4.flyaway
10.03.2016 12:27+1Под тестированием с локалхоста я имел в виду запуск системы нагрузочного тестирования на том же VDS с указанием таргета localhost.
>PHP зато 7.0.4.
Заглядывать в этот ppa не стали?
php7.0 7.0.4-5+deb.sury.org~trusty+1
xXxSPYxXx
10.03.2016 14:14https://www.dotdeb.org
Есть какое-то решение проблемы 502, кроме как уход с сокетов?
Evgeny42
10.03.2016 04:02+2Даже с кучами кеша, сжатий и отказов от плагина простой бложик падает на 200 пользователях, что-то в этом мире не так.
OrNix
10.03.2016 08:35Вместо handler sockets посмотрите на стандартный InnoDB Memcache Plugin: https://dev.mysql.com/doc/refman/5.6/en/innodb-memcached-setup.html
nikolayvaganov
10.03.2016 08:42+5вместо "make install" использовать checkinstall. Вообще очень странно, что у Вас бекенд fpm висит на TCP/IP вместо unix socket .
nonname
10.03.2016 11:23+2Ну и как альтернатива например можно использовать сторонний репозиторий тот же dotdeb, там уже есть пакеты для PHP7, чтобы не собирать их на дохленькой впс.
nikolayvaganov
10.03.2016 14:14+1dotdeb для продакшена крайне плох. По опыту — очень нестабильные пакеты у них. По поводу TCP/IP vs unix socket — не видел проектов, чтобы быстрый сокет проигрывал по скорости, стабильности, ресурсоемкости TCP/IP подключению, зато видел сотню висящих соединений в SYN_RECV. И по логике вещей при каждом новом подключении к tcp/ip сокету нужно будет ждать tcp handshake.
xXxSPYxXx
10.03.2016 14:20Есть проблема в php7. Через некоторое время работы php7-fpm начинает выплевывать в Nginx 502 ошибку. Что только не делал чтобы исправить. На своем блоге сейчас пришлось вернуть на php5.6
nikolayvaganov
10.03.2016 15:03+1Можете подсказать, для каких целей требуется использовать версии php не из репозиториев системы? Понятно, что для хайлоад проектов требуется собирать ПО с нужными опциями и отключать ненужные, но для среднего блога я не вижу разницы в использовании совсем новых сырых релизов, при том, что в новом новых версиях баги и дырки находят значительно чаще, чем в старых. Тут можно ( если можно ) сравнить с сопровождением Linux систем в целом. Выходит новый релиз, ждешь год для обкатки, выявления багов и уязвимостей, потом начинаешь внедрять для проектов.
Sannis
11.03.2016 03:24Не пробовали чем-нибудь вроде strace смотреть чем в этот момент php-fpm занимается?
ivashkevitch
11.03.2016 10:36Перевёл на сокет, проблему с 502 ошибкой решил добавлением net.core.somaxconn = 65535 в /etc/sysctl.conf
nikolayvaganov
11.03.2016 12:18Также крайне рекомендую отдельные сайты разносить под отдельных пользователей :
- В плане безопасности.
Ломают один сайт — вешают шелл, шелл запускается от пользователя, а не от www-data.
- В плане стабильности и анализа нагрузок.
Через top и аналогичные сможем увидеть, какой пользователь насколько грузит систему
- В плане работы с файлами
Стандартный umask 755, соответственно, файлы созданные из php будут иметь владельца www-data с разрешениями 755 и при работе из под пользователя, владельца сайта ( допустим через ftp ) пользователь будет не в состоянии изменять файл.
user = user group = user listen = /var/run/site.ru.sock listen.owner = user listen.group = www-data listen.mode = 0660
- В плане безопасности.
Dmi3yy
10.03.2016 09:30Теперь я знаю еще 1 причину почему люблю MODX Evo ;) он без оптимизации работает на уровне очень хорошо оптимизированного WP еще и на VPS))
Несомненно популярность WP и количество готовых решений и тем вне конкуренции но скорость работы крайне важный показатель.
Graid
10.03.2016 11:17+1ivashkevitch, оптимизацией пагинатора при большом кол-ве постов не занимались? Насколько видел очень узкое место из коробки.
jehy
10.03.2016 11:42+4Очень странный стресс тест. Вроде как вы выбираете базу данных по тому, когда у вас упадёт сервер, а потом при обновлении PHP максимальная нагрузка увеличивается со 150 до 200 пользователей. Возможно, потому что база у вас не является узким местом? И вообще, причина падения абсолютно непонятна. У вас закончилась память, своп, процессор, или что? Не вижу ни одного мониторинга, вижу желание потыкать пальчиком и посмотреть, вдруг что случится. Настройка wordpress под highload это весьма интересная тема, но если вы претендуете на полноценное исследование, что анализируйте и делайте выводы, а не "оно упало". Пока что на основании ваших опытов выводы можно сделать совершенно разные. Очень жду полноценного исследования, серьёзно.
Кстати, отдельной интересной темой является оптимизация wordpress под SSL и HTTP2 — тоже можно посмотреть. У меня по моей инсталляции создаётся ощущение, что возникают новые интересные грабли. А wordpress без SSL в наше время — это уже не очень хорошо.
К слову насчёт использования TCP\IP вместо сокетов — насколько я помню, ошибка при использовании сокетов возникает в случае, если исчерпан системный лимит на количество открытых файлов. Просто увеличьте его. Сокеты всё же немного быстрее.xXxSPYxXx
10.03.2016 14:23"К слову насчёт использования TCP\IP вместо сокетов — насколько я помню, ошибка при использовании сокетов возникает в случае, если исчерпан системный лимит на количество открытых файлов. Просто увеличьте его. Сокеты всё же немного быстрее."
Поделитесь подробным мануалом или ссылкой.jehy
10.03.2016 15:03+2Интересно — начал искать готовый развёрнутый ответ и не нашёл. Видимо, для части людей очевидно, для остальных — сложно.
В общем — сокеты быстрее, так как избавляют от TCP\IP оверхеда.
К сожалению, большинство "профессиональных" советов касательно настройки говорят "ну, тут можно покопаться в системных настройках для оптимизации сокетов, но боже мой — это так сложно — давайте лучше настроим по TCP\IP". И все радостно так делают. Вся поисковая выдача этим забита.
На самом деле, можно открыть хоть 600.000 коннектов по сокетам. Вы упираетесь только в максимальное количество открытых файловых дескрипторов, которое установлено у вас на системе.Его легко можно увеличить (то самое страшное действие, которого никто не делает).
Так что в итоге — да, сокеты быстрее, легче и секьюрнее, хотя выигрыш получается довольно небольшой. Для 90% пользователей проще настроить TCP\IP и забыть. Но если уж мы пишем серьёзную статью про оптимизацию, то говорить в ней о том, что нужно обязательно использовать TCP\IP — это некорректно. Кстати, это тоже вполне себе материал для следующей статьи на эту тему — нормально настроить сокеты и посмотреть, как это повлияет на производительность блога.
ivashkevitch
11.03.2016 10:34+1Только что решил проблему. net.core.somaxconn = 65535 в /etc/sysctl.conf
После перехода на сокеты сайт стал держать 276 юзера вместо 200, максимальное время ответа при этом сократилось до 7 секунд, а было 13.
В Debain 8 x64 по умолчанию это значение было 128. Обновил статью.
as3k
12.03.2016 09:17Убил ночь на эксперименты, арендовал VPS с такими же характеристиками, поднял apache+php7+varnish+marinadb, вообщем — все, что было в обоих статьях, результат оказался скорее плачевным, мой сайт на WP статику отдает на 2 секунды дольше, чем самый дешевый хостинг…
Связка работает, в какую сторону копать — не знаю. Перепробовал все, и сжатие, и без varnish, короче беда)ivashkevitch
12.03.2016 11:25Видимо, Varnish статику не кеширует и отдачей занимается Apache. Напишите в личку, посмотрим.
zm_llill
17.03.2016 13:28А зачем компилировали PHP 7, не проще было подключить репозиторий и с него установить? На Убунту я себе на тестовом сервере так и сделал, например.
antoo
А чтобы не грузить сервер плагинами и не использовать голый
<pre>
без подсветки, можно найти JS библиотеку, highlight.js, например.gibson_dev
А вдруг плагина то для WP и нету? И все, значит никак))))
Sannis
А что, WP настолько убог что не подволяет добавить пару строк HTML в шаблон?
gibson_dev
Ктож его спросит то при желании, просто большинство даже не буде насчет этого задумываться. А те кто задумываются WP не используют)
jehy
Неправда ваша. Есть много хороших проектов на вордпрессе, и много качественных плагинов. Принижать этот движок — всё равно, что говорить, что на PHP пишут только школьники.
Кстати, вот и плагин с highlight.js.