Горизонтальное масштабирование PHP-приложений. Основы масштабирования

С ростом популярности 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-приложения. Каждый из них обладает своими достоинствами и недостатками. Не существует некоторого рецепта, как сделать всё хорошо и сразу – для каждой задачи найдётся множество решений со своими плюсами и минусами. Какой из них выбрать – решать вам.

Возможность масштабирования информационной системы – как горизонтальное, так и вертикальное – является одним из самых важных факторов, на которые стоит обращать при выборе средства автоматизации деятельности любой организации. Если выбранное решение невозможно будет масштабировать, или каждая стадия роста бизнеса будет приводить к сложностям с сопровождением и развитием такого программного продукта, то не следует даже начинать его использовать. Мы разрабатывали СЭД ЛЕТОГРАФ с учетом высоких требований к масштабированию.

Необходимость в горизонтальном или вертикальном масштабировании возникает в связи с созданием корпоративных высоконагруженных ИТ-систем, в которых работают тысячи или даже десятки тысяч пользователей. Однако поддерживать одновременную работу большого числа пользователей могут далеко не все СЭД. Только если в СЭД на уровне архитектуры заложены возможности по наращиванию количества пользователей без потери производительности – только в этом случае масштабирование будет успешным. Созданная нами система ЛЕТОГРАФ была разработана таким образом, чтобы идеально масштабироваться как горизонтально, так и вертикально. Это достигается как за счет архитектуры самой системы и того прикладного кода, который мы разработали, так и за счет функционала СУБД InterSystems Caché, на которой наша СЭД построена.

СУБД Caché – это современная система управления базами данных и среда для быстрой разработки приложений. В основе этой СУБД лежит технология, которая обеспечивает быстродействие и высокую производительность, масштабируемость и надежность. При этом аппаратные требования системы остаются довольно скромными.

СУБД Caché сохраняет высокую производительность даже при работе с огромными массивами данных и большим числом серверов в распределенных системах. При этом доступ к данным осуществляется через объекты, высокопроизводительные SQL-запросы и путем прямой обработки многомерных структур данных.

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

Вертикальное масштабирование предполагает наращивание мощности сервера и его возможностей, связанных с дисковой подсистемой. ЛЕТОГРАФ поддерживает современную процессорную архитектуру, что позволяет обрабатывать большие объемы данных в несколько потоков. При этом сами данные в СЭД организованы таким образом, чтобы их можно было легко разносить по СХД на разные диски. Такой подход позволяет равномерно распределить нагрузку на хранилища данных и минимизировать ее при чтении данных непосредственно из базы, а значит и падения производительности системы удастся избежать даже при одновременной работе большого количества пользователей.

Еще на этапе разработки платформы мы понимали, что вертикальное масштабирование – одна из ключевых возможностей системы, потребность в которой со временем будет только увеличиваться. Мы разработали систему таким образом, чтобы процессы работы каждого пользователя были выделены в отдельные системные процессы, которые между собой не пересекаются благодаря тому, что базы данных эффективно делят доступ к информации. При этом количество блокировок данных в СЭД ЛЕТОГРАФ минимизировано и нет «узкого горла» ни при чтении данных, ни при их записи.

Архитектура СЭД ЛЕТОГРАФ позволяет распределять данные на несколько физических или виртуальных серверов. Благодаря такому распределению каждый из пользователей работает в изолированном процессе, а требуемые данные эффективно кэшируются с использованием технологий СУБД Caché. Время блокировки данных минимизировано: все транзакции выстроены таким образом, чтобы переводить данные в эксклюзивный режим доступа лишь на очень короткое время. При этом даже такие высоконагруженные с точки зрения количества обращений к диску данные, как журналы, индексы, данные объектов, потоки, логи действий пользователей, распределены таким образом, что средняя нагрузка на подсистему остается равномерной и не приводит к задержкам. Такой подход позволяет эффективно вертикально масштабировать систему, распределяя нагрузку между серверами или виртуальными дисками.

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

Горизонтальное масштабирование – это распределение сессий пользователей по разным серверам (равномерная загрузка серверов приложений и возможность подключать дополнительные сервера приложений), а также распределение данных по разным серверам БД, что обеспечивает высокую производительность системы, при этом не приводя к снижению отказоустойчивости. Для горизонтального масштабирования в системе ЛЕТОГРАФ предусмотрен целый ряд возможностей.

