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

Итак, что такое высоконагруженная система? Ответ на этот вопрос стоит начать с описания качественных свойств такого рода систем.

Традиционные качества высоконагруженной системы Link to heading

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

  • это не вся правда;
  • приведенные факторы являются количественными, а не качественными.

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

Многопользовательская система Link to heading

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

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

Если посмотреть на статистику Московского метрополитена за 2010 год, то окажется что средняя часовая нагрузка на систему максимальна в диапазоне от 8 до 9 часов утра1. За этот час через турникеты проходят приблизительно 720 тысяч человек. Что порождает необходимость не менее 200 раз в секунду проверять статус предъявленных проездных и принимать решение о пропуске того или иного человека через турникет. В Интернете существует масса высоконагруженных ресурсов с подобными показателями пропускной способности. Например, статистика по StackOverflow за тот же 2010-й год показывает что их средняя пропускная способность находится в диапазоне 100-150 хитов в секунду2.

Определенно у метрополитена более высокие требования к пропускной способности. Но значит ли это что Московский метрополитен можно считать более “высоконагруженным” чем StackOverflow? Вряд ли, в частности потому что эти две системы оперируют несравнимыми объемами информации, о чем мы поговорим позже.

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

Распределенная система Link to heading

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

  • необходимости обрабатывать возрастающие объемы данных;
  • необходимости “живучести” системы в случаях отказа части серверов.

Но обо всем по порядку…

Я наверное не ошибусь если скажу что большинство высоконагруженных приложений являются Интернет-приложениями (позже мы еще вернемся к состоятельности этой гипотезы). А отличительной особенностью современного Интернета основанного на концепции Web 2.0 является тот факт, что сами пользователи генерируют данные, которые они сами же в итоге и потребляют. Это приводит к тому, что чем больше у вас пользователей, тем больше потенциальный объем хранимых данных.

Требование обработки больших объемов данных может существенно осложнить жизнь. Под “большим объемом” я подразумеваю такой объем информации, который не может эффективно обработать одна машина. В большинстве случаев, это объем превышающий объем доступной на сервере оперативной памяти. То есть приходится тем или иным образом распределять данные между несколькими машинами, каждая из которых обрабатывает свой небольшой кусочек данных, но делает это эффективно, без page fault’ов (не используя swap) и прочих неприятностей. Необходимость эффективной обработки данных диктуется другим очень важным качеством высоконагруженных систем, – интерактивностью, о котором будет сказано ниже.

Но большие объемы данных – это не все. Ко всему к этому хочется чтобы система работала в режиме 24x7 без остановок и перерывов. Но вот незадача, любое даже самое надежное оборудование иногда выходит из строя. Встает естественная задача обеспечения доступности системы в случаях отказа оборудования.

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

Позитивная динамика по пользователям и данным Link to heading

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

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

Интерактивность Link to heading

И тут мы подходим к своеобразной финальной ноте в аккорде качеств highload систем, если позволите так выразиться. Интерактивность – одно из основополагающих качеств высоконагруженной системы. Интерактивность подразумевает, что пользователь после того как послал запрос сидит и ждет ответа, а люди как известно ждать не любят. При этом большинство Интернет-приложений о которых мы говорим не являются критическими важными в жизни людей. Twitter, Flickr, Facebook и т.д. это все круто конечно, но если они будут отвечать непомерно долго, я найду чем занятся еще. Наша жизнь от них не зависит (прогрессирующие формы задротства у некоторых особо аддиктивных индивидов не в счет), а это значит что эти приложения должны занимать минимум нашего времени. То есть отвечать за приемлимое время. Это контрастирует, например, с системами пакетной обработки данных, в которых время ответа системы вторично.

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

Управление ресурсами Link to heading

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

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

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

Высоконагруженная система – это интерактивная распределенная система которая требует постоянного контроля за собственными ресурсами. В противном случае она перестает работать.

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

  • рост аудитории;
  • рост объема данных;
  • изменения паттернов поведения аудитории, в том числе и сезонные.

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

  • как решать существующие задачи используя меньше ресурсов (практически все NoSQL БД, неблокирующий I/O, оптимизация и тюнинг);
  • как имея больше ресурсов решать пропорционально больший объем задач (message queueing, распределенные вычисления, распределенные БД, параллелизм).

Эту дихотомию я уже затрагивал ранее в заметке Performance vs. Scalability.

Фактически речь на таких конференциях идет в основном о различных способах адекватного управления аппаратными ресурсами в контексте баз данных, языков программирования, операционных систем, алгоритмов, моделей ввода/вывода, вычислительных парадигм и т.д.

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

Высоконагруженный проект – это Интернет приложение Link to heading

Если исходить из того что неотъемлемой частью высоконагруженного проекта является постоянный рост данных и аудитории, то становится понятно почему высоконагруженные проекты – это поголовно Интернет приложения.

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

В сфере High Performance Computations приложения могут выполнять просто гигансткое количество операций в единицу времени. Больше чем любое Интернет-приложение. Но это количество зависит только от объема входных данных, а также алгоритма обработки (например, от точности моделирования, если речь идет о моделировании динамических систем). Тяжело придумать причину почему нагрузка на такую систему может вырасти сама по себе без вмешательства персонала ее сопровождающего.

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

Работая в Highload проекте Link to heading

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

  • какие bottleneck’и есть в системе по ресурсам и как их устранить?
  • каков запас системы по ресурсам учитывая естественный рост аудитории/данных?
  • что делать при нехватке того или иного ресурса? (например, можно за счет RAM сэкономить CPU).

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

Это приводит нас к cписку первостепенных задач которые стоят перед разработчиками в контексте высокой нагрузки:

  • создание инфраструктуры предоставляющей качественную обратную связь по утилизации аппаратных ресурсов системы (мониторинг, self-аудит приложений);
  • определение звеньев системы нуждающихся в масштабировании в ближайшем времени и выбор стратегии масштабирования этих звеньев;
  • определение toolbox’а позволяющего решать типовые задачи эффективно по аппаратным ресурсам (базы данных, очереди сообщений, языки программирования, библиотеки и т.д.).

В состоянии гонки Link to heading

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

Что же остается? Не так много на самом деле. Сделать так чтобы возможности системы были всегда на шаг впереди ее потребностей.