Вертикальное и горизонтальное масштабирование систем. Горизонтальное масштабирование. Проблемы и пути решения

|

Постоянно растущее количество посетителей сайта – всегда большое достижение для разработчиков и администраторов. Конечно, за исключением тех ситуаций, когда трафик увеличивается настолько, что выводит из строя веб-сервер или другое ПО. Постоянные перебои работы сайта всегда очень дорого обходятся компании.

Однако это поправимо. И если сейчас вы подумали о масштабировании – вы на правильном пути.

В двух словах, масштабируемость – это способность системы обрабатывать большой объем трафика и приспособляться к его росту, сохраняя при этом необходимый UX. Существует два метода масштабирования:

  • Вертикальное (также называется scaling up): увеличение системных ресурсов, например, добавление памяти и вычислительной мощности. Этот метод позволяет быстро устранить проблемы с обработкой трафика, но его ресурсы могут быстро себя исчерпать.
  • Горизонтальное (или scaling out): добавление серверов в кластер. Рассмотрим этот метод подробнее.

Что такое горизонтальное масштабирование?

Проще говоря, кластер – это группа серверов. Балансировщик нагрузки – это сервер, распределяющий рабочую нагрузку между серверами в кластере. В любой момент в существующий кластер можно добавить веб-сервер для обработки большего объёма трафика. В этом и есть суть горизонтального масштабирования.

Балансировщик нагрузки отвечает только за то, какой сервер из кластера будет обрабатывать полученный запрос. в основном, он работает как обратный прокси-сервер.

Горизонтальное масштабирование – несомненно, более надёжный метод увеличения производительности приложения, однако оно сложнее в настройке, чем вертикальное масштабирование. Главная и самая сложная задача в этом случае – постоянно поддерживать все ноды приложения обновленными и синхронизированными. Предположим, пользователь А отправляет запрос сайту mydomain.com, после чего балансировщик передаёт запрос на сервер 1. Тогда запрос пользователя Б будет обрабатываться сервером 2.

Что произойдёт, если пользователь А внесёт изменения в приложение (например, выгрузит какой-нибудь файл или обновит содержимое БД)? Как передать это изменение остальным серверам кластера?

Ответ на эти и другие вопросы можно найти в этой статье.

Разделение серверов

Подготовка системы к масштабированию требует разделения серверов; при этом очень важно, чтобы серверы с меньшим объёмом ресурсов имели меньше обязанностей, чем более объёмные серверы. Кроме того, разделение приложения на такие «части» позволит быстро определить его критические элементы.

Предположим, у вас есть PHP-приложение, позволяющее проходить аутентификацию и выкладывать фотографии. Приложение основано на стеке LAMP. Фотографии сохраняются на диске, а ссылки на них – в базе данных. Задача здесь заключается в поддержке синхронизации между несколькими серверами приложений, которые совместно используют эти данные (загруженные файлы и сессии пользователя).

Для масштабирования этого приложения нужно разделить веб-сервер и сервер БД. Таким образом в кластере появятся ноды, которые совместно используют сервер БД. Это увеличит производительность приложения, снизив нагрузку на веб-сервер.

В дальнейшем можно настроить балансировку нагрузки; об этом можно прочесть в руководстве « »

Сессионная согласованность

Разделив веб-сервер и базу данных, нужно сосредоточиться на обработке пользовательских сессий.

Реляционные базы данных и сетевые файловые системы

Данные сессий часто хранят в реляционных базах данных (таких как MySQL), потому что это такие базы легко настроить.

Однако это решение не самое надёжное, потому что в таком случае увеличивается нагрузка. Сервер должен вносить в БД каждую операцию чтения и записи для каждого отдельного запроса, и в случае резкого увеличения трафика база данных, как правило, отказывает раньше других компонентов.

Сетевые файловые системы – ещё один простой способ хранения данных; при этом не требуется вносить изменения в базу исходных текстов, однако сетевые системы очень медленно обрабатывают I/O операции, а это может оказать негативное влияние на производительность приложения.

Липкие сессии

Липкие сессии реализуются на балансировщике нагрузки и не требуют никаких изменений в нодах приложения. Это наиболее удобный метод обработки пользовательских сессий. Балансировщик нагрузки будет постоянно направлять пользователя на один и тот же сервер, что устраняет необходимость распространять данные о сессии между остальными нодами кластера.

Однако это решение тоже имеет один серьёзный недостаток. Теперь балансировщик не только распределяет нагрузку, у него появляется дополнительная задача. Это может повлиять на его производительность и привести к сбою.

Серверы Memcached и Redis

Также можно настроить один или несколько дополнительных серверов для обработки сессий. Это самый надёжный способ решения проблем, связанных с обработкой сессий.

Заключительные действия

Горизонтальное масштабирование приложения сначала кажется очень сложным и запутанным решением, однако оно помогает устранить серьёзные проблемы с трафиком. Главное – научиться работать с балансировщиком нагрузки, чтобы понимать, какие из компонентов требуют дополнительной настройки.

Масштабирование и производительность приложения очень тесно связаны между собой. Конечно, масштабирование нужно далеко не всем приложениям и сайтам. Однако лучше подумать об этом заранее, желательно ещё на стадии разработки приложения.

Tags: ,

С ростом популярности web-приложения его поддержка неизбежно начинает требовать всё больших и больших ресурсов. Первое время с нагрузкой можно (и, несомненно, нужно) бороться путём оптимизации алгоритмов и/или архитектуры самого приложения. Однако, что делать, если всё, что можно было оптимизировать, уже оптимизировано, а приложение всё равно не справляется с нагрузкой?

Оптимизация

Первым делом стоит сесть и подумать, а всё ли вам уже удалось оптимизировать:
  • оптимальны ли запросы к БД (анализ EXPLAIN, использование индексов)?
  • правильно ли хранятся данные (SQL vs NoSQL)?
  • используется ли кеширование?
  • нет ли излишних запросов к ФС или БД?
  • оптимальны ли алгоритмы обработки данных?
  • оптимальны ли настройки окружения: Apache/Nginx, MySQL/PostgreSQL, PHP/Python?
