Поделиться через


Рекомендации по настройке производительности для Storm в HDInsight и Azure Data Lake Storage 1-го поколения

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

Предварительные требования

Настройка параллелизма топологии

Возможно, повысить производительность поможет увеличение степени параллелизма операций ввода-вывода для Data Lake Storage 1-го поколения. Топология Storm имеет набор конфигураций, которые определяют параллелизм:

  • Количество рабочих процессов. Рабочие роли равномерно распределяются между виртуальными машинами.
  • Количество экземпляров исполнителей spout.
  • Количество экземпляров исполнителей bolt.
  • Количество задач spout.
  • Количество задач bolt.

Предположим, что в кластере с 4 виртуальными машинами и 4 рабочими процессами работают 32 исполнителя и 32 задачи для элемента spout, а также 256 исполнителей и 512 задач для элемента bolt. Для этой ситуации справедливо следующее.

Каждый супервизор, то есть рабочий узел, имеет один рабочий процесс виртуальной машины Java (JVM). Этот процесс JVM управляет 4-мя потоками spout и 64-ю потоками bolt. Внутри каждого потока задачи выполняются последовательно. В условиях описанной выше конфигурации каждый поток spout выполняет одну задачу, а каждый поток bolt — две.

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

  • Головной узел (называемый в Storm Nimbus) используется для отправки заданий и управления ими. Эти узлы не оказывают влияния на степень параллелизма.
  • Узлы супервизора. Этот объект HDInsight соответствует рабочему узлу на виртуальной машине Azure.
  • Рабочие задачи — это процессы Storm, выполняемые на виртуальных машинах. Каждая рабочая задача соответствует экземпляру виртуальной машины Java. Storm распределяет указанное число рабочих процессов между рабочими узлами максимально равномерно.
  • Количество экземпляров исполнителей spout и bolt. Каждый экземпляр исполнителя соответствует потоку, который выполняется в рабочих процессах (на виртуальных машинах Java).
  • Задачи Storm. Это логические задачи, которые выполняет каждый из потоков. Это не меняет уровень параллелизма, поэтому следует оценить, нужны ли вам несколько задач на каждый исполнитель.

Достижение максимальной производительности Data Lake Storage 1-го поколения

Чтобы достичь оптимальной производительности при работе с Data Lake Storage 1-го поколения, следует сделать следующее.

  • Объедините маленькие добавления в пакеты большего размера (в идеале размером по 4 МБ).
  • Выполняйте максимально возможное количество одновременных запросов. Так как каждый поток элементов bolt выполняет чтение с блокировкой, желательно выполнять от 8 до 12 потоков на каждое ядро. Это позволит сохранить хорошую нагрузку на сетевой адаптер и ЦП. Крупная виртуальная машина позволяет выполнять большее число параллельных запросов.

Пример топологии

Предположим, что у вас есть кластер из восьми рабочих узлов на виртуальной машине Azure D13v2. Эта виртуальная машина имеет восемь ядер, то есть восемь рабочих узлов в совокупности предоставляют 64 ядра.

Предположим, что мы запускаем восемь потоков элементов bolt на ядро. Так как у нас есть 64 ядра, мы получаем 512 экземпляров исполнителей элемента bolt (т. е. потоков). Например, мы начинаем с одной виртуальной машины Java на каждую виртуальную машину, а для достижения параллелизма используем в основном параллелизм потоков внутри виртуальной машины Java. Это означает, что нам нужно восемь рабочих задач (по одной на каждую виртуальную машину Azure) и 512 исполнителей элемента bolt. В такой конфигурации Storm пытается распределить рабочие процессы равномерно между рабочими узлами (узлами супервизора), предоставляя каждому рабочему узлу одну виртуальную машину Java. В пределах супервизоров Storm пытается распределить исполнители равномерно между ними, предоставляя каждому супервизору (а следовательно, каждой виртуальной машине Java) по восемь потоков.

Настройка дополнительных параметров

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

  • Число виртуальных машин Java на рабочий узел. Если вы размещаете в памяти структуру данных большого объема (например, таблицу подстановки), потребуется отдельный экземпляр этой структуры для каждой виртуальной машины Java. Кроме того, можно распределить структуру данных на несколько потоков, если число виртуальных машин Java сравнительно невелико. Количество виртуальных машин Java не так сильно влияет на производительность операций ввода-вывода элементов bolt, как число потоков на этих машинах. Мы рекомендуем использовать простое правило: выделять одну виртуальную машину Java для каждой рабочей роли. Это количество можно изменять в зависимости от того, какие функции выполняет объект bolt, и какая нужна обработка в приложении.
  • Количество экземпляров исполнителей spout. В примере выше элементы bolt используются для записи в Data Lake Storage 1-го поколения, поэтому количество элементов spout не влияет непосредственным образом на производительность элементов bolt. В зависимости от объема обработки или операций ввода-вывода в элементе spout, для повышения производительности можно попробовать изменить количество spout. Убедитесь, что у вас есть достаточно элементов spout, чтобы загрузить все элементы bolt. Скорость вывода элементов spout должна соответствовать пропускной способности элементов bolt. Итоговая конфигурация зависит от работы spout.
  • Число задач. Каждый элемент bolt выполняется как один поток. Увеличение количества задач для каждого элемента bolt не повышает уровень параллелизма. Они могут обеспечить преимущество только в том случае, если на процесс подтверждения кортежа затрачивается большая часть времени выполнения элемента bolt. Оптимально объединить несколько кортежей в крупную операцию добавления, прежде чем отправлять подтверждение из элемента bolt. Поэтому в большинстве случаев увеличение количества задач не дает дополнительных преимуществ.
  • Локальное группирование или группирование в случайном порядке. Если включить этот параметр, все кортежи отправляются в bolt в одном рабочем процессе. Это уменьшает межпроцессное взаимодействие и количество сетевых вызовов. Мы рекомендуем использовать этот параметр для большинства топологий.

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

