- PVSM.RU - https://www.pvsm.ru -
Тема высоконагруженных приложений у всех на слуху. Тоже решил вставить свои 5 копеек и поделиться опытом создания высоконагруженного приложения на инфраструктуре AWS.
Сначала, буду банален и повторю всем известные истины. Есть 2 пути масштабирования приложения:
1) вертикальное масштабирование — это увеличение производительности каждого компонента системы (процессор, оперативная память, прочие компоненты);
2) горизонтальное, когда соединяют несколько элементов воедино, а система в целом состоит из множества вычислительных узлов, решающих общую задачу, тем самым увеличивая общую надежность и доступность системы. А увеличение производительности достигается добавлением в систему дополнительных узлов.
Первый подход неплох, но есть существенный минус — ограниченность мощности одного вычислительного узла — невозможно бесконечно увеличивать частоту вычислительного ядра процессора и пропускную способность шины.
Поэтому горизонтальное масштабирование значительно выигрывает у своего вертикального брата, ведь при недостатке производительности можно добавить в систему узел (или группу узлов).
Недавно мы в очередной раз постигали все прелести горизонтального масштабирования на практике: строили высоконадежный социальный сервис для болельщиков американского футбола, выдерживающий пиковую нагрузку в 200 000 запросов в минуту. Поэтому хочу рассказать о нашем опыте создания высокомасштабируемой системы на инфраструктуре Amazon Web Services.
Обычно, архитектура веб приложения выглядит следующим образом:
Рис. 1. Типичная архитектура веб приложения
Чаще всего узкими местами системы являются код приложения и база данных, следовательно, стоит предусмотреть возможности их распараллеливания. Мы использовали:
Первым делом, проведем максимальную оптимизацию кода и запросов к БД, а затем разделим аппликацию на несколько частей, по характеру выполняемых ими задач. На отдельные серверы выносим:
Каждому участнику системы — индивидуальный подход. Поэтому выбираем сервер с наиболее подходящими под характер решаемых задач параметрами.
Приложению лучше всего подойдет сервер с наибольшим числом процессорных ядер (для обслуживания большого количества параллельно работающих пользователей). Amazon предоставляет набор Computer Optimized Instances, которые наилучшим образом подходят под данные цели.
Что есть работа БД? — Многочисленные дисковые операции ввода-вывода (запись и чтение данных). Тут самым лучшим вариантом будет сервер с наиболее быстрым жестким диском (например ССД). И снова Амазон рад стараться и предлагает нам Storage Optimized Instances, но также подойдет и сервер из линейки General Purpose (large or xlarge), так как в дальнейшем я собираюсь их масштабировать.
Для статических ресурсов не нужен ни мощный процессор, ни большой объем оперативной памяти, тут выбор падает на сервис статических ресурсов Amazon Simple Storage Service.
Разделив приложение, я привел его к схеме, отображенной на рис. 1.
Плюсы разделения:
Но само приложение по-прежнему осталось некластеризуемо, также отсутствуют сервера кэша и репликации сессий.
Для точных экспериментов и тестирования производительности апликации нам потребуется одна или более машин с достаточно широким каналом. Действия пользователя будем эмулировать при помощи утилиты Apache Jmeter. Он хорош тем, что позволяет в качестве тестовых данных использовать реальные access логи с сервера, либо же проксировать браузер и запускать на выполнение несколько сотен параллельных потоков.
Итак, эксперименты показали, что полученной производительности по-прежнему не хватает, а сервер с приложением был нагружен на 100% (слабым звеном оказался код разработанного приложения). Распараллеливаю. В игру вводятся 2 новых элемента:
Как выяснилось, разработанное приложение не справляется с возложенной на него нагрузкой, следовательно, нагрузку нужно разделить между несколькими серверами.
В качестве балансировщика нагрузки можно завести еще один сервер с широким каналом и настроить специальное программное обеспечение (haproxy[], nginx[], DNS[]), но так как производится работа в инфраструктуре Амазон, то будет использован существующий там сервис ELB (Elastic Load Balancer). Он очень прост в настройке и имеет неплохие показатели производительности. Первым делом необходимо клонировать существующую машину с приложением для последующего добавления пары машин в балансировищик. Клонирование осуществляется средствами Amazon AMI. ELB автоматически осуществляет контроль за состоянием добавленных в рассылку машин, для этого в приложении следует реализовать простейший пинг ресурс, который будет отвечать 200 кодом на запросы, именно его указывают балансировщику.
Итак, после конфигурирации балансировщика на работу с уже двумя существующими серверами с приложением, настраиваю днс на работу через балансировщик.
Этот пункт можно пропускать, если в приложении не возлагается на хттп сессии дополнительной работы, или же если реализуется простой REST сервис. В противном случае, необходимо, чтобы все приложения, участвующие в балансировке, имели доступ к общему хранилищу сессий. Для хранения сессий запускается еще один large instance и настраивается на нем ram memcached хранилище. Репликация сессий возлагается на модуль к томкату: memcached-session-manager [5]
Теперь система выглядит следующим образом (сервер статики опущен для упрощения схемы):
Рис. 2. Вид системы после кластеризации приложения
Результаты кластеризации приложения:
При возрастающем числе серверов c приложением также возрастает и нагрузка на базу данных, с которой она с течением времени справиться не сможет. Необходимо снижать нагрузку на БД.
Итак, снова проводится нагрузочное тестирование с Apache Jmeter и на этот раз все упирается в производительность базы данных. Оптимизируя работу с бд, применяю два подхода: кэширование данных запросов и репликация базы для read запросов.
Основная идея кэшированя состоит в том, чтобы те данные, что запрашиваются чаще всего запоминать в RAM и при повторении запросов первым делом проверять, есть ли запрашиваемые данные в кэше, и только в случае их отсутствия производить запросы к базе данных, с последующим помещением результатов запросов в кэш. Для кэширования был развернут дополнительный сервер с настроенным memcached и достаточным объемом оперативной памяти.
Специфика нашего приложения предполагает в большей степени чтение данных, нежели запись.
Поэтому кластеризуем БД на чтение. Тут помогает механизм репликации базы данных. Репликация в MongoDB устроена следующим образом: сервера БД делятся на мастеров и слейвов, при этом прямая запись данных разрешена только в мастера, с него уже и происходит синхронизация данных на слейвы, а чтение разрешено как с мастера, так и со слейвов.
Рис. 3 Кластеризация БД для чтения
В результате трудов мы достигли желаемого: система обрабатывает 200 000 запросов в минуту.
Автор: Dritar
Источник [1]
Сайт-источник PVSM.RU: https://www.pvsm.ru
Путь до страницы источника: https://www.pvsm.ru/amazon-web-services/49715
Ссылки в тексте:
[1] Источник: http://habrahabr.ru/post/202280/
Нажмите здесь для печати.