О каждом из этих пунктов можно написать отдельную статью, так что детальное их рассмотрение в рамках данной статьи явно избыточно. Важно лишь понимать, что перед тем как приступить к масштабированию приложения, крайне желательно максимально оптимизировать его работу – ведь возможно тогда никакого масштабирования и не потребуется.

Масштабирование

И так, допустим, что оптимизация уже проведена, но приложение всё равно не справляется с нагрузкой. В таком случае решением проблемы, очевидно, может послужить разнесение его по нескольким хостам, с целью увеличения общей производительности приложения за счёт увеличения доступных ресурсов. Такой подход имеет официальное название – «масштабирование» (scale) приложения. Точнее говоря, под «масштабируемостью » (scalability) называется возможность системы увеличивать свою производительность при увеличении количества выделяемых ей ресурсов. Различают два способа масштабирования: вертикальное и горизонтальное. Вертикальное масштабирование подразумевает увеличение производительности приложения при добавлении ресурсов (процессора, памяти, диска) в рамках одного узла (хоста). Горизонтальное масштабирование характерно для распределённых приложений и подразумевает рост производительности приложения при добавлении ещё одного узла (хоста).

Понятно, что самым простым способом будет простое обновление железа (процессора, памяти, диска) – то есть вертикальное масштабирование. Кроме того, этот подход не требует никаких доработок приложения. Однако, вертикальное масштабирование очень быстро достигает своего предела, после чего разработчику и администратору ничего не остаётся кроме как перейти к горизонтальному масштабированию приложения.

Архитектура приложения

Большинство web-приложений априори являются распределёнными, так как в их архитектуре можно выделить минимум три слоя: web-сервер, бизнес-логика (приложение), данные (БД, статика).

Каждый их этих слоёв может быть масштабирован. Поэтому если в вашей системе приложение и БД живут на одном хосте – первым шагом, несомненно, должно стать разнесение их по разным хостам.

Узкое место

Приступая к масштабированию системы, первым делом стоит определить, какой из слоёв является «узким местом» - то есть работает медленнее остальной системы. Для начала можно воспользоваться банальными утилитами типа top (htop) для оценки потребления процессора/памяти и df, iostat для оценки потребления диска. Однако, желательно выделить отдельный хост, с эмуляцией боевой нагрузки (c помощью или JMeter), на котором можно будет профилировать работу приложения с помощью таких утилит как xdebug , и так далее. Для выявления узких запросов к БД можно воспользоваться утилитами типа pgFouine (понятно, что делать это лучше на основе логов с боевого сервера).

Обычно всё зависит от архитектуры приложения, но наиболее вероятными кандидатами на «узкое место» в общем случае являются БД и код. Если ваше приложение работает с большим объёмом пользовательских данных, то «узким местом», соответственно, скорее всего будет хранение статики.

Масштабирование БД

Как уже говорилось выше, зачастую узким местом в современных приложениях является БД. Проблемы с ней делятся, как правило, на два класса: производительность и необходимость хранения большого количества данных.

Снизить нагрузку на БД можно разнеся её на несколько хостов. При этом остро встаёт проблема синхронизации между ними, решить которую можно путём реализации схемы master/slave с синхронной или асинхронной репликацией. В случае с PostgreSQL реализовать синхронную репликацию можно с помощью Slony-I , асинхронную – PgPool-II или WAL (9.0). Решить проблему разделения запросов чтения и записи, а так же балансировки нагрузку между имеющимися slave’ами, можно с помощью настройки специального слоя доступа к БД (PgPool-II).

Проблему хранения большого объёма данных в случае использования реляционных СУБД можно решить с помощью механизма партицирования (“partitioning” в PostgreSQL), либо разворачивая БД на распределённых ФС типа Hadoop DFS .

Однако, для хранения больших объёмов данных лучшим решением будет «шардинг » (sharding) данных, который является встроенным преимуществом большинства NoSQL БД (например, MongoDB).

Кроме того, NoSQL БД в общем работают быстрее своих SQL-братьев за счёт отсутствия overhead’а на разбор/оптимизацию запроса, проверки целостности структуры данных и т.д. Тема сравнения реляционных и NoSQL БД так же довольно обширна и заслуживает .

Отдельно стоит отметить опыт Facebook, который используют MySQL без JOIN-выборок. Такая стратегия позволяет им значительно легче масштабировать БД, перенося при этом нагрузку с БД на код, который, как будет описано ниже, масштабируется проще БД.

Масштабирование кода

Сложности с масштабированием кода зависят от того, сколько разделяемых ресурсов необходимо хостам для работы вашего приложения. Будут ли это только сессии, или потребуется общий кеш и файлы? В любом случае первым делом нужно запустить копии приложения на нескольких хостах с одинаковым окружением.

Далее необходимо настроить балансировку нагрузки/запросов между этими хостами. Сделать это можно как на уровне TCP (haproxy), так и на HTTP (nginx) или DNS .

Следующим шагом нужно сделать так, что бы файлы статики, cache и сессии web-приложения были доступны на каждом хосте. Для сессий можно использовать сервер, работающий по сети (например, memcached). В качестве сервера кеша вполне разумно использовать тот же memcached, но, естественно, на другом хосте.

Файлы статики можно смонтировать с некого общего файлового хранилища по NFS /CIFS или использовать распределённую ФС (HDFS , GlusterFS , Ceph).

Так же можно хранить файлы в БД (например, Mongo GridFS), решая тем самым проблемы доступности и масштабируемости (с учётом того, что для NoSQL БД проблема масштабируемости решена за счёт шардинга).

Отдельно стоит отметить проблему деплоймента на несколько хостов. Как сделать так, что бы пользователь, нажимая «Обновить», не видел разные версии приложения? Самым простым решением, на мой взгляд, будет исключение из конфига балансировщика нагрузки (web-сервера) не обновлённых хостов, и последовательного их включения по мере обновления. Так же можно привязать пользователей к конкретным хостам по cookie или IP. Если же обновление требует значимых изменений в БД, проще всего, вообще временно закрыть проект.

Масштабирование ФС

