В прошлых уроках вы изучили стили архитектуры ПО. В этом уроке вы узнаете, как стили архитектуры помогают приложению справляться с увеличением числа пользователей, транзакций и серверов.
Даня
Я немного запутался.
Айгуль
Попробую распутать 😉
Даня
Получается, архитектору ПО и команде разработки нужно сразу знать, сколько у приложения с монолитной архитектурой будет пользователей?
Айгуль
Ну, это не очень реально, да и не нужно.
Даня
Но ведь дополнять и менять монолитное приложение сложно… Как тогда быть?
Айгуль
Для таких случаев есть масштабирование!
Масштабирование
Вы узнали из предыдущих уроков, что монолитные стили и, в частности, многослойная архитектура отлично подходят для начала разработки приложений. Ведь на первом этапе приложение, как правило, небольшое и простое.
По мере прибавления функций и пользователей монолиты становятся неудобны для проектирования, разработки и сопровождения. А ещё монолиты зачастую не справляются с увеличением количества запросов, объёма данных и сетевого трафика.
Поэтому архитектор ПО и команда разработки выбирают распределённые стили архитектуры, масштабируя монолитное приложение.
Масштабируемость (Scalability)** — это возможность приложения расти и обслуживать больше пользователей, данных, серверов, географических точек, транзакций, сетевого трафика, операций поиска и других сервисов без снижения его производительности и с сохранением корректности его работы.
Масштабный куб
Мартин Эббот (Martin Abbott) и Майкл Фишер (Michael Fisher) в своей книге «Искусство масштабирования» (The Art of Scalability) представили три подхода к масштабированию приложений в виде куба, расположенного в трёхмерной системе координат.
Три оси пересекаются в точке с координатами x = 0, y = 0 и z = 0. В этой точке приложение монолитно и развёртывается на единственном сервере. Его можно масштабировать с помощью более мощного и быстрого аппаратного обеспечения, но только до определённого предела. Кроме того, такое приложение сложно разрабатывать.
Поэтому его нужно масштабировать с помощью одного, двух или сразу трёх подходов:
Копирование приложения (ось X)
Создание копий приложения и равномерное распределение запросов между ними.
Разбивка по функциям (ось Y)
Разделение приложения на сервисы, каждый из которых выполняет только часть функций.
Разбивка по данным (ось Z)
Создание копий приложения, каждая из которых хранит только определённое подмножество данных (партицию), и распределение запросов между ними на основании значений их атрибутов.
Копирование приложения (ось X)
Масштабирование по оси X используется для увеличения производительности приложений с монолитной архитектурой.
При таком масштабировании одно приложение дублируется несколько раз. Каждая копия приложения развёртывается, как правило, на отдельном сервере — физическом или виртуальном. Она работает независимо от других копий.
Копии приложения называют экземплярами или инстансами (Instances) приложения. Они представляют собой частный случай реализации определённого приложения.
Между клиентом и серверами с экземплярами добавляют балансировщик нагрузки (Load Balancer). Он представляет собой программу, которая равномерно распределяет запросы клиента между действующими копиями приложения, чтобы оптимизировать их работу и сократить время обработки запроса.
Балансировщик последовательно перенаправляет полученные от клиента запросы сначала экземпляру 1, потом экземпляру 2, затем экземпляру 3, снова экземпляру 1 и так далее.
Чтобы лучше понять, как работают все три подхода к масштабированию, рассмотрим их на примере производства автомобилей. Как приложение выполняет запросы пользователя, так и автомобильные заводы выполняют заказы клиентов на машины.
Если завод «монолитный», он собирает все виды автомобилей: внедорожник, кабриолет и седан. Если клиентов станет слишком много, придётся построить ещё один завод, а потом ещё один, чтобы справляться с нагрузкой и не заставлять пользователей долго ждать своего автомобиля.
Как только заводов становится больше одного, появляется необходимость в управляющей структуре, которая будет распределять заказы между заводами и следить, чтобы они были загружены равномерно. Управление в данном случае выполняет роль «балансировщика» заказов.
Разбивка по данным (ось Z)
Масштабирование по оси Z решает задачи по обработке возросшего количества запросов и данных.
При таком масштабировании монолитное приложение тоже «клонируют», но, в отличие от масштабирования по оси X, каждый получившийся экземпляр отвечает только за подмножество данных исходного приложения (партицию).
В данном случае запросы между экземплярами распределяет маршрутизатор (Router). Он представляет собой программу, которая перенаправляет запросы от клиента экземплярам приложения по определённым правилам.
Маршрутизатор — это специализированное ПО, передающее (маршрутизирующее) запрос между серверами на основании заранее установленных правил маршрутизации.
Правила маршрутизации указывают на то, какому экземпляру нужно перенаправить запрос клиента, на основании значений одного или нескольких атрибутов запроса. Каждому экземпляру приложения будет соответствовать свой диапазон значений.
В качестве правил маршрутизации могут быть выбраны значения идентификаторов, имён сущностей.
В примере с заводами масштабирование по оси Z предполагает, что каждый завод собирает только определённый тип автомобиля: внедорожник, кабриолет или седан. При оформлении заказа отдел работы с заказами (маршрутизатор) обязательно запрашивает параметр: необходимый тип автомобиля. В зависимости от выбранного типа, заказ пользователя маршрутизируется на завод, производящий этот тип автомобилей.
Разбивка по функциям (ось Y)
Масштабирование по осям X и Z повышает производительность и отказоустойчивость приложения. Но, как вы уже знаете из урока про монолитную архитектуру, у этого архитектурного стиля есть существенные недостатки. По мере развития монолитного приложения возрастает сложность его разработки и сопровождения, потому что программный код становится слишком объёмным для понимания разработчиками.
Для решения проблемы используется масштабирование по оси Y — декомпозиция по функциям. При таком подходе монолитное приложение разбивают на набор сервисов.
Как вы помните, сервис — это небольшая программа, которая реализует ограниченный перечень функций, например управление заказами, клиентами и так далее. Сервисы — это результат разделения архитектуры ПО по предметным областям.
Сервис, который масштабируется по оси Y, можно также в дальнейшем масштабировать по осям X и Z.
Чтобы масштабировать завод по производству автомобилей по оси Y, нужно разделить один большой завод на более мелкие производства — цеха, отвечающие за отдельные части машины: руль, колёса, кузов. А ещё нужны специальные цеха, которые будут собирать автомобиль из деталей.
Эти цеха могут находиться в разных городах и странах. Если определённых деталей требуется больше, чем может произвести один цех, можно построить ещё один цех.
Такая организация производства делает его более устойчивым к сбоям поставок. Например, если в цехе по производству кузова кабриолета произойдёт авария и производство остановится, это не повлияет на поставки внедорожников и седанов.
Ниже приведены примеры масштабирования приложений. Выберите из списка подход к масштабированию, который был использован в каждом примере.
После удачной рекламной кампании приложение для продажи зоотоваров «Кошки и вараны» перестало справляться с количеством посещений сайта. Команда разработки приняла решение развернуть на сервере дополнительный экземпляр приложения.
Копирование приложения (ось X)
Добавив дополнительный экземпляр, администратор использовал горизонтальное масштабирование. Копия позволит распределить возросшее количество запросов между экземплярами приложения.
Из-за роста количества пользователей команда разработки приложения для просмотра фильмов «Ещё одну серию» решила пересмотреть его архитектуру и разбить на три сервиса: сервис авторизации пользователей, сервис индивидуальных рекомендаций, сервис истории просмотров пользователей.
Разбивка по функциям (ось Y)
В данном случае монолитное приложение разбили на несколько сервисов, сфокусированных на выполнении одной функции. Это декомпозиция по функциям, то есть масштабирование по оси Y.
После изменения архитектуры приложения для просмотра фильмов «Ещё одну серию» его пользователи стали жаловаться на слишком медленную авторизацию. В результате технический директор решил развернуть несколько экземпляров сервиса авторизации, каждый из которых будет обрабатывать запросы в зависимости от того, с какой буквы начинается логин пользователя. Всего было выделено четыре диапазона: A-D, E-H, I-O, P-Z.
Разбивка по данным (ось Z)
В данном случае экземпляр отвечает за часть обрабатываемых данных, а в качестве правил маршрутизации используется имя пользователя. Это разделение данных, то есть масштабирование по оси Z.
Подведём итоги
Масштабируемость — это возможность приложения расти и обслуживать больше пользователей, данных, серверов, географических точек, транзакций, сетевого трафика, операций поиска и других сервисов без снижения его производительности и с сохранением корректности его работы.
Три подхода к масштабированию приложений можно представить в виде куба, расположенного в трёхмерной системе координат. Эту модель называют масштабным кубом.
В точке пересечения трёх осей приложение монолитно и развёртывается на единственном сервере. В соответствии с масштабным кубом, такое приложение можно масштабировать с помощью одного, двух или сразу трёх подходов:
Копирование приложения (ось X)
Создание копий (экземпляров) приложения и равномерное распределение запросов между ними.
Разбивка по функциям (ось Y)
Разделение приложения на сервисы, каждый из которых выполняет только часть функций.
Разбивка по данным (ось Z)
Создание копий приложения, каждая из которых хранит только определённое подмножество данных, и распределение запросов между ними на основании значений их атрибутов.
Используя масштабный куб, архитектор ПО и команда разработки могут принимать решения об изменениях, которые нужно внести в архитектуру ПО.