Прежде всего, это масштабирование нагрузки благодаря Enterprise Cache Protocol (ECP, протокол распределенного кэша), протоколу, используемому в СУБД InterSystems Caché. Преимущество ECP заключается в инновационном подходе к кэшированию данных. В рамках данного протокола пользовательские процессы, которые работают на серверах приложений (или ECP-клиентах) СУБД и обслуживают запросы, получают доступ к локальному кэшу недавно использованных данных. И только если этих данных недостаточно, ECP-клиент обращается к базе данных. С помощью протокола ECP выполняется автоматическое управление кэшем: наиболее часто используемые данные сохраняются в кэше, часто обновляемые данные периодически реплицируются, обеспечивая постоянное целостность и корректность данных на всех ECP-клиентах. При этом внутренний алгоритм InterSystems Caché предполагает, что базы данных синхронизируются между ECP-клиентом и ECP-сервером.

Фактически использование технологий СУБД Caché позволяет легко и быстро масштабировать нагрузку по серверам приложений, обеспечив таким образом подключение большого числа пользователей к одному серверу базы данных благодаря использованию ECP-протокола.

Так как информация, которую затребовал тот или иной пользователь, может быть задействована на нескольких ECP-клиентах, необходимо блокировать данные на короткий период времени, быстро выполнять транзакции, не выполняя внутренних вычислений. И мы успешно это реализовали. Данная технология позволяет нам эффективно масштабировать систему в ситуации, когда используются один сервер базы данных и несколько серверов, на которых работают пользовательские процессы. Технологическая особенность СУБД Caché заключается в том, что она поддерживает корректность транзакций в рамках одного ECP-сервера вне зависимости от количества ECP-клиентов, которые к ней подключены. В случае, когда у нас один ECP-сервер и множество ECP-клиентов, эта задача великолепно решается, потому что все транзакции идут на одном сервере базы данных.

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

В СЭД ЛЕТОГРАФ реализован механизм шардинга, благодаря которому мы на уровне настроек системы (без применения программирования), даем возможность описать правила и принципы разнесения самих данных по разным серверам БД. Несмотря на то, что с точки зрения структуры баз данных информация, хранящаяся на каждом сервере одинакова, сама информация отличается принципиально в зависимости от организации или каких-либо других признаков, которые являются значимыми для конкретной задачи. Используя технологию шардинга можно добиться, что в 95-99 % случаев пользователи будут работать только со своей «порцией данных», и не потребуется в рамках сессии обращаться к разным серверам БД.

На возможности масштабирования СЭД ЛЕТОГРАФ влияет и то, данные могут по разному обрабатываться. Например, в документы (даже созданные несколько лет назад) могут вноситься изменения, а в журнал действий пользователей записи только добавляются (ни одна запись не может быть ни удалена, ни изменена). Механизмы, которые используются в СЭД ЛЕТОГРАФ, позволяют дополнительно повысить производительность системы и улучшить масштабирование за счет ведения таких журналов на отдельных серверах БД – причем, как в случае односерверной, так и многосерверной конфигурации. Такой подход ориентирован на снижение нагрузки на основные сервера БД.

Аналогичная ситуация возникает и контентом (“информационным содержанием” СЭД). Так как система ЛЕТОГРАФ работает с большим объемом контента – это терабайты данных, миллионы файлов и документов – разумно предположить, что контент, который попадает в систему, ни при каких условиях не должен пострадать. Поэтому мы также выносим хранение файлов на отдельные сервера баз данных и обеспечиваем таким образом дополнительно горизонтальное масштабирование.

Программное обеспечение фронт-энда

В качестве фронт-энда в СЭД ЛЕТОГРАФ используются Apache и HAProxy. HAProxy отвечает за балансировку нагрузки между веб-серверами Apache. HAProxy, как показал опыт работы системы, зарекомендовал себя как наиболее эффективное решение, способное обеспечить поддержку работы большого числа пользователей и необходимый контроль за отказоустойчивостью.

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

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

Пример реализации проекта

Архитектура ЛЕТОГРАФ позволяет добиться существенных результатов в сокращении времени отклика и повышении производительности системы. В рамках одного из наших проектов в СЭД хранится 23,5 Тбайт данных. Из них 14,7 Тбайт (63%) приходится на потоки (“прикрепленные к карточкам файлы”), 3,5 Тбайт (15%) – на отчетные формы, такие как таблицы отчетов, которые формируются в асинхронном режиме, могут запускаться как по расписанию, так и по требованию пользователя и представляют собой сводную таблицу, любые данные в которой можно детализировать до объекта. Еще 1,6 Тбайт (7%) – это протокол пользовательских операций, а все остальное (16%) – данные карточек и индексы.