При необходимости хранения большого объёма статики можно выделить две проблемы: нехватка места и скорость доступа к данным. Как уже было написано выше, проблему с нехваткой места можно решить как минимум тремя путями: распределённая ФС, хранение данных в БД с поддержкой шардинга и организация шардинга «вручную» на уровне кода.

При этом стоит понимать, что раздача статики тоже не самая простая задача, когда речь идёт о высоких нагрузках. Поэтому в вполне резонно иметь множество серверов предназначенных для раздачи статики. При этом, если мы имеем общее хранилище данных (распределённая ФС или БД), при сохранении файла мы можем сохранять его имя без учёта хоста, а имя хоста подставлять случайным образом при формировании страницы (случайным образом балансирую нагрузку между web-серверами, раздающими статику). В случае, когда шардинг реализуется вручную (то есть, за выбор хоста, на который будут залиты данные, отвечает логика в коде), информация о хосте заливки должна либо вычисляться на основе самого файла, либо генерироваться на основании третьих данных (информация о пользователе, количестве места на дисках-хранилищах) и сохраняться вместе с именем файла в БД.

Мониторинг

Понятно, что большая и сложная система требует постоянного мониторинга. Решение, на мой взгляд, тут стандартное – zabbix, который следит за нагрузкой/работой узлов системы и monit для демонов для подстраховки.

Заключение

Выше кратко рассмотрено множество вариантов решений проблем масштабирования web-приложения. Каждый из них обладает своими достоинствами и недостатками. Не существует некоторого рецепта, как сделать всё хорошо и сразу – для каждой задачи найдётся множество решений со своими плюсами и минусами. Какой из них выбрать – решать вам.

Вертикальное масштабирование — scaling up — увеличение количества доступных для ПО ресурсов за счет увеличения мощности применяемых с серверов.

— scaling out — увеличение количества нод, объединенных в кластер серверов при нехватке CPU, памяти или дискового пространства.

И то и другое является инфраструктурными решениями, которые в разных ситуациях требуются когда веб проект растет.

Вертикальное и горизонтальное масштабирование, scaling для web

Для примера можно рассмотреть сервера баз данных. Для больших приложений это всегда самый нагруженный компонент системы.

Возможности для масштабирования для серверов баз данных определяются применяемыми программными решениями: чаще всего это реляционные базы данных (MySQL, Postgresql) или NoSQL ( , Cassandra и др).

Горизонтальное масштабирование для серверов баз данных при больших нагрузках значительно дешевле

Веб-проект обычно начинают на одном сервере, ресурсы которого при росте заканчиваются. В такой ситуации возможны 2 варианта:

  • перенести сайт на более мощный сервер
  • добавить еще один сервер небольшой мощности с объединить машины в кластер

MySQL является самой популярной RDBMS и, как и любая из них, требует для работы под нагрузкой много серверных ресурсов. Масштабирование возможно, в основном, вверх. Есть шардинг (для его настройки требуется вносить изменения в код) и , которая может быть сложной в поддержке.

Вертикальное масштабирование

NoSQL масштабируется легко и второй вариант с, например, MongoDB будет значительно выгоднее материально, при этом не потребует трудозатратных настроек и поддержки получившегося решения. Шардинг осуществляется автоматически.

Таким образом с MySQL нужен будет сервер с большим количеством CPU и оперативной памяти, такие сервера имеют значительную стоимость.

Горизонтальное масштабирование
С MongoDB можно добавить еще один средний сервер и полученное решение будет стабильно работать давая дополнительно отказоустойчивость.


Scale-out или является закономерным этапом развития инфраструктуры. Любой сервер имеет ограничения и когда они достигнуты или когда стоимость более мощного сервера оказывается неоправданно высокой добавляются новые машины. Нагрузка распределяется между ними. Также это дает отказоустойчивость.

Добавлять средние сервера и настраивать кластеры нужно начинать когда возможности для увеличения ресурсов одной машины исчерпаны или когда приобретение сервера мощнее оказывается невыгодно

Приведенный пример с реляционными базами данных и NoSQL является ситуацией, которая имеет место чаще всего. Масштабируются также фронтэнд и бэкенд сервера.

Читайте про и балансер

Олег Спиряев

В последнее время нередки утверждения, что серверы среднего и старшего класса активно заменяются на группы серверов начального уровня, объединенные в стойки или кластеры. Однако некоторые эксперты с этим не согласны. Так, по данным Dataquest, доля моделей ценой от 500 тыс. долл. и выше (к ним относятся средние и старшие серверы SMP) в общем объеме продаж серверов с 2000 до 2002 г. выросла с 38 до 52%.

Другие данные, полученные компанией IDC, свидетельствуют о росте (по крайней мере, по числу машин) в секторе младших моделей серверов - с двумя процессорами. IDC также предсказывает, что в 2005 г. самой распространенной операционной системой для серверов стоимостью от 50 тыс. до 3 млн долл. будет Unix. Из сравнения этих данных видно, что Unix-серверы среднего и старшего класса останутся преобладающей платформой для центров обработки данных, но будут дополняться все растущим числом небольших (обычно двухпроцессорных) серверов.

Эта тенденция сложилась в результате выделения в центрах обработки данных разных уровней вычислений (рис. 1). Уровень 1, или фронтальный уровень, постепенно переходит на модель горизонтального масштабирования небольших серверов, а на уровне 3 (уровне баз данных) преобладают серверы с вертикальным масштабированием. Уровень 2 (уровень приложений) становится областью, где сосуществуют вертикальная и горизонтальная архитектуры.

Вертикальная и горизонтальная архитектуры

Рассмотрим основные различия между вертикальной и горизонтальной архитектурами. Серверы с вертикальным масштабированием - это большие SMP-системы (с симметричной многопроцессорной обработкой или совместно используемой памятью), насчитывающие свыше четырех центральных процессоров. В них используется только одна копия ОС, управляющая работой всех процессоров, памяти и компонентов ввода-вывода. Обычно все эти ресурсы размещены в одной стойке или шкафу. Межсоединения у таких серверов осуществляются по высокоскоростной центральной или объединительной панели с небольшим временем запаздывания и согласованным доступом к кэш-памяти. Добавить ресурсы можно путем установки внутрь шкафа дополнительных системных плат. В системах с вертикальной архитектурой (или SMP-системах) память используется совместно, т. е. все процессоры и компоненты ввода-вывода получают доступ ко всей памяти. Пользователь "видит" память как единый большой объект.

