Архитектура потоковой передачи: пример

Завершено

Теперь, когда мы узнали, как развивались потоковые архитектуры, рассмотрим одну конкретную платформу — Apache Samza.

Apache Samza

Проект Samza был разработан в компании LinkedIn как распределенная платформа потоковой обработки. Он преобразует входной поток сообщений в измененный выходной поток в процессе обработки с отслеживанием или без отслеживания состояния. Samza разрабатывали параллельно с Kafka (см. выше) — распределенной системой обмена сообщениями с низкой задержкой. Samza позволяет выполнять обработку сообщений из Kafka в режиме реального времени.

Samza делится на три слоя:

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

The three layers of a Samza application.

Рис. 9. Три слоя приложения Samza

Слой потоковой передачи и слой выполнения можно подключать и отключать. В реализации по умолчанию в качестве брокера потоковой передачи сообщений используется Kafka. Входные и выходные потоки представляют собой неизменяемые последовательности сообщений, которые можно секционировать между узлами. В пределах одного раздела сообщения упорядочивают и однозначно идентифицируются по смещению в пределах потока. Слой выполнения по умолчанию использует YARN, но можно применить и другой распространенный диспетчер ресурсов — Mesos. YARN упрощает приложению Samza задачу по обеспечению отказоустойчивости, а также развертывание и использование встроенных функций ведения журнала и изоляции ресурсов. Использование YARN с HDFS также позволяет Samza выгодно использовать размещение данных.

Samza также использует cgroups для обработки одноядерных контейнеров, которые запускают виртуальные машины Java для выполнения одной или нескольких задач в рамках одного задания. Cgroups — это функция ядра Linux, которая позволяет коллекции процессов иметь общую связь с ЦП, памятью и доступом к файловой системе. В Samza каждый контейнер при обработке сообщения логически выполняется как один поток в том смысле, что в любой момент времени в контейнере выполняется только одна задача. Обработка производится с помощью пользовательского кода, написанного с помощью API Samza.

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

Input and output streams in a Samza job.

Рис. 10. Входные и выходные потоки в задании Samza

Клиенты Samza запускают задания Samza в YARN. У Samza есть собственный мастер приложения, который договаривается о ресурсах с диспетчером ресурсов YARN. Диспетчер ресурсов YARN обращается к различным диспетчерам узлов, чтобы выделить ресурсы для приложения Samza. YARN запускает задачу SamzaContainers (Task Runners), которая выполняет пользовательский код, реализующий API Samza StreamTask. Часто они размещаются вместе в контейнерах для брокеров Kafka, чтобы обеспечить максимальную локальность данных.

A Samza job is split into tasks, which can be grouped within a container. As there is only one thread per container, only one task is active at any time.

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

Samza использует для повышения производительности горизонтальное масштабирование. Для этого увеличивается число задач в одном задании. Каждая задача работает с одним разделом из входных потоков задания. Таким образом, чтобы можно было выполнять больше параллельных задач, поток необходимо разбивать на большее число разделов. Об этом говорится выше в разделе о Kafka. Для каждой входящей темы запускается как минимум один экземпляр StreamTask на каждый раздел. Каждая задача потока независимо обрабатывает один раздел.

Samza applications run on YARN in isolated containers.

Рис. 12. Приложения Samza выполняются в YARN в изолированных контейнерах

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

Однако более интересные примеры применения потоковой обработки предполагают подключение нескольких потоков, агрегирование сообщений или принятие решений на основе определенного окна данных. Все эти сценарии требуют хранения сведений о состоянии. Samza обеспечивает устойчивость с помощью абстракции KeyValueStore. Каждый экземпляр StreamTask сохраняет состояние в отдельном встроенном хранилище данных на том же компьютере. По умолчанию Samza использует RocksDB — она обеспечивает низкую задержку и высокую пропускную способность, а также оптимизирована для записи. Использование внедренной базы данных сокращает расходы на дорогостоящие сетевые вызовы для запроса данных.

Ensuring durability of a task's local state using an embedded data store.

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

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

Each local embedded database writes to a changelog output stream.

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

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

Failure recovery in Samza.

Рис. 15. Восстановление сбоя в Samza

Проверьте свои знания

1.

Что из нижеперечисленного обеспечивает параллелизм в Samza?