В данной системе работает более 11 тыс. пользователей, 2 тыс. из них работают одновременно, а в дни пиковой нагрузки число одновременно работающих в СЭД сотрудников превышает 3 тыс. Количество записей в журнале уже превысило 5,5 млрд, а учетных карточек – почти достигло полумиллиарда.

В качестве сервера базы данных в данном проекте установлен отказоустойчивый кластер из двух физических серверов с тремя инсталляциями СУБД, а также резервный сервер. Десять серверов приложений (и один резервный) обрабатывают пользовательские сессии и обеспечивают формирование асинхронных отчетов. 2 сервера HAProxy выполняют функции балансировщиков. В случае проблем с одним из серверов, выполняется автоматическая передача его IP-адреса на другой сервер. Также предусмотрены сервер индексации файлов и сервер распознавания (обеспечивающий распознавание текста отсканированных бумажных документов при размещении электронных образов в систему).

Резюме

В СЭД ЛЕТОГРАФ предусмотрено большое количество разнообразных механизмов масштабирования. Мы предлагаем своеобразный пирог, в основе которого лежит сервер (физический или виртуальный), на который устанавливается операционная система. Поверх нее стоит СУБД InterSystems Caché, внутри которой располагается код платформы. А уже над ним – настройки системы ЛЕТОГРАФ, благодаря которым СЭД полностью конфигурируется. И такой пирог размещен на каждом сервере. Сервера между собой связаны определенным образом за счет выбранных конфигураций. И последний слой – это HAProxy, распределяющий между серверами запросы пользователей. Такая архитектура позволяет нам поддерживать масштабирование и обеспечивать все необходимые механизмы мониторинга. В результате конечные пользователи получают быстро работающую СЭД, а ИТ-специалисты – простую в управлении и обслуживании, унифицированную систему, без огромного числа составляющих, которые в случае высоконагруженных приложений приходится постоянно контролировать и администрировать. Кроме того, в зависимости от изменения потребностей организации СЭД ЛЕТОГРАФ легко переконфигурировать, добавив новые серверы или дисковые возможности.


Данный материал является частной записью члена сообщества Club.CNews.
Редакция CNews не несет ответственности за его содержание.

Представим, что мы сделали сайт. Процесс был увлекательным и очень приятно наблюдать, как увеличивается число посетителей.

Но в какой-то момент, траффик начинает расти очень медленно, кто-то опубликовал ссылку на ваше приложение в Reddit или Hacker News , что-то случилось с исходниками проекта на GitHub и вообще, все стало как будто против вас.

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

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

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

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

Оптимизация

Первым делом, стоит провести обновление до последней версии PHP (текущая версия 5.5, использует OpCache ), проиндексировать базу данных и закэшировать статический контент (редко изменяющиеся страницы вроде About , FAQ и так далее).

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

Идея заключается в следующем: вы помещаете Nginx перед вашим Apache-сервером (Ngiz будет frontend -сервером, а Apache — backend ), и поручаете ему, перехват запросов на статические ресурсы (т.е. *.jpg , *.png , *.mp4 , *.html …) и их обслуживание БЕЗ ОТПРАВЛЕНИЯ запроса на Apache.

Такая схема называется reverse proxy (её часто упоминают вместе с техникой балансировки нагрузки, о которой рассказано ниже).

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

Существует два типа масштабирования – горизонтальное и вертикальное .

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

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

Представьте, что у вас имеется веб-сервер, обслуживающий веб-приложение. Этот сервер имеет следующие характеристики 4GB RAM , i5 CPU и 1TB HDD .

Он хорошо выполняет возложенные на него задачи, но чтобы лучше справляться с нарастающим трафиком, вы решаете заменить 4GB RAM на 16GB, устанавливаете новый i7 CPU и добавляете гибридный носитель PCIe SSD/HDD .

Сервер теперь стал более мощным и может выдерживать увеличенные нагрузки. Именно это и называется вертикальным масштабированием или «масштабированием вглубь » – вы улучшаете характеристики машины, чтобы сделать её более мощной.

Это хорошо проиллюстрировано на изображении ниже:

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

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

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

Если количества ядер процессора недостаточно для выполнения имеющихся потоков, то не имеет значения, насколько мощный установлен CPU – сервер все равно будет работать медленно, и заставит посетителей ждать.

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

В данном случае, используется балансировщик нагрузки (load balancer ) – машина или программа, которая занимается тем, что определяет, какому кластеру следует отправить очередной поступивший запрос.