При альтернативном, горизонтальном масштабировании системы соединяются через сеть или объединяются в кластер. Для межсоединений обычно используются стандартные сетевые технологии, такие, как Fast Ethernet, Gigabit Ethernet (GBE) и Scalable Coherent Interconnect (SCI), дающие меньшую пропускную способность и большее запаздывание по сравнению с вертикальными системами. Ресурсы в этом случае распределяются между узлами, обычно содержащими от одного до четырех процессоров; каждый узел имеет собственный процессор и память и может иметь собственную подсистему ввода-вывода или использовать ее совместно с другими узлами. На каждом узле работает отдельная копия ОС. Ресурсы расширяются за счет добавления узлов, но не добавления ресурсов в узел. Память в горизонтальных системах распределена, т. е. у каждого узла есть собственная память, к которой напрямую обращаются его процессоры и подсистема ввода-вывода. Доступ к этим ресурсам с другого узла происходит намного медленнее, чем с узла, где они расположены. Кроме того, при горизонтальной архитектуре отсутствует согласованный доступ узлов к памяти, а используемые приложения потребляют относительно немного ресурсов, поэтому они "умещаются" на одном узле и им не нужен согласованный доступ. Если же приложению потребуется несколько узлов, то оно само должно обеспечить согласованный доступ к памяти.

Если горизонтальная система удовлетворяет требованиям приложений, то такая архитектура предпочтительна, поскольку расходы на ее приобретение меньше. Обычно стоимость приобретения в расчете на один процессор у горизонтальных систем ниже, чем у вертикальных. Разница в цене объясняется тем, что в вертикальных системах применяются более мощные функции надежности, доступности и обслуживаемости - RAS (reliability, availability, serviceability), а также высокопроизводительные межсоединения. Однако есть ряд ограничений на применение систем с горизонтальной архитектурой. Ниже мы обсудим, в каких условиях возможно применение горизонтальных систем и когда обязательно вертикальное масштабирование.

Помимо одного большого SMP-сервера, к вертикальной архитектуре относятся также кластеры больших SMP-серверов, используемые для одного крупномасштабного приложения.

Недавно появившиеся на рынке модульные, или blade-серверы, обычно оборудуемые одним-двумя процессорами, - пример горизонтальных серверов. Здесь кластер состоит из небольших узлов, в каждом из которых установлен SMP-сервер начального уровня с числом центральных процессоров от 1 до 4.

Другой способ горизонтального масштабирования - это большие вычислительные системы с массовым параллелизмом (MPP), состоящие из множества установленных в одном шкафу небольших процессоров, каждый из которых имеет собственную копию ОС или копию микроядра ОС. В настоящее время выпускаются всего несколько систем MPP, которые чаще всего представляют специализированные решения. Это, например, системы Terradata производства компании NCR, IBM RS/6000SP (SP-2) и HP Tandem non-stop.

Таблица 1. Особенности вертикальной и горизонтальной архитектур

Параметр Вертикальные системы Горизонтальные системы
Память Большая совместно используемая Небольшая выделенная
Потоки Много взаимозависимых потоков Много независимых потоков
Межсоединения Сильносвязанные внутренние Слабосвязанные внешние
RAS Мощные RAS одиночной системы Мощные RAS с использованием репликации
Центральные процессоры Много стандартных Много стандартных
ОС Одна копия ОС на множество центральных процессоров Несколько копий ОС (по одной копии на 1-4 процессора)
Компоновка В одном шкафу Размещение большого числа серверов в стойке
Плотность размещения Высокая плотность размещения процессоров на единицу площади пола
Оборудование Стандартное и специально разработанное Стандартное
Масштабирование В пределах корпуса одного сервера В масштабе нескольких серверов
Расширение Путем установки в сервер дополнительных компонентов Путем добавления новых узлов
Архитектура 64-разрядная 32- и 64-разрядная

Табл. 1 позволяет провести сравнительный анализ вертикальной и горизонтальной архитектур.

  • В вертикальных системах память используется совместно и обеспечивается согласованный доступ к кэш-памяти.
  • Вертикальные системы идеальны для потоков выполнения задач, которые должны обмениваться данными между собой.
  • Вертикальные системы характеризуются мощными функциями RAS, а в горизонтальных системах доступность реализуется с помощью массивной репликации (в кластер соединяются несколько узлов, поэтому отказ одного из них мало влияет на работу всей системы).
  • В вертикальных системах одна копия ОС охватывает все ресурсы. Некоторые вертикальные системы, например, мидфреймы и серверы класса high-end Sun Microsystems (от Sun Fire 4800 до Sun Fire 15K), можно разделить на меньшие вертикальные серверы.
  • В вертикальных системах используется максимально возможное число стандартных компонентов, но некоторые основные составляющие (например, межсоединения) специально разрабатываются.
  • Вертикальные системы можно расширять, устанавливая в существующий каркас дополнительные компоненты (более мощные процессоры, добавочную память, дополнительные и более производительные соединения ввода-вывода и т. п.). Горизонтальные системы расширяются за счет добавления узла или замены старых узлов на новые.
  • Практически все вертикальные системы 64-разрядные, а горизонтальные могут быть как 32-разрядными, так и 64-разрядными.

Для одних типов приложений лучше подходят вертикальные системы, для других - горизонтальные, однако во многих случаях оптимальный выбор архитектуры зависит от размера задачи. В табл. 2 приведены примеры приложений, для которых оптимальна вертикальная либо горизонтальная архитектура.

Таблица 2. Типы приложений для вертикальной и горизонтальной архитектур

