Статьи

Автоматическое масштабирование по комплексной телеметрии

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

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

Как я должен думать об автомасштабировании?

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

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

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

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

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

Оба являются бременем обслуживания и требуют постоянного контроля и периодического вмешательства человека.

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

Первые шаги: масштабирование процессора

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

Использование CPU — это хорошо понятная вещь, о которой стоит поговорить; нет необходимости в дополнительном обучении, чтобы рассуждать о поведении системы, и это отлично подходит для принятия решений в команде. Кроме того, загрузка ЦП фактически бесплатна с точки зрения инженерных усилий, поскольку это стандартная метрика CloudWatch .

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

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

1
2
3
4
5
while (true) {
        if (have_work) {
            ...
        }
    }

Почему? Это быстрее, чтобы разбудить поток занятого ожидания. , Erlang — это язык, разработанный для мягких приложений реального времени; для ВМ имеет смысл расставить приоритеты для задержки.

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

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

Однопаровая телеметрия

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

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

Если вы работаете на Java, Dropwizard Metrics — подходящая библиотека; в Эрланге, экзометр . Каждая из этих библиотек имеет особую направленность, которая делает их ценными: они объединяются на компьютере и отправляются во внешние службы. Рассмотрим этот пример из документации Dropwizard Metrics:

1
2
3
4
5
6
private final Histogram responseSizes = metrics.histogram(name(RequestHandler.class, "response-sizes"));
     
    public void handleRequest(Request request, Response response) {
        // etc
        responseSizes.update(response.getContent().length);
    }

Здесь metrics — это экземпляр MetricsRegistry , хранилища в локальной памяти для агрегирования телеметрии. MetricsRegistry может быть MetricsRegistry помощью пользовательского кода — что будет важно в следующем разделе этого поста — и по умолчанию существует несколько объектов Reporter которые отправляют содержимое MetricsRegistry через определенные промежутки времени. Экзометр имеет аналогичные возможности .

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

  • транзакций в секунду (TPS)
  • задержка транзакций на несколько процентилей в секунду (LPS)
  • непроверенные исключения в секунду (EPS)

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

В AdRoll мы увидели, что при переходе от масштабирования ЦП к масштабированию TPS 15-процентное снижение количества экземпляров машин без снижения качества обслуживания. Почему? Оказывается, 15 процентов было фактором шероховатости процессора для нашей системы.

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

Совокупная пользовательская метрика

Автоматическое масштабирование на задней стороне однопотоковой телеметрии прекрасно, но не без проблем. Обратите внимание, что в предыдущем разделе я сказал «ключевые показатели» и перечислил три. Какой из них выбрать? Давайте пройдемся по мыслительному упражнению.

Скажем, цель автоматического масштабирования — 1000 TPS на машину. При скорости 500 TPS система автомасштабирования удалит экземпляры из группы автомасштабирования; на 1500 TPS, он добавит их. Что произойдет, если система сообщит о транзакции, только если в ее обработке не было исключений? Вы будете недооценивать «реальные» транзакции и перерасход.

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

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

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

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

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

1
Index = (1.0*TPS + 15.0*EPS) - 2.0*LPS

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

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
-module(stat).
     
    -export([index/0]).
     
    index() -> (per_second(tps) + per_second(eps)) - per_second(lps).
     
    per_second(Metric) ->
        PerMinute = case exometer:get_value(Metric, one) of
                        {ok, [{one, PM}]} ->  PM;
                        {error, not_found} -> 0.0
                    end,
        PerMinute * (1/60.0) * weight(Metric).
     
    weight(tps) -> 1.0;
    weight(eps) -> 15.0;
    weight(lps) -> 2.0;
    weigth(_)   -> 1.0.

После этого настройте exometer на периодический опрос stat:index/0 и отправку отчета в CloudWatch. Масштаб по индексу, и вы в бизнесе.

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

Вывод

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