Диплом: Повышение производительности веб-приложения за счет обратного проксирования с помощью NGINX

Внимание! Если размещение файла нарушает Ваши авторские права, то обязательно сообщите нам
32
USE RMS;
FLUSH ALL TABLES WITH READ LOCK;
exit
mysqldump -u root -p RMS > dump.sql
Установлена блокировка чтения на все таблицы в базе для того, чтобы
сделать дамп и предотвратить изменение базы в это время. Далее:
mysql -u root –p
GRANT REPLICATION SLAVE ON *.* TO ‘slave_user’@’%’
IDENTIFIED BY ‘pass’;
FLUSH PRIVILEGES;
START MASTER;
SHOW MASTER STATUS;
UNLOCK TABLES;
Exit
Запущена запись бинарного лога, снята блокировка чтения и
просмотрен статус мастера:
Рисунок 3. Статус ведущего сервера MySQL.
Крайне важно имя файла лога и значение Position – оно понадобится
при запуске слейва.
Далее необходимо переместиться в консоль контейнера db:
mysql -u root -p RMS < dump.sql
mysql -u root –p
CHANGE MASTER TO MASTER_HOST=192.168.16.8,
MASTER_USER='slave_user', MASTER_PASSWORD=’pass’,
MASTER_LOG_POS=140268516, MASTER_LOG_FILE=RMS-mysql-
bin.000001;
33
START SLAVE;
SHOW SLAVE STATUS\G
В пустую базу RMS загружен дамп рабочей базы, запущен
подчиненный сервер репликации, настроено чтение бинарного лога и
проверен его статус:
Рисунок 4. Статус репликации ведомого сервера MySQL.
34
О правильном запуске и исправном функционировании
свидетельствуют строки
Slave_IO_Running: Yes
Slave_SQL_Running: Yes
Из вывода команды SHOW SLAVE STATUS. Если они не такие,
присутствуют ошибки и репликация не идет.
На этом этапе работы получена полноценная реплика продуктивного
приложения, уже способная самостоятельно (путем обращения к контейнеру
web на порт 8088) обслуживать запросы пользователей и поддерживающаяся
в актуальном состоянии за счет репликации базы данных. Далее необходимо
настроить nginx так, чтобы запросы правильно распределялись по серверам и
создавался кэш.
Для синхронизации сессий на двух серверах было решено использовать
memcache[17]. Сервер с memcache уже имеется в сети, достаточно было
изменить настройки в конфигурационных файлах php на обоих серверах:
session.save_handler = memcache
session.save_path = "tcp://192.168.16.188:11211"
2.2.3. Настройка NGINX
Полный текст конфигурационного файла приведен в приложении 2. В
этом разделе будут рассмотрены некоторые особенности и приемы – почему
сделано именно так.
В первую очередь, необходимо сразу отметить один важный момент –
сайт работает по протоколу https и терминирование ssl будет осуществляться
на nginx, на сервера бек-энда запросы будут отправляться по http.
О том, что сайт использует https говорит наличие опции ssl в директиве
listen контекста server. За работу с ssl соединениями в конфигурационном
файле отвечают директивы ssl_certificate, ssl_certificate_key,
ssl_prefer_server_ciphers, ssl_protocols, ssl_ciphers и ssl_session_cache. Из их
названий ясен смысл, следует рассмотреть директиву ssl_session_cache. Она
35
объявляет разделяемую между рабочими процессами область в памяти, таким
образом, если клиент установил соединение с одним из рабочих процессов,
другим при обслуживании его запросов этого делать не нужно. Это позволяет
экономить ресурсы сервера.
В секции http нужно отметить наличие следующих директив,
оптимизирующих работу со статическими файлами, в том числе из кэша:
tcp_nopush on;
tcp_nodelay on;
sendfile on;
В nginx если включен sendfile, позволяющий отправлять файлы
напрямую, tcp_nopush не дает отправить не заполненный пакет клиенту. При
этом когда вызов senfile прекращается, начинает работать tcp_nodelay,
предписывающая отправлять пакеты любого размера без задержек[2]. Это
оптимизирует работу сервера с сетью.
Далее объявлены три области кэша:
1. Fast_cache предназначен для кэширования динамических страниц.
Страницы хранятся в ней минуту, затем удаляются. Это небольшая и
быстрая область, use_temp_path=off предотвращает запись файлов
на диск. В локации, отвечающей за кэширование динамических
страниц, proxy_cache_valid any 1s; указывает, что кэш валиден в
течение 1 секунды. Это значит, что кэшированная страница
практически сразу становится просроченной. Но директивы
proxy_cache_use_stale updating error timeout; и
proxy_cache_background_update on; позволяют вернуть пользователю
страницу из кэша, пока она не удалена, при этом запустив фоновое
обновление. Если пользователь читает список, переходит в какую-то
задачу или к другому списку, и в течение минуты возвращается
обратно (сотрудник что-то ищет – это реальная ситуация), страница
возвращается ему из кэша. При этом сами задачи не кэшируются –
если не сбрасывать страницу из кэша после добавления сообщения,
36
пользователь не видит свое сообщение до следующего обновления
страницы. К этому вопросу вернусь в главе 3. Так как страницы
уникальны для пользователей, в качестве ключа, помимо url с
аргументами, используется еще однозначно идентифицирующий
пользователя куки.
2. Mid_cache – эта область кэша использована для кэширования
страниц, заканчивающихся расширением htm или html. В
исследуемой системе это страницы различных документаций. Этот
кэш хранится в течение 24 часов, при этом через 60 минут считается
устаревшим, но страницы могут быть возвращены благодаря
использованию описанного выше механизма. Директива
proxy_cache_revalidate позволяет серверу проводить ревалидацию
кэша – на бек-энд отправляется запрос, содержащий заголовок If-
Modified-Since. Если страница была изменена с указанного момента,
возвращается новая версия, иначе – ответ с кодом 304 – not-modified
и кэш продолжает храниться, пока не будет удален через 24 часа.
Чтобы это работало, нужно включить использование http 1.1 для
связи прокси с бек-эндом с помощью proxy_http_version 1.1;
3. Slow_cache – наиболее интересная область кэша. Она предназначена
для хранения статических файлов в течение 160 дней. Валидность
кэша – 30 дней, ревалидация происходит с помощью описанного
выше механизма. В этой же области кэшируются статические
файлы, которые возвращаются в ответ на GET запросы к скрипту
index.php. Эта область кэша – реально разделяемый между
пользователями кэш, снижающий количество запросов к apache и к
БД.
Так как статические файлы не переносились в контейнер, запросы к
ним передаются на старый сервер 192.168.16.8. Также на старый сервер
передаются запросы POST, меняющие содержимое базы данных и к особой
странице ascetic, работа которой в контейнерной версии не была налажена.
37
Это делается с помощью директивы map, с помощью которой присваивается
значение переменной, от которой зависит в какую из локаций будет
направлен запрос:
map $request $ret_val {
~POST @nocache;
~ascetic @nocache;
~upload @slowcache;
default @fastcache;
}
Записи, начинающиеся со знака ~ сообщают серверу, что нужно
проверить наличие слова в переменной $request, содержащей весь запрос
пользователя, и при совпадении назначить переменной $ret_val значение из
правого столбца.
Внутренняя локация @nocache предназначена для работы со старым
сервером напрямую, без кэша. Она достаточно проста и содержит только
описание файла журнала, куда нужно записывать обращения к этой локации,
назначение заголовков хоста и клиентского ip, добавление адреса nginx в
заголовок со списком адресов прокси-серверов и передачу запроса на бекэнд.
Локация @slowcache предназначена для обработки запросов к
статическим файлам. Принципы кэширования в ней описаны выше, в
описании кэшей.
Локация @fastcache предназначена для кэширования динамических
страниц. Следует отметить, что содержимое страниц с сообщениями задачи
кэшироваться не должно. Идентифицировать такие страницы можно по
наличию аргумента tn. Блок
if ($arg_tn){
set $Bypass 1;
}
38
Определяет наличие этого аргумента в url и устанавливает переменную
Bypass. Директива proxy_cache_bypass отправляет запрос напрямую к бек-
энду, минуя кэш (червоточина в кэше), если переменная $bypass установлена.
GET-запросы распределяются между новым и старым сервером на
основе ip_hash. Эта директива позволяет выбирать один из серверов бек-энда
в блоке upstream, основываясь на ip адресе клиента и в последствии
отправлять запросы от этого клиента на него же[12,15].
Распределение по локациям происходит в основной локации «/» с
помощью механизма страниц ошибок. Возвращается нестандартный код
ответа 418, страница ошибки которого определена в директиве error_page 418
= $ret_val; Знак «=» позволяет в последствии заменить код ответа на тот,
который вернет локация, определенная в $ret_val. Для того, чтобы в локации,
куда будет перенаправлен запрос, он корректно был передан на сервер бек-
энда, в контексте сервера указана директива recursive_error_pages on;
2.3. Анализ результатов внедрения
2.3.1. Анализ журналов доступа
Кэширование статики улучшило работу приложения. Благодаря зоне с
быстрым кэшем часть запросов на обновление страницы или возврат к
списку обслуживаются из кэша. Это значительно снизило время получения
пользователем запрашиваемой страницы, которая может быть немного
устаревшей. В то же время страницы, которые должны быть актуальны,
доставляются напрямую с бек-энда.
Эффективность работы кэша можно отследить по журналам доступа.
Для этих целей специально написана небольшая программа на awk, полный
текст которой представлен в приложении 4. Она сортирует запрашиваемые
страницы с кодом ответа 200 (успешное выполнение запроса) по url, типу
запроса и наличию в кэше, подсчитывает их количество и среднее время
отдачи. Конечный список отсортирован по количеству запросов к странице.
Отдельно считаются страницы с $upstream_cache_status равным MISS с
39
нулевым и ненулевым временем. Если время равно нулю, значит была взята
и отправлена устаревшая версия из кэша (proxy_cache_use_stale) и
параллельно запущено фоновое обновление
(proxy_cache_background_update). Если же значение не нулевое, страница
была сначала получена с бек-энда. Локация @midcache не анализируется
потому что запросов к этим страницам ничтожно мало. Статистика работы
для разных локаций за рабочий день c топ 20 запросов выглядит следующим
образом:
Рисунок 5. Статистика использования локации @nocache.
Рисунок 6. Статистика использования локации @fastcache.
40
Рисунок 7. Статистика использования локации @slowcache.
Полученные списки необходимо нормализовать – удалить
дублирующиеся запросы и те, которых не должно быть в зоне, они могли
оказаться там во время отладки конфигурации.
Рассмотрим пример на основе обращений к страницам, попадающим в
@fastcache. Если взять топ запрашиваемых страниц для каждой кэшируемой
локации и попробовать получить их с бек-энда напрямую, можно узнать
время их загрузки.
Для @fastcache нормализованный список получился таким (время
указано в секундах):
/rms/index.php?ac=qe 6,58
/rms/index.php?ac=qe&ct=0 16,08
/rms/index.php?ac=qe&te=0&ct=0&T2=1 12,45
/rms/index.php?ac=qe&aa=Wr&tn=71505&RE=42 0,374
/rms/index.php?ac=qe&te=0&ct=0&T2=2 0,215
/rms/index.php?ac=qe&te=0&ct=0&T2=8 28,48
Соответственно, выигрыш в производительности работы приложения
для каждой из страниц можно посчитать, умножив количество страниц со
значениями $upstream_cache_status HIT и MISS с нулеrвым временем на
время получения страницы напрямую с бек-энда. Совокупная статистика
будет выглядеть следующим образом:
Рисунок 8. Разница во времени получения страниц напрямую и из
кэша.
914 секунд - это то время, которое пользователь мог потратить, просто
ожидая появления страниц. То же самое время сервер бек-энда был бы занят
41
вычислениями. С учетом того, что рассматривался достаточно сжатый
период времени и работа приложения через обратный прокси-сервер еще
находится на этапе тестирования, разница может стать значительно больше.
Можно сделать вывод, что обдуманное применение кэширования там,
где это востребовано, способно значительно повысить быстродействие
приложения без вмешательства в его код и архитектуру.
2.3.2. Анализ нагрузки на бек-энд
Для того чтобы измерить нагрузку на Apache необходимо посчитать
количество запросов, обслуживание которых nginx взял на себя. Из
статистики предыдущего раздела видно, что запросов к статическим файлам
точно не попало на бек-энд. Соответственно, для их обслуживания не
выделялась память, не устанавливалось соединение, вообще не
производилось ни каких операций на бек-энде.
Также стоит отметить, что благодаря обслуживанию почти всех
запросов GET (кроме страницы ascetic и запросов на получение файлов,
которые после первого раза попадают в кэш), наличие блокировок таблиц БД
на чтение ни как не сказывается на запись информации в основную базу
данных на мастере запросами POST. Это значит, что не зависимо от того,
кто, что и в каком объеме сейчас читает (реально в системе есть отчеты,
способные на некоторое время заблокировать всю базу на время, достаточное
для получения таймаута при попытке к ней обратиться), информация будет
записана, а затем механизмом репликации передана на слейв-сервер.
2.3.3. Ошибки, через которые пришлось пройти
В этом разделе хотелось бы указать на ошибки, допущенные при
конфигурировании сервера.
Прежде всего, необходимо отметить, что кэширование динамических
страниц может разгрузить сервер но осложнить работу пользователю. Когда
для страниц задач было включено кэширование, пользователь мог написать

Смотрите также:

«Психологическое сопровождение персонала в организации на примере ООО «Крокус»
Cовершенствование деловой оценки персонала в организации (на примере ООО "Даймонд кейтеринг развитие")
PR-коммуникации в сфере общественного питания (на примере кафе-кондитерской «Cream Cheese»)
SMM как средство повышения эффективности работы учреждений социокультурной сферы (на примере Малого театра)
Value-based education: ценности в системе образования и способы их реализации на уроке английского языка. Опыт Европейских стран
Work-life balance подход в управлении рабочим временем молодых сотрудников (на примере ООО «МГТ-сервис»)
Актуализация контента, отражающего концепцию «диалога культур», при освоении английского языка взрослыми обучающимися
Актуализация приемов инсценирования и драматизации в рамках интерактивной модели обучения английскому языку в старших классах
Актуальные подходы в построении внутреннего pr строительной компании (на примере ООО "Ренессанспроект")
Анализ деловой активности и экономической эффективности деятельности организации (на примере АО «СГ-Транс»)