Для небольших и модульных серверов хорошо подходят приложения, которые не используют информацию о состоянии, невелики по масштабу и легко реплицируются. А для приложений, использующих информацию о состоянии и большие объемы данных, требующих интенсивной передачи данных внутри системы, идеальным решением будут вертикальные серверы. На рынке высокопроизводительных технических вычислений (HPTC) имеется множество приложений, в которых потоки зависят друг от друга и обмениваются данными между собой. Существуют также приложения, которым нужны большие объемы совместно используемой памяти. Для этих двух типов приложений лучше всего подходят большие SMP-серверы. Однако имеются и такие приложения HPTC, в которых потоки исполнения независимы и им не требуется совместно используемая память большого объема. Такие приложения можно разбивать на разделы, и потому для их выполнения идеальны кластеры небольших серверов. Аналогичным образом некоторые коммерческие приложения поддерживают разделы, и для них оптимальны горизонтальные серверы, а другие нельзя разбить на разделы, поэтому для них лучшая платформа - это вертикальные серверы.

Факторы, влияющие на производительность

Все крупные центры обработки данных представляют собой параллельные компьютеры. Здесь даже кластеры можно рассматривать как особый тип параллельных систем. Для получения высокой производительности требуется сбалансированная система с мощными процессорами, работающими на высокой скорости межсоединениями и подсистемой ввода-вывода, масштабируемой ОС, оптимизированными приложениями и совершенными функциями RAS.

Процессоры и системные межсоединения

Процессоры, безусловно, существенный компонент, но они только отчасти определяют общую производительность системы. Более важно обеспечить работу процессоров с максимальной загрузкой. У мощного процессора, загруженного лишь на 50%, производительность будет хуже, чем у более медленного процессора, который загружен на 80%.

Кроме того, по мере роста числа процессоров в параллельной системе на первый план выходит не их мощность, а системные межсоединения. Именно они отвечают за перемещение данных с диска, из памяти и из сети к процессору. В кластере в качестве межсоединения выступает сетевое соединение, например, Fast Ethernet или Gigabit Ethernet. Кластерные межсоединения перемещают данные между узлами, а системные - внутри отдельной системы. Если межсоединение работает слишком медленно, то процессор в ожидании данных будет простаивать.

Системные межсоединения также используются для перемещения адресов данных, что необходимо для поддержки согласованного обращения к кэш-памяти. Если системное межсоединение слишком медленно передает адреса данных, то процессор опять-таки будет простаивать в ожидании данных, поскольку для доступа к ним ему нужно знать их адрес. Быстрые межсоединения обеспечивают высокую пропускную способность и низкое запаздывание (малое время, проходящее от момента запроса на данные до начала передачи данных).

Основное техническое различие между горизонтальными и вертикальными системами - это пропускная способность и запаздывание их межсоединений. У межсоединений кластеров пропускная способность может составлять от 125 Мбайт/с для Fast Ethernet до 200 Мбайт/с для SCI, а запаздывание - от 100 тыс. нс для GBE и до 10 тыс. нс для SCI. С помощью интерфейса InfiniBand возможно реализовать более быстрые межсоединения с пиковой скоростью от примерно 250 Мбайт/с для первой версии и до 3 Гбайт/с для последующих.

Ввод и вывод

Быстрый ввод-вывод необходим для того, чтобы межсоединение могло быстро получить данные с диска и из сети и передать их процессорам. Узкое место в подсистеме ввода-вывода может отрицательно сказаться на работе даже самых быстрых межсоединений и процессоров.

Операционная система

Даже лучшее оборудование оказывается неэффективным, если ОС недостаточно масштабируема. Для горизонтальных систем масштабируемость ОС не столь важна, потому что в отдельном узле или с отдельной копией ОС работает не более четырех процессоров.

Доступность системы

Вообще говоря, доступность системы во многом зависит от типа архитектуры. В больших SMP-системах функции RAS встроены в систему и дополнены переключением при отказах для двух-четырех узлов. В горизонтальных системах RAS отдельных узлов хуже, но улучшение этих функций достигается многократной репликацией узлов.

Оптимизированные приложения

Приложения необходимо оптимизировать для архитектуры вычислительной системы. Легче всего писать и оптимизировать приложения для SMP-систем. Основные коммерческие приложения оптимизированы именно для SMP-систем и даже разрабатывались на них, поэтому SMP доминируют на рынке систем среднего класса и high-end последние десять лет.

Размер приложений

Как уже отмечалось, в больших SMP-системах используются высокоскоростные межсоединения, обеспечивающие достаточную производительность системы. В горизонтальных системах могут возникать проблемы с производительностью из-за низкой пропускной способности и значительной задержки межсоединений в тех случаях, когда требуется часто передавать данные между узлами. Однако некоторым приложениям для достижения высокой производительности не нужна высокая скорость межсоединений - обычно это небольшие приложения и приложения, которые можно легко реплицировать (например, Web-серверы, прокси-серверы, брандмауэры и небольшие серверы приложений). В таких горизонтальных системах каждый узел выполняет небольшую задачу независимо от работы всех остальных.

Например, в случае горизонтальной архитектуры (или архитектуры с распределенной памятью) четыре процессорных узла (каждый с отдельным ОЗУ и выделенной либо используемой совместно подсистемой ввода-вывода) могут использовать сетевое межсоединение, например, Gigabit Ethernet. В этой вычислительной среде выполняются рабочие нагрузки трех типов. Самая маленькая нагрузка помещается на одном узле, но по мере ее увеличения для выполнения требуется уже несколько узлов. Как утверждают специалисты, при выполнении одной задачи на нескольких узлах производительность значительно ухудшается из-за медленных межузловых межсоединений. Небольшие нагрузки, которым не нужно обмениваться данными между собой, прекрасно сочетаются с горизонтальной архитектурой, но при выполнении в ней крупномасштабных нагрузок возникают проблемы.

Конфигурация большой системы SMP может включать, например, до 100 процессоров, 576 Гбайт совместно используемой памяти и высокоскоростные межсоединения. Такая система может обрабатывать все типы нагрузок, поскольку в ней отсутствует обмен данными между узлами и эффективно осуществляется обмен данными между процессами. Все центральные процессоры могут одновременно получить доступ ко всем дискам, всей памяти и сетевым соединениям - это ключевая особенность SMP-систем (или вертикальных систем).