Настройка spout

Можно изменить следующие параметры для настройки spout.

  • Время ожидания кортежа: topology.message.timeout.secs. Этот параметр определяет время, в течение которого сообщение должно завершиться и получить подтверждение. По истечении этого времени для сообщения регистрируется сбой.

  • Максимальный объем памяти для каждого рабочего процесса: worker.childopts. Этот параметр позволяет указать дополнительные параметры командной строки для рабочих ролей Java. Наиболее часто используемый здесь параметр — XmX, который определяет максимальный объем памяти, выделенный для кучи виртуальных машин Java.

  • Максимальное количество ожидающих spout: topology.max.spout.pending. Этот параметр определяет максимально допустимое число активных (не подтвержденных на всех узлах в топологии) кортежей для каждого потока spout в любой момент времени.

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

Настройка bolt

При записи в Data Lake Storage 1-го поколения установите для политики размера синхронизации (буфер на стороне клиента) значение 4 МБ. Очистка или операция hsync() выполняется только тогда, когда размер буфера достигает этого значения. Драйвер Data Lake Storage 1-го поколения на виртуальных машинах рабочих ролей автоматически выполняет эту буферизацию, если пользователь не выполняет операцию hsync() явным образом.

По умолчанию в Data Lake Storage 1-го поколения для объекта bolt Storm определен параметр политики размера синхронизации (fileBufferSize), который можно использовать для настройки этого параметра.

В топологиях с интенсивным выполнением операций ввода-вывода желательно настроить запись в отдельный файл для каждого потока bolt и установить политику ротации файлов (fileRotationSize). Когда файл достигает определенного размера, поток автоматически очищается и выполняется запись в новый файл. Рекомендуемый размер файла для ротации составляет 1 ГБ.

Обработка данных кортежа

В Storm элемент spout удерживает кортеж, пока не получит явное подтверждение от элемента bolt. Если bolt уже прочитал кортеж, но не подтвердил его, для spout не гарантируется сохранение данных в серверной части Data Lake Storage 1-го поколения. После подтверждения кортежа элемент bolt гарантированно сохраняет данные, поэтому элемент spout может удалить исходные данные, независимо от того, откуда он их считывает.

Для обеспечения максимальной производительности Data Lake Storage 1-го поколения настройте в bolt буфер для данных кортежа размером 4 МБ. Передавайте эти данные в Data Lake Storage 1-го поколения одной операцией записи размером 4 МБ. После успешной записи данных в хранилище (путем вызова hflush()) элемент bolt может отправить элементу spout подтверждение обработки данных. Это выполняет приведенный здесь пример элемента bolt. Вполне допустимо удерживать большее количество кортежей до вызова hflush() и подтверждения кортежей. Однако это увеличивает число активных кортежей, которые должен удерживать элемент spout. Таким образом увеличивается объем памяти, необходимый для каждой виртуальной машины Java.

Примечание

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

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

  • Уменьшите количество элементов bolt, чтобы заполнять меньше буферов.
  • Создайте политику на основе времени или на основе количества, которая будет запускать операцию hflush() после каждых x операций сброса данных или через каждые y миллисекунд, а затем подтверждать накопленные кортежи.

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

Мониторинг топологии в Storm

Выполнение топологии можно отслеживать в пользовательском интерфейсе Storm. Вот основные параметры, на которые следует обращать внимание.

  • Общая задержка выполнения процесса. Это среднее время, за которое один кортеж создается элементом spout, обрабатывается элементом bolt и подтверждается.

  • Общая задержка процесса bolt. Это среднее время, проведенное кортежем в элементе bolt до получения подтверждения.

  • Общая задержка выполнения bolt. Это среднее время, затраченное элементом bolt на выполнение метода execute.

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

  • Емкость. Это мера занятости вашей системы. Если это значение равно 1, элементы bolt работают с максимально возможной скоростью. Если это значение меньше 1, необходимо увеличить параллелизм. Если значение больше 1, уменьшите параллелизм.

Устранение распространенных неполадок

Здесь описано несколько типичных сценариев устранения неполадок.

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

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

  • Высокая задержка выполнения bolt. Это означает, что метод execute() элемента bolt выполняется слишком долго. Оптимизируйте код или изучите настройки размеров и процессов для записи.

Регулирование Data Lake Storage 1-го поколения

Если вы достигнете пределов пропускной способности, предоставленной Data Lake Storage 1-го поколения, вы увидите сбои задач. Проверьте журналы задач на наличие ошибок регулирования. Вы можете уменьшить параллелизм, увеличив размер контейнера.

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

  1. В разделе Ambari>Storm>Config (Настройка)>Advanced storm-worker-log4j (Расширенные параметры storm-worker-log4j) измените значение <root level="info"> на <root level=”debug”> . Перезапустите все узлы и службы, чтобы изменения конфигурации вступили в силу.
  2. Отслеживайте журналы топологии Storm на рабочих узлах (в разделе /var/log/storm/worker-artifacts/<TopologyName>/<port>/worker.log) на предмет Data Lake Storage 1-го поколения исключений регулирования.

Дальнейшие действия

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

Дополнительный пример для запуска есть в этом разделе GitHub.