А машины в кластере автоматически разделяют задачу между собой. В этом случае, пропускная способность вашего сайта возрастает на порядок по сравнению с вертикальным масштабированием. Это также известно как «масштабирование вширь ».

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

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

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

При горизонтальном масштабировании происходит следующее:


Заметьте, что два описанных способа масштабирования не являются взаимоисключающими – вы можете улучшать аппаратные характеристики машин (также называемых нодами — node ), используемых в масштабированной вширь кластерной системе.

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

Сложности с разделением данных

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

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

Постоянный балансировщик нагрузки

Постоянный балансировщик нагрузки запоминает, где обрабатывался предыдущий запрос того или иного клиента и, при следующем запросе, отправляет запрос туда же.

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

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

Это становится еще одним узким местом. А что, если единственный балансировщик нагрузки сам выйдет из строя и вся информации о расположении клиентов на серверах будет утеряна? Кто будет управлять балансировкой? Замысловатая ситуация, не правда ли?

Разделение локальных данных

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

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

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

Замечу, что обработчики сессий в PHP могут быть переопределены – вы можете определить свой собственный класс/функцию для управления сессиями.

Использование базы данных

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

Хотя данный подход работает достаточно хорошо, в случае большого трафика, база данных становится не просто уязвимым местом (потеряв её, вы потеряете все), к ней будет много обращений из-за необходимости записывать и считывать данные сессий.

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

Использование общей файловой системы

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

Это еще одна потенциальная опасность, даже более опасная, чем в случае с базой данных, описанном выше. Активация общей файловой системы очень проста: смените значение session.save_path в файле php.ini , но категорически рекомендуется использовать другой способ.

Если вы все-таки хотите реализовать вариант с общей файловой системой, то есть гораздо более лучшее решение — GlusterFS .

Memcached

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

Какое-либо постоянство отсутствует – данные о входе будут храниться до тех пор, пока memcached -сервер запущен и имеется свободное пространство для хранения этих данных.

Вы можете быть удивлены – разве оперативная память не отдельна для каждой машины? Как применить данный способ к кластеру? Memcached имеет возможность виртуально объединять всю доступную RAM нескольких машин в единое хранилище:

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

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

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

Использовать этот способ в PHP-приложениях очень легко: нужно изменить значение в файле php.ini :

session.save_handler = memcache session.save_path = "tcp://path.to.memcached.server:port"

Redis Cluster

Redis это не SQL хранилище данных, расположенное в оперативной памяти, подобно Memcached , однако оно имеет постоянство и поддерживает более сложные типы данных, чем просто строки PHP-массива в форме пар «key => value ».

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

Если сравнивать Redis с решениями вроде Memcached , то он представляет собой нечто среднее между обычной базой данных и Memcached .

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

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

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

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

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

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

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

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

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

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

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

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

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

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


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

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

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

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

К концу 2012 года более 50% приложений работающих на х86 платформе виртуализированы. Вместе с тем виртуализировано только 20% бизнес критических приложений.

Это из-за того что ИТ отделы не доверяют платформам виртуализации? Считают ли они платформы виртуализации не достаточно стабильными для поддержки работы критически важных приложений?

За последние 10 лет VMware доказала что виртуализация это уже реальность, и, фактически, виртуализированные приложения часто более стабильны, когда работают на инфраструктуре под управлением VMware.

Тогда если доверие или стабильность не являются проблемой в чём же причина того что ИТ отделы еще не виртуализировали оставшиеся приложения?

Scale out
Scale out или горизонтальное масштабирование - добавление новых ресурсов в инфраструктуру, например, серверов в кластер.

Так как цены продолжают падать, а производительность расти то дешёвые, commodity (широкого потребления) сервера являются идеальным решением для горизонтального масштабирования, и могут быть собраны в большие кластера для объединения вычислительных ресурсов.

Последние семь лет архитекторы инфраструктур на VMware молились на горизонтальное масштабирование. Кто-то может аргументировать за использование именного этого подхода, но он тоже имеет свои нюансы, и всё зависит от требований бизнеса. Плюс горизонтального масштабирования в том, что commodity сервера дёшевы, и в случае выхода сервера из строя это влияет на небольшое количество ВМ. Минус в бОльших затратах на лицензии на vSphere, большие требования к площади ЦОД, и обычно такие commodity сервера не обладают большими вычислительными ресурсами.

Scale up
Вертикальное масштабирование - добавление вычислительных ресурсов в какой-то уже используемый сервер. Обычно это процессоры или оперативная память.