Часто возникает вопрос о целесообразности размещения на больших SMP малых нагрузок. Хотя в техническом плане это возможно, с экономической точки зрения такой подход себя не оправдывает. Для больших SMP стоимость приобретения в расчете на один процессор выше, чем для маленьких систем. Поэтому если приложение может работать на небольшом узле (или нескольких небольших узлах) и это не создает серьезных проблем с управлением, для его развертывания лучше подходит горизонтальное масштабирование. Но если приложение слишком велико и не может выполняться на небольшом узле (или нескольких таких узлах), то крупный SMP-сервер будет оптимальным вариантом с точки зрения как производительности, так и системного администрирования.

Производительность на уровне базы данных

Основной вопрос здесь - сравнение производительности одиночных средних и больших SMP-серверов с кластером небольших серверов (не более четырех процессоров).

При обсуждении масштабируемости фирмы-производители используют ряд специальных терминов. Так, рост производительности (Speedup) для SMP определяется как отношение скоростей выполнения приложения на нескольких процессорах и на одном. Линейный рост производительности (Linear speedup) означает, например, что на 40 процессорах приложение работает в 40 раз (40x) быстрее, чем на одном. Рост производительности не зависит от числа процессоров, т. е. для конфигурации из 24 процессоров он будет таким же, как для 48 процессоров. Рост производительности кластера (Cluster speedup) отличается только тем, что при его расчете берется число узлов, а не процессоров. Как и рост производительности SMP, рост производительности кластера остается постоянным для разного числа узлов.

Эффективность масштабирования (Scaling efficiency) характеризует способность приложений, особенно кластерных, масштабироваться на большое число узлов. Обычно считается, что эффективность масштабирования зависит от числа узлов, участвующих в измерении. Эффективность масштабирования SMP (SMP scaling efficiency) - это рост производительности, деленный на число процессоров, а эффективность кластера (Cluster efficiency) - это рост производительности кластера, деленный на число узлов в нем. Нужно понимать, в чем смысл этих параметров, чтобы не складывалась неправильная картина, поскольку эффективность масштабирования 90% на двух узлах - это не то же самое, что эффективность масштабирования 90% на четырех узлах.

На рис. 2 приведены три графика: идеальная линейная масштабируемость, масштабируемость 24-процессорного SMP-сервера в 95% и масштабируемость кластера из двух 4-процессорных серверов в 90%. Видно, что существуют определенные ограничения на масштабируемость баз данных в кластерах (при горизонтальном масштабировании). Соединяя вместе много маленьких серверов, не удается получить масштабируемость, необходимую для средних и крупных приложений. Причина этого - ограничения пропускной способности внутрикластерных межсоединений, дополнительная нагрузка на ПО баз данных, связанная с управлением кластером, и трудности написания приложений для кластерных сред с распределенной памятью.

Опубликованные результаты эталонных тестов показывают, например, что у Oracle9i RAC (Real Application Cluster) рост производительности составляет 1,8 и эффективность масштабирования равна 90%. Такая эффективность масштабируемости может показаться достаточно высокой, но на самом деле масштабируемость 90% для четырех узлов оказывается неэффективной, если сравнить ее с результатами больших SMP-серверов.

Производительность на уровне приложений

Уровень приложений в трехуровневом центре обработки данных сильно отличается от уровня базы данных. Обычно приложения этого уровня работают без запоминания состояния - иными словами, на самом сервере данные не хранятся или хранится только их небольшая часть. Этот уровень содержит бизнес-правила для сервисов приложений. Транзакции приходят на уровень приложений и им же обрабатываются. Когда данные нужно записать или считать, транзакции передаются на уровень базы данных. Серверы приложений стремятся консолидировать соединения с базой данных, поскольку большое число соединений отрицательно влияет на производительность.

В большинстве случаев уровню сервера приложений требуется намного больше процессоров, чем уровню базы данных в расчете на отдельный прикладной сервис. Например, в случае SAP R/3 это соотношение составляет примерно 10 процессоров на каждый процессор базы данных, т. е. если SAP R/3 требуется 20 процессоров для уровня базы данных, то на уровне приложений должно быть примерно 200 процессоров. Вопрос заключается в том, что выгоднее развернуть - 100 двухпроцессорных серверов или десять 20-процессорных. Аналогичным образом в Oracle соотношение процессоров приложений к процессорам баз данных равно примерно 5 к 1.

Считается, что серверы приложений не требуется распределять по нескольким узлам. Несколько копий прикладного ПО можно распределить по разным физическим серверам разной мощности или по динамическим доменам больших серверов.

Число процессоров, требуемых для уровня приложений, будет примерно одинаково независимо от архитектуры компьютеров. Затраты на приобретение оборудования и ПО для горизонтальной архитектуры будут меньше, поскольку стоимость в расчете на один процессор в этом случае меньше. В большинстве случаев горизонтальные системы способны обеспечить производительность, необходимую для выполнения соглашения об уровне сервиса. Затраты, связанные с приобретением лицензий на ПО, для обеих архитектур примерно одинаковы.

В то же время расходы на управление и обслуживание инфраструктуры у горизонтальной архитектуры могут оказаться более высокими. При развертывании на горизонтальных системах используются многочисленные копии ОС и ПО серверов приложений. Затраты же на поддержание инфраструктуры обычно растут пропорционально числу копий ОС и приложений. Кроме того, для горизонтальной архитектуры резервное копирование и восстановление после аварий становится децентрализованным, и управлять сетевой инфраструктурой сложнее.

Стоимость системного администрирования с трудом поддается измерениям. Обычно модели для сравнения горизонтального и вертикального развертывания прикладных серверов показывают, что управление меньшим числом более мощных серверов (вертикальных серверов) обходится дешевле, чем управление множеством небольших серверов. В целом при выборе типа архитектуры для развертывания уровня приложений ИТ-менеджеры должны детально проанализировать стоимость приобретения оборудования.

Влияние архитектуры на доступность

