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

Внимание! Если размещение файла нарушает Ваши авторские права, то обязательно сообщите нам
52
При повторной попытке обратиться к странице списка также была
получена ошибка 504, так как прошло уже более миеуты и страница из кэша
удалилась.
Можно сделать вывод, что при такой архитектуре nginx практически ни
как не улучшает доступность приложения при сбое на бек-энде.
Единственный способ ее повысить – разворачивать дополнительные
контейнеры для слоя Apache.
3.2. Отказ от слоя web-сервера apache
3.2.1. Конфигурирование тестового приложения
Долгое время Apache считался единственным веб-сервером для сайтов,
написанных на РНР, поскольку его модуль mod_php позволяет без труда
интегрировать РНР непосредственно с веб-сервером. Но после включения
PHP-FPM в ядро РНР появилась альтернатива. PHP-FPM - это технология
исполнения РНР-скриптов под управлением FastCGI-сервера. Главный
процесс PHP-FPM берет на себя заботу о запуске рабочих процессов с учетом
нагрузки на сайт; при необходимости дочерние процессы перезапускаются.
Главный процесс взаимодействует с другими службами по протоколу
FastCGI. На текущий момент вся инфраструктура приложения выглядит
следующим образом:
Рисунок 14. Инфраструктура приложения.
Nginx используется для балансировки нагрузки между серверами бек-
энда и при этом копит на себе кэш статических файлов и динамических
страниц. Для статических файлов используется долгосрочный кэш, со
Nginx + кэш
Apache +
приложение + mysql
Apache +
приложение
mysql
53
временем он либо сильно вырастет, либо будет работать не так эффективно,
как ожидается – более старые фалы начнут вытесняться новыми, и запросы,
которые могли быть обслужены из кэша начнут направляться на бек-энд.
Нагрузка на приложение не очень высока, балансировщик в данном
случае вполне может совмещать в себе и роль веб-сервера. Если отказаться
от веб-сервера Apache и использовать вместо него nginx, можно будет
сделать более эффективную систему. В Nginx имеется модуль fastcgi,
позволяющий ему взаимодействовать с PHP-FPM или любым cgi-сервером.
FPM (FastCGI Process Manager, менеджер процессов FastCGI) является
альтернативной реализацией PHP FastCGI с несколькими дополнительными
возможностями обычно используемыми для высоконагруженных сайтов. В
последующем тексте речь будет идти о нем. Инфраструктура при этом
изменится следующим образом:
Рисунок 15. Инфраструктура после отказа от Apache.
Как было сказано ранее, nginx очень эффективно работает со
статическими файлами. Соответственно, вместо того, чтобы кэшировать их
(этот процесс требует дополнительных расходов на хранение кэша и работу
менеджера кэша), в этом случае их можно будет отдавать пользователю
прямо из каталога, где их хранит приложение, соответственно, избежать
дублирования и всегда иметь под рукой все файлы.
При этом продолжать использовать кэширование динамических
страниц так, как это было настроено в главе 2.
Nginx + кэш +
приложение
mysql
mysql
54
Nginx имеет модуль ngx_stream_core_module, позволяющий
использовать сервер как tcp прокси. Модуль stream находится на одном
уровне с модулем http. В нем можно также описывать группы серверов, по
которым распределяется нагрузка путем объявления блока upstream. Также в
нем указывается блок server, в котором определяются параметры обработки
сервером соединений.
Следовательно можно установить несколько серверов баз данных,
настроить между ними репликацию master-master (делается точно также как
master-slave, описанная во 2 главе, но настраивается на обоих серверах) и
распределять по ним запросы к БД[5].
Этой цели можно достигнуть, сконфигурировав секцию stream
следующим образом:
stream{
upstream @db{
server db1:3306;
server db2:3306;
}
server {
listen 3306;
proxy_pass @db;
}
}
Это простейший пример настройки без указания признаков, по
которым будут распределяться подключения, весов серверов и прочих
возможных настроек, но он будет работать.
Для использования такого сервера в приложении в качестве сервера БД
в настройках нужно будет указать имя nginx. Nginx будет принимать tcp
подключения к серверу баз данных и распределять их по серверам,
перечисленным в блоке upstream. Такая мера позволит увеличить
55
отказоустойчивость приложения, если один из серверов баз данных выйдет
из строя, другой сможет полностью заменить его собой.
Далее необходимо рассмотреть конкретный пример. Для отказа от
Apache нужно будет, прежде всего, передать веб-серверу nginx файлы сайта и
настроить правила переписывания в соответствии с директивами файлов
.htaccess. В нашем тестовом приложении правил переписывания нет, но об
этом стоит помнить.
Далее необходимо позаботиться о выполнении php скриптов. Для этого
будет использован сервер с PHP-FPM, а в конфигурационный файл nginx
внесены соответствующие изменения. Стек приложения станет выглядеть
следующим образом:
Рисунок 16. Стек приложения для nginx + php-fpm.
Для ознакомления приложение доступно по адресу
http://ssi.pictcut.com:8482
В приложении 9 приведен конфигурационный файл nginx. По
сравнению с предыдущим примером, в нем есть ряд важных изменений.
Главное – теперь для получения динамического содержимого веб-сервер
обращается к FastCGI серверу с PHP-FPM, соответственно, директивы
56
proxy_* теперь не используются. Веб сервер ищет статические файлы в своем
каталоге и, если не находит, обращается к FastCGI серверу.
Такая архитектура еще значительнее снижает нагрузку на бек-энд –
теперь он не должен возвращать вообще ни чего, кроме динамики.
Кэширование статических файлов не осуществляется, так как nginx и так
имеет их у себя, это способно экономить значительную часть дискового
пространства, занимаемого кэшем.
Также nginx сконфигурирован как tcp-прокси к серверам СУБД. В
блоке stream описана секция upstream с двумя серверами СУБД, между
которыми равномерно распределяются запросы к базе данных.
Логика кэширования в этом примере ни как не изменена. Как еще
можно использовать кэширование, применительно к тестовому и основному
приложениям, рассматриваемым в работе, будет сказано в следующем
разделе.
3.2.2. Анализ производительности при использовании SSI
Применим ту же методику сбора информации о событиях,
происходящих в системе, которая применялась для анализа
производительности в предыдущем примере.
Журнал доступа сервера будет выглядеть следующим образом:
Рисунок 17. Журналдоступа после отказа от Apache.
Как можно видеть, общая картина изменилась не сильно. Однако
можно посмотреть как происходит отдача статических файлов. Нажатие
клавиш Ctrl+F5 заставит перезагрузить все файлы с сервера. Фрагмент
журнала доступа приложения http://ssi.pictcut.com:8482/ со статическими
файлами выглядит следующим образом:
57
Рисунок 18. Получение статических файлов с nginx.
Для того, чтобы оценить картину в общем, имеет смысл получить
суммарное время загрузки (кроме последнего файла – это веб-страница).
Потребовалось 106 миллисекунд для загрузки всех статических файлов.
Для того, чтобы выяснить эффективность отдачи, необходимо
получить аналогичный фрагмент лога с предыдущего экземпляра
приложения, http://ssi.pictcut.com:8481/:
Рисунок 19. Запросы статических файлов с Apache.
Общее время в этом случае составило 124 миллисекунды. Для того,
чтобы иметь какую-то статистику, нужно повторить операцию хотя бы 5 раз
и вывести общее арифметическое. Для сервера с бек-эндом Apache
получение статических файлов с него каждый раз занимает ~128
миллисекунд. При получении статических файлов с nginx это время
сохраняется на уровне ~105 миллисекунд. Соответственно, эффективность
отдачи файлов напрямую с nginx в этом случае примерно на 20% выше.
Проверим, хорош ли результат 105 миллисекунд на загрузку файлов,
если загружать файлы не с бек-энда, а из кэша приложения
http://ssi.pictcut.com:8481/:
Рисунок 20. Получение статических файлов из кэша.
58
Общее время здесь настолько мало, что его даже невозможно
посчитать. Кэш nginx работает очень быстро.
Из описанного в разделе можно сделать вывод, что nginx очень
эффективно работает со статическими файлами, его использование в
качестве веб-сервера может ускорить работу, по сравнению с Apache.
Однако следует помнить, что кэш работает еще быстрее и, возможно,
для части часто запрашиваемых статических файлов следует держать
отдельную долгосрочную область, либо, если файлов много, установить
отдельный кэширующий сервер, например, на базе memcached[17].
3.2.3. Анализ доступности приложения
При тестировании доступности будет использована методика,
примененная в разделе 3.1.3. После обхода всех страниц приложения, чтобы
содержимое обновилось в кэше, необходимо выполнить переход в каталог
этого экземпляра стека приложения и выполнить команду:
sudo docker-compose pause fpm
После остановки fastcgi сервера страница со списком открылась. При
переходе на страницу задачи отобразился шаблон index.html, загрузились все
статические файлы, но содержимое задачи так и не появилось. В журнале
ошибок было получено сообщение:
2018/10/06 17:49:36 [error] 583#0: *1030 upstream timed out (110: Connection
timed out) while reading response header from upstream, client: 188.65.209.195,
server: ssi.abelov.com, request: "GET /index.html?show=table HTTP/1.1",
subrequest: "/render.php", upstream: "fastcgi://172.28.0.4:9000", host:
"ssi.pictcut.com:8482", referrer:
http://ssi.pictcut.com:8482/index.html?show=table
Через минуту список также перестал появляться на странице, так как
кэш SSI блока с ним был очищен.
Можно сделать вывод, что использование nginx в качестве веб-сервера
позволяет при сбое на fastcgi сервере продолжать исправно отдавать
59
статическое содержимое и страницы, находящиеся в долгосрочном кэше. В
разделе 3.3.3 будет продемонстрировано, как себя может вести приложение,
кэш которого хранится значительно дольше.
Так как в этом примере обсуждалась настройка репликации между
двумя серверами баз данных и настройка модуля stream на nginx для
балансировки нагрузки между ними, можно попробовать выключить один из
контейнеров с СУБД и посмотреть как приложение на это отреагирует.
Позволим серверу nginx определять работоспособность сервера mysql1,
поправив в секции stream директиву для mysql1: server mysql1:3306
max_fails=2 fail_timeout=60s; Это позволит nginx после двух
последовательных таймаутов в течение 60 секунд пометить сервер как
неработоспособный. Также необходимо в контекст server секции stream
добавить директиву error_log /var/nginx/stream.log; чтобы собирать
сообщения об ошибках во время работы модуля.
Выполним sudo docker-compose stop mysql1 в каталоге стека чтобы
имитировать отключение сервера СУБД. При перемещении по страницам
приложения один раз загрузилась пустая страница с сообщениями после 20
секундного ожидания, затем ожидания прекратились. В задаче 1 было
оставлено тестовое сообщение для проверки репликации. Сообщение
появилось на странице, запрос POST сработал.
В журнале ошибок появились следующие записи:
2018/10/06 18:25:42 [error] 79#79: *171 upstream timed out (110:
Connection timed out) while connecting to upstream, client: 172.28.0.4, server:
0.0.0.0:3306, upstream: "172.28.0.2:3306", bytes from/to client:0/0, bytes from/to
upstream:0/0
2018/10/06 18:25:52 [error] 79#79: *184 connect() failed (113: No route to
host) while connecting to upstream, client: 172.28.0.4, server: 0.0.0.0:3306,
upstream: "172.28.0.2:3306", bytes from/to client:0/0, bytes from/to upstream:0/0
60
2018/10/06 18:26:18 [error] 79#79: *202 connect() failed (113: No route to
host) while connecting to upstream, client: 172.28.0.4, server: 0.0.0.0:3306,
upstream: "172.28.0.2:3306", bytes from/to client:0/0, bytes from/to upstream:0/0
По записям видно, что в первый раз ответ от сервера ожидался в
течение какого-то времени, а в последующие разы сетевая ошибка не давала
направить на него запрос. Приложение продолжило работу, используя для
получения данных сервер mysql2.
Можно сделать вывод, что балансировка нагрузки между серверами
СУБД с помощью модуля stream имеет смысл, так как приложение
продолжило работать после отключения одного из серверов. В описанной
ситуации правильнее всего было бы изменить директиву, описывающую
upstream сервер mysql1 на server mysql1:3306 down; , перезагрузить
конфигурацию nginx командой nginx –s reload и разбираться с причинами
неработоспособности сервера СУБД.
В нашем случае причина недоступности известна, и нужно просто
выполнить команду sudo docker-compose start mysql1.
После запуска контейнера и подключения к его консоли команда show
slave status показала, что репликация исправна. Выполнение запроса select *
from messages where id=117; (номер тестового сообщения оказался 117) был
получен результат с тестовым сообщением:
| 117 | 1 | Test replication | 2018-10-06 18:54:14 |
Можно сделать вывод, что сервер вернул работоспособное состояние,
получил данные, которые были добавлены на другой сервер во время простоя
и полностью готов к обработке запросов.
3.3. Возможности, предоставляемые NGINX Plus
3.3.1. Очистка кэша с помощью nginx-cache-purge
Коммерческая редакция Nginx Plus имеет определенные преимущества
перед распространяемым бесплатно приложением. Среди них достаточно
61
много различных опций, позволяющих производить точную настройку. В
этом разделе хотелось бы упомянуть некоторые из них.
Во-первых, коммерческая редакция дает возможность использовать в
блоках upstream директиву least_time. В upstream некоммерческой версии
можно распределять подключения к серверам бек-энда по следующим
признакам:
least_conn – по количеству соединений с сервером
hash – хеш адреса страницы
ip_hash – хеш адреса клиента
По умолчанию, без указания директивы, будет использоваться
алгоритм round-robin.
least_time позволяет распределять подключения между серверами,
основываясь на времени отклика. Это значит, что в случае «торможения»
одного из серверов бек-энда, не зависимо от того, сколько сейчас на нем
находится соединений и откуда пришел запрос, он не будет использован для
обслуживания новых запросов. Это наиболее эффективный алгоритм
распределения[8].
Другой ценной особенностью nginx Plus является наличие возможности
удаления отдельных страниц из кэша с помощью директивы
proxy_cache_purge_method. Эту возможность следует рассмотреть подробно.
В предыдущих разделах говорилось, что пользователи испытывают
дискомфорт когда оставляют изменения на странице и не видят его сразу, а
только после перезагрузки страницы. Это не позволяет использовать
кэширование так, как хотелось бы для наиболее нагруженной части системы
страниц с сообщениями в задачах. Но, если вдуматься, это наиболее
стабильные страницы, имеющие в данном приложении только одну точку,
через которую меняется содержимое – использование метода POST для uri
данной страницы. Соответственно, можно хранить страницы задачи в кэше
неограниченное количество времени, если в нее не добавляются сообщения,
но сбрасывать кэш всех страниц задачи (для длинных задач используется

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

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