Обычно такие сервера довольно мощные - с поддержкой 4 процессоров и 512ГБ памяти. Кроме того встречаются системы с 8 процессорами и 1ТБ памяти, а некоторым повезло увидеть даже 16-ти процессорные сервера с 4ТБ памяти. И нет, это не мейнфреймы или что-то типа того, это сервера на основе классической х86 архитектуры.

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

  • Недостаточные возможности по масштабированию. Нагрузки с высокими требованиями к объёму вычислительных ресурсов являются проблемой из-за ограниченного объёма ресурсов доступных с дешёвыми commodity серверами.
  • Недостаточная надёжность. Commodity оборудование или аппаратное обеспечение использующее такие компоненты может быть менее надёжным. Проблему надёжности можно решить с помощью функций о которых я расскажу в следующих статьях.
  • Увеличение сложности управления и рост операционных расходов. Легче управлять 100 серверами, а не 1000, ну и, как следствие, 10 серверами управлять проще чем 100. Тоже самое касается и операционных расходов - 10 серверов гораздо дешевле поддерживать чем 100.
Вертикальное масштабирование отлично подходит для бизнес критических приложений с их огромными требованиями к ресурсам. Привет, Monster VM! Все эти прожорливые критичные базы данных, огромные ERP системы, системы аналитики больших данных, JAVA приложения и так далее и тому подобное получат прямую выгоду от вертикального масштабирования.

С выходом vSphere 5 количество ресурсов, доступных одной ВМ выросло в 4 раза.

А с выходом vSphere 5.1 монструозные ВМ могут быть еще монструознее.

Для того чтобы vSphere 5.1 могла запустить ВМ-монстра планировщику необходимо иметь и спланировать запуск потоков на 64 физических процессорах. Не так много серверов, которые могут поддерживать столько ядер, а серверов с поддержкой 16 сокетов и 160 ядер и того меньше.

Всего существует два типа вертикального масштабирования серверов: glueless и glued. На русский язык эти слова переводятся так: без интегрирующих технологий и с интегрирующими технологиями, соответственно.

Glueless архитектура
Данная архитектура была разработана в Intel, и представлена в Intel Xeon E7.

Для связи между устройствами ввода-вывода, сетевыми интерфейсами и процессорам используется специально разработанная шина QPI.

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

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

Преимущества такой архитектуры:

  • Нет необходимости в специальной разработке или специализации у производителя серверов
  • Любой производитель серверов может выпускать 8-ми процессорные сервера
  • Снижается стоимость как 4-ёх так и 8-ми процессорного сервера
Недостатки:
  • Общая стоимость владения растёт при горизонтальном масштабировании
  • Архитектура ограничена 8-ми процессорными серверами
  • Тяжело поддерживать целостность кэша при увеличении сокетов
  • Нелинейный рост производительности
  • Соотношение цены к производительности падает
  • Неоптимальная эффективность при использовании больших ВМ
  • Вплоть до 65% пропускной способности шины уходит на широковещательные сообщения болтливого протокола QPI
В чём же причина болтливости протокола QPI? Для того чтобы достичь целостности процессорного кэша каждая операция на чтение должна быть реплицирована на все процессоры. Это можно сравнить с широковещательным пакетом в IP сети. Каждый процессор должен проверить у себя затребованную строку памяти, и в случае использования последней версии данных предоставить её. В случае если актуальные данные находятся в другом кэше протокол QPI с минимальными задержками копирует данную строку памяти из удалённого кэша. Таким образом на репликацию каждой операции чтения тратиться пропускная способность шины и такты кэша, которые могли бы использоваться для передачи полезных данных.

Основные приложения, производительность которых страдает от недостатков протокола QPI это Java приложения, большие БД, чувствительные к задержкам приложения.

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

Glued архитектура
Для решения описанных выше проблем разработчики аппаратного обеспечения разработали glued архитектуру. Данная архитектура использует внешний контроллер нод для организации взаимосвязи островков QPI - кластеров процессоров.


Intel QPI предлагает специальное масштабируемое решение - eXternal Node-Controllers (или XNC), практическая реализация которого разрабатывается сторонними OEM компаниями. Внешний контроллер нод, используемый начиная с Intel Xeon E7-4800, со встроенным контроллером памяти, включает в себя также систему Cache Coherent Non-Uniform Memory Access (ccNUMA) задача которой отслеживать актуальность данных в каждой строке памяти процессорного кэша были актуальные данные.

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




Top