Доступность крайне важна для современных центров обработки данных - сервисы приложений должны быть доступны в режиме 24x7x365 (24 часа в сутки, 7 дней в неделю, 365 дней в году). В зависимости от потребностей конкретного центра обработки данных используются разные схемы обеспечения высокой доступности. Для выбора конкретного решения необходимо определить допустимое время простоев (запланированных и незапланированных). На рис. 3 показано, как процент доступности отражается на продолжительности простоев.

По мере роста требований к доступности растет и стоимость решения. Менеджеры центров обработки данных должны определить, какое сочетание стоимости, сложности и доступности наилучшим образом соответствует требованиям к уровню сервиса. Центры обработки данных, которым нужна доступность примерно 99,95%, могут развернуть одиночный SMP-сервер с такими функциями RAS, как полное резервирование аппаратуры и обслуживание в онлайновом режиме.

Однако для достижения доступности выше 99,95% потребуется кластер. ПО Sun Cluster с переключением при отказе HA (High Availability - высокой доступности) обеспечивает доступность 99,975%. Переключение при отказе HA использует основной сервер и находящийся в горячем резерве; при отказе основного сервера резервный берет на себя его нагрузку. Время перезапуска сервиса зависит от приложений и может занять несколько минут, особенно в случае приложений баз данных, которым для восстановления транзакций требуется откат с обработкой большого объема данных.

Если простои в несколько минут недопустимы для центра обработки данных, то решением может стать система типа "активный-активный", где приложение развертывается на двух или нескольких узлах: если один из них выйдет из строя, то остальные продолжат выполнение приложения. В результате перебой будет очень коротким (некоторые клиенты сообщают, что он продолжается менее 1 мин), иногда пользователь может даже не заметить отказа узла.

Вертикальные серверы обеспечивают высокую доступность за счет встраивания многих функций RAS в отдельный сервер для сокращения до минимума запланированных и незапланированных простоев. В горизонтальных серверах функции, обеспечивающие высокий уровень RAS, реализуются не на уровне отдельного сервера, а за счет дублирования и размещения нескольких серверов. Из-за разной реализации функций RAS и межсоединений горизонтальные серверы обычно дешевле в расчете на один процессор.

Для трехуровневой архитектуры хорошим примером горизонтальной высокой доступности служит развертывание Web-серверов. Можно развернуть много небольших серверов, на каждом из которых будет установлена отдельная копия ПО Web-сервера. Если один Web-сервер выйдет из строя, его транзакции перераспределяются между остальными работоспособными серверами. В случае серверов приложений они могут размещаться как на горизонтальных, так и на вертикальных серверах, и высокая доступность реализуется с помощью дублирования. Независимо от того, развертывается ли несколько крупных SMP-серверов или много небольших, дублирование остается основным способом обеспечения высокого RAS на уровне приложений.

Однако для уровня баз данных ситуация меняется. Базы данных сохраняют состояние и по своей природе требуют в большинстве случаев разделения данных и возможности доступа к ним со всех процессоров/узлов. Это означает, что для высокой доступности с помощью дублирования нужно использовать такое ПО кластеризации, как Sun Cluster или Oracle9i RAC (для очень высокой доступности).

Выводы

Как у вертикальной, так и у горизонтальной архитектуры есть своя ниша в сегодняшнем центре обработки данных. Хотя сегодня основное внимание сосредоточено на таких новых технологиях, как модульные серверы и параллельные базы данных, на рынке сохраняется высокий спрос на серверы среднего класса и класса high-end.

Вертикальные и горизонтальные системы могут использовать одно и то же ПО, ОС и даже одинаковые процессоры. Основное различие, которое сказывается на цене и производительности, это межсоединения, используемые в той и в другой архитектуре. Горизонтальные серверы используют слабосвязанные внешние межсоединения, а вертикальные серверы - сильносвязанные межсоединения, обеспечивающие более высокую скорость передачи данных.

Для фронтального уровня горизонтальные серверы обычно предоставляют оптимальное решение с точки зрения производительности, совокупной стоимости приобретения и доступности. Для уровня приложений можно эффективно использовать как вертикальную, так и горизонтальную архитектуру. Для уровня баз данных оптимальным решением будет использование вертикальных серверов, независимо от требуемого уровня доступности.

Масштабирование приложений ASP.NET

Итак, вы увеличили производительность своего веб-приложения, применив все знания, полученные в предыдущих статьях, и может быть даже другие приемы, почерпнутые из других источников, и теперь ваше приложение оптимизировано до предела.

Далее вы развертываете приложение, вводите его в эксплуатацию и оно работает замечательно в течение нескольких первых недель, но с увеличением количества пользователей увеличивается и количество запросов, которые требуется обработать вашему серверу, и вдруг, ваш сервер начинает захлебываться. Сначала это может проявляться в увеличении времени обработки запросов, затем рабочий процесс начинает использовать все больше памяти и вычислительных ресурсов и в конечном итоге веб сервер просто перестает успевать обрабатывать все запросы и в файлах журналов начинают все чаще появляться сообщения HTTP 500 («Internal Server Error»).

Что случилось? Может быть снова заняться оптимизацией приложения? Однако, с увеличением количества пользователей ситуация повторится. Может быть увеличить объем памяти или добавить процессоры? Однако подобное расширение возможностей единственного компьютера имеет свои пределы. Пришло время признать тот факт, что вам необходимы дополнительные серверы.

Горизонтальное масштабирование (scaling out) веб-приложений - это естественный процесс, начинающийся в определенный момент в жизни веб-приложений. Один сервер может одновременно обслуживать десятки, сотни и даже тысячи пользователей, но он не в состоянии достаточно долго выдерживать пиковые нагрузки. Память начинает заполняться информацией о сеансах, обработка новых запросов приостанавливается из-за отсутствия свободных потоков выполнения, и переключения контекста начинают выполняться слишком часто, что ведет к увеличению задержек и снижению пропускной способности сервера.

Горизонтальное масштабирование

С архитектурной точки зрения, выполнить масштабирование совсем не сложно: достаточно приобрести еще один-два компьютера (или десять), разместить серверы за компьютером, выполняющим распределение нагрузки, и все! Но проблема в том, что обычно все не так просто.

