Тема высоконагруженных приложений у всех на слуху.
Я тоже решил вставить свои 2 копейки и поделиться опытом создания высоконагруженного приложения на инфраструктуре AWS. Сначала буду банален и повторю известные истины.
Существует 2 способа масштабирования приложения: 1) вертикальное масштабирование — увеличение производительности каждого компонента системы (процессора, оперативной памяти, других компонентов); 2) горизонтальный, когда несколько элементов соединены между собой, а система в целом состоит из множества вычислительных узлов, решающих общую задачу, тем самым повышая общую надежность и доступность системы.
А увеличение производительности достигается за счет добавления в систему дополнительных узлов.
Первый подход неплох, но есть существенный недостаток – ограниченность мощности одного вычислительного узла – невозможно бесконечно увеличивать частоту вычислительного ядра процессора и пропускную способность шины.
Поэтому горизонтальное масштабирование значительно превосходит своего вертикального брата, поскольку при недостатке производительности в систему можно добавить узел (или группу узлов).
Недавно мы в очередной раз убедились во всех преимуществах горизонтального масштабирования на практике: построили высоконадежный социальный сервис для любителей американского футбола, выдерживающий пиковую нагрузку в 200 000 запросов в минуту.
Поэтому я хочу рассказать о нашем опыте создания высокомасштабируемой системы на инфраструктуре Amazon Web Services.
Обычно архитектура веб-приложения выглядит следующим образом:
Рис.
1. Типичная архитектура веб-приложения.
Веб-сервер первым «встречает» пользователя; ему поручено возвращать статические ресурсы и передавать запросы приложению; Дальше эстафета передается приложению, где происходит вся бизнес-логика и взаимодействие с базой данных.
Чаще всего узкими местами системы являются код приложения и база данных, поэтому стоит рассмотреть возможность их распараллеливания.
Мы использовали: язык разработки и основная структура — Java 7 и остальные трикотажные изделия
сервер приложений — Tomcat 7
база данных — MongoDB (NoSQL)
система кэширования — memcached
Как это было, или через тернии к высокой нагрузке
Шаг первый: разделяй и властвуй
В первую очередь проведем максимальную оптимизацию кода и запросов к базе данных, а затем разделим приложение на несколько частей, в зависимости от характера решаемых ими задач.Переносим на отдельные сервера: сервер приложений; сервер базы данных; сервер со статическими ресурсами.
Каждый участник системы получает индивидуальный подход. Поэтому мы подбираем сервер с параметрами, наиболее подходящими по характеру решаемых задач.
Сервер приложений Приложение лучше всего подходит для сервера с наибольшим количеством процессорных ядер (для обслуживания большого количества одновременных пользователей).
Amazon предоставляет набор инстансов, оптимизированных для компьютера, которые лучше всего подходят для этих целей.
Сервер базы данных Какова работа базы данных? — Многочисленные операции дискового ввода-вывода (запись и чтение данных).
Здесь лучшим вариантом будет сервер с самым быстрым жестким диском (например, SSD).
Опять же, Amazon рад попробовать и предлагает нам Storage Optimized Instances, но подойдет и сервер из линейки General Purpose (large или xlarge), так как я планирую масштабировать их в будущем.
Статические ресурсы Статические ресурсы не требуют мощного процессора или большого объема оперативной памяти; здесь выбор падает на сервис статических ресурсов Amazon Simple Storage Service. Разделив приложение, я привел его к схеме, показанной на рис.
1. Плюсы разделения: каждый элемент системы работает на машине, максимально адаптированной к его потребностям; появляется возможность кластеризации базы данных; Вы можете отдельно протестировать разные элементы системы, чтобы найти слабые места.
Но само приложение по-прежнему не является кластеризуемым; также нет кэша или серверов репликации сеансов.
Шаг второй: эксперименты
Для точных экспериментов и тестирования производительности приложений нам понадобится одна или несколько машин с достаточно широким каналом.Эмулировать действия пользователя мы будем с помощью утилиты Apache Jmeter. Он хорош тем, что позволяет использовать в качестве тестовых данных реальные логи доступа с сервера или проксировать браузер и запускать несколько сотен параллельных потоков.
Шаг третий: Балансировка нагрузки
Итак, эксперименты показали, что полученной производительности всё равно не хватало, а сервер с приложением был загружен на 100% (слабым звеном был код разрабатываемого приложения).Я это параллелизирую.
В игру введены 2 новых элемента: балансировщик нагрузки сеансовый сервер Балансировка нагрузки Как оказалось, разработанное приложение не справляется с возложенной на него нагрузкой, поэтому нагрузку необходимо разделить между несколькими серверами.
В качестве балансировщика нагрузки можно создать еще один сервер с широким каналом и настроить специальное ПО (haproxy[], nginx[], DNS[]), но так как работа ведется в инфраструктуре Amazon, то сервис ELB (Elastic Load) существующий там будет использоваться Balancer).
Он очень прост в настройке и имеет хорошую производительность.
Первый шаг — клонировать существующую машину с приложением, чтобы затем добавить пару машин в балансировщик.
Клонирование выполняется с помощью Amazon AMI. ELB автоматически отслеживает состояние машин, добавленных в список рассылки; для этого приложение должно реализовать простой ресурс ping, который будет отвечать на запросы кодом 200; это то, что указано балансировщику.
Итак, настроив балансировщик на работу с двумя существующими серверами с приложением, я настраиваю DNS на работу через балансировщик.
Репликация сеанса Этот пункт можно пропустить, если приложение не требует дополнительной работы для HTTP-сессии или если реализуется простой REST-сервис.
В противном случае необходимо, чтобы все приложения, участвующие в балансировке, имели доступ к общему хранилищу сессий.
Для хранения сессий запускается еще один большой экземпляр и на нем настраивается ram memcached-хранилище.
Репликация сеанса возложена на модуль Tomkat: memcached-session-manager [5]
Теперь система выглядит следующим образом (статический сервер опущен для упрощения схемы):
Рис.
2. Вид системы после кластеризации приложений Результаты кластеризации приложений: повышенная надежность системы.
Даже после выхода из строя одного из серверов с приложением балансировщик исключает его из раздачи, и система продолжает функционировать; для увеличения производительности системы вам просто необходимо добавить вместе с приложением еще один вычислительный узел; добавив дополнительные узлы, мы смогли достичь пиковой производительности в 70 000 запросов в минуту.
С увеличением количества серверов, на которых работает приложение, увеличивается и нагрузка на базу данных, с которой она со временем не сможет справиться.
Необходимо снизить нагрузку на базу данных.
Шаг 4: оптимизация работы с базой данных
Итак, нагрузочное тестирование снова проводится с помощью Apache Jmeter, и на этот раз все сводится к производительности базы данных.При оптимизации работы с базой данных я использую два подхода: кэширование данных запроса и репликация базы данных для запросов на чтение.
Кэширование Основная идея кэширования заключается в том, чтобы хранить в оперативной памяти те данные, которые чаще всего запрашиваются, и при повторении запросов сначала проверять, находятся ли запрошенные данные в кеше, и только если их нет, делать запросы к базе данных, а затем сохраняя результаты запроса в кэше.
Для кэширования был развернут дополнительный сервер с настроенным memcached и достаточным объемом оперативной памяти.
Репликация базы данных Специфика нашего приложения предполагает больше чтения данных, чем записи.
Поэтому кластеризуем базу данных на чтение.
Здесь помогает механизм репликации базы данных.
Репликация в MongoDB устроена следующим образом: серверы баз данных делятся на главные и подчиненные, при этом прямая запись данных разрешена только на мастер, с которого данные синхронизируются со слейвами, а чтение разрешено как с мастера, так и слейвов.
Рис.
3 Кластеризация базы данных для чтения
Финал: 200 тыс.
запросов в минуту.
В результате наших усилий мы добились того, чего хотели: система обрабатывает 200 000 запросов в минуту.
Теги: #Amazon Web Services #Кластеризация #системы с высокой нагрузкой #Amazon Web Services
-
Несколько Советов По Использованию Wi-Fi
19 Oct, 24 -
Сервис По Ремонту Мобильных Телефонов
19 Oct, 24 -
Прием Платежей Онлайн.
19 Oct, 24