Одной из основных проблем горизонтального масштабирования, с которыми сталкиваются разработчики - как реализовать привязку к серверу. Например, когда работает единственный веб-сервер, информация о состоянии сеансов пользователей хранится в памяти. Если добавить еще один сервер, как обеспечить для него доступ к объектам сеансов? Как синхронизировать сеансы между серверами?

Некоторые веб-разработчики решают эту проблему, сохраняя информацию на сервере и связывая клиента с конкретным сервером. Как только клиент соединится с одним из серверов, находящихся за балансировщиком нагрузки, с этого момент все запросы от этого клиента будут направляться одному и тому же веб-серверу. Этот прием называется также привязкой сеанса. Привязка сеанса - это обходное решение, но оно не решает проблему, потому что не позволяет равномерно распределять нагрузку между серверами. Используя этот прием, легко попасть в ситуацию, когда один сервер будет обслуживать достаточно много пользователей, а другие будут в это время простаивать, потому что их клиенты уже закончили работу и отключились.

Поэтому настоящее решение заключается в том, чтобы не использовать память компьютера для хранения таких данные, как информация о сеансах пользователей или кеш. Но как хранение кеша в памяти определенного компьютера может помешать масштабированию?

Представьте, что произойдет, когда пользователь пошлет запрос, вызывающий обновление кеша: сервер, получивший запрос, обновит свой кеш в памяти, но другие серверы не будут знать, что это необходимо сделать, и если в их кешах хранится копия того же объекта, это приведет к противоречивости данных в масштабе всего приложения. Один из способов решения этой проблемы - организовать синхронизацию объектов в кеше между серверами. Такое вполне возможно, но это усложнит общую архитектуру веб-приложения, не говоря уже о том, как вырастет объем трафика между серверами.

Механизмы масштабирования в ASP.NET

Горизонтальное масштабирование требует хранения информации о состоянии за пределами процессов. В ASP.NET имеется два механизма, обеспечивающих такой способ хранения данных:

Служба управления состоянием (State Service)

Служба управления состоянием - это служба Windows, поддерживающая управление состоянием для нескольких компьютеров. Эта служба устанавливается автоматически при установке.NET Framework, но она выключена по умолчанию. Вам достаточно просто выбрать, на каком сервере будет выполняться служба управления состоянием, и настроить все остальные на ее использование. Несмотря на то, что служба управления состоянием позволяет нескольким серверам использовать общее хранилище информации, она не поддерживает возможность долговременного хранения. То есть, если что-то приключится с сервером, где выполняется эта служба, вся информация о сеансах в вашей веб-ферме будет утеряна.

SQL Server

ASP.NET поддерживает возможность хранения информации о состоянии в базе данных SQL Server. Этот механизм не только поддерживает те же возможности, что и служба управления состоянием, но также обеспечивает долговременное хранение данных, поэтому, даже если на веб-серверах и на сервере с базой данных SQL Server случится аварийная ситуация, информация о состоянии сохранится.

Для нужд кеширования в большинстве случаев можно с успехом использовать один из механизмов распределенного кеширования, таких как Microsoft AppFabric Cache , NCache или Memcached , последний из которых является открытой реализацией распределенного кеша.

Механизм распределенного кеширования позволяет объединить память нескольких серверов в один распределенный кеш. Распределенные кеши поддерживают абстракцию местоположения, поэтому от вас не потребуется знать, где находится каждый фрагмент данных, службы уведомлений помогут оставаться в курсе - где и что изменилось, а высокая доступность гарантирует, что даже в случае аварии на одном из серверов данные не будут утеряны.

Некоторые распределенные кеши, такие как AppFabric Cache и Memcached, также имеют собственные реализации службы управления состоянием и провайдеров кеша для ASP.NET.

Ловушки горизонтального масштабирования

Хотя это и не имеет прямого отношения к производительности, все же стоит обозначить некоторые проблемы, с которыми можно столкнуться при масштабировании веб-приложений.

Некоторые части веб-приложений требуют использования особых ключей безопасности для генерации уникальных идентификаторов, чтобы предотвратить возможность обмана веб-приложения и вторжения в него. Например, уникальный ключ используется в процедуре аутентификации FormsAuthentication и при шифровании данных механизмом сохранения состояния представления. По умолчанию ключи безопасности для веб-приложений генерируются каждый раз, когда запускается пул приложения.

В случае с единственным сервером это не вызывает никаких проблем, но когда веб-приложение выполняется на нескольких серверах, это может превратиться в проблему, так как каждый сервер будет иметь свой собственный уникальный ключ. Представьте такую ситуацию: клиент посылает запрос серверу A и получает в ответ cookie, подписанный уникальным ключом сервера A, затем клиент посылает новый запрос с принятым cookie, который попадает на сервер B. Поскольку сервер B имеет иной уникальный ключ, содержимое cookie признается недействительным и клиенту возвращается сообщение об ошибке.

Управлять генерацией этих ключей в ASP.NET можно путем настройки параметров в разделе machineKey, в файле web.config. Когда веб-приложение выполняется на нескольких серверах, вам необходимо настроить все серверы так, чтобы они использовали один и тот же предварительно сгенерированный ключ.

Другой проблемой, связанной с горизонтальным масштабированием и уникальными ключами, является возможность шифрования разделов в файлах web.config. Закрытая информация в файлах web.config часто шифруется, когда приложение развертывается на серверах. Например, раздел connectionString можно зашифровать, чтобы предотвратить утечку имени пользователя и пароля к базе данных. Вместо того, чтобы шифровать файл web.config на каждом сервере отдельно, усложняя процесс развертывания, можно сгенерировать один зашифрованный файл web.config и развернуть его на всех серверах. Для этого следует создать RSA-контейнер ключей и импортировать его на все веб-серверы.

Более полную информацию о создании уникальных ключей и включения их в настройки приложений можно получить в базе знаний Microsoft Knowledge Base . За дополнительной информацией о создании RSA-контейнера ключей обращайтесь к статье «Импорт и экспорт защищенных контейнеров ключей RSA для конфигурации» на сайте MSDN.