Реал-тайм процессинг данных в AWS Cloud. Часть 1

    Всем привет!

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

    image

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

    Попробуем формализировать задачу.



    Исходные данные: десятки тысяч файлов, каждый из которых представляет собой несколько связанных матриц типа int и float. Размер одного файла колеблется и может составлять порядка 2-4 ГБайт. Все данные предполагается загружать в облачное хранилище.

    Возвращаемые значения: набор точек, по которым можно построить изображение высокого разрешения. Процесс обработки предполагает суммирование и находжение максимальных значений в массивах с заданными границами, а потому является довольно активным потребителем CPU time. Размеры результатов зависят от запроса со стороны пользователя — от ~50 КБайт до ~20 МБайт. Размер исходных обрабатываемых данных для формирования одного ответа превосходит размер ответа в 30-200 раз. То есть чтобы отправить 100 КБайт ответа, нужно прочесть и обработать порядка 3-20 МБайт.

    Требования:

    • Возможность для конечных пользователей использовать браузер или десктоп-приложение для навигации по данным.
    • Равный по скорости доступ для пользователей вне зависимости от их географического положения.
    • Одновременная работа 100+ пользователей c возможностью горизонтального масштабирования.
    • Рендеринг изображений с комфортной для работы скоростью — до 500мс на одно изображение.


    Исходные позиции:

    В качестве провайдера облачных технологий заказчик выбрал Amazon Web Services, используя Amazon S3 как “бесконечное” хранилище исходных данных и Amazon EC2 в качестве хостинга для рабочих узлов.

    Фронт-энд, который должен отдавать изображения браузерам и десктоп-клиенту, написан на Java. Расположен на Amazon EC2.

    Бэк-энд, определяющий бизнес-логику, включая контроль доступа к данным, написан на Java и расположен на другом инстансе EC2.

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

    С чего начать?



    С попытки решения проблемы “в лоб”! Что если создать одно приложение, обрабатывающее параллельно набор запросов от пользователей? Предлагается забирать данные с S3 и отдавать некую структуру, представляющую собой набор точек или рендерить готовое изображение.

    Набор возникающих трудностей очевиден:

    1. Средний объем ответа равен 4 МБайт. Для 100 одновременных или почти одновременных запросов суммарный объем результатов достингет 4 МБайт * 100 = 400 МБайт. Размер исходных данных превышает размер ответа в 30 и более раз. Значит, придется практически одновременно зачитать из хранилища не менее 30 * 400 МБайт ~ 12 ГБайт, а как максимум 200 * 400 МБайт ~ 80 ГБайт данных.
    2. Наличие 100 одновременных запросов, обработка каждого из которых требует процессорного времени, предполагает наличие сопоставимого количества CPU.
    3. Теоретическая максимальная пропускная способность сети между Amazon S3 и инстансом EC2 составляет 1 ГБит/c, то есть 125 МБайт/c. То есть, для того, чтобы зачитать [в лабораторных условиях] даже 12 ГБайт данных потребуется примерно 12 * 1024 / 125 ~ 98 секунд.
    4. Единственный инстанс никак не может обслуживать пользователей из разных частей планеты с равной скоростью.


    Amazon EC2 позволяет создавать разные по размеру инстансы, но самый большой из них — d2.8xlarge (36 x Intel Xeon E5-2676v3, 244 ГБайт ОЗУ) — решает только проблемы №1 и №2. Проблема №3 — время на загрузку данных — на два порядка превышает ожидаемую скорость возврата результатов. Кроме того, масштабируемость такого решения стремится к нулю.

    Готовое решение?



    Elastic MapReduce

    Для решения подобных задач AWS предоставляет облачный Elastic MapReduce, он же — hosted Apache Hadoop. С его помощью удается преодолеть все возникавшие трудности за счет распределения нагрузки между узлами кластера. Однако, в этом варианте появляются новые проблемы:

    1. Скорость старта Hadoop-задачи — секунды. Что в несколько раз медленнее, чем требуемое время формирования ответа.
    2. Необходимость предразогрева кластера и загрузки выбранных данных с S3 в HDFS. Это требует дополнительных телодвижений по выбору стратегии оперирования кластером (кластерами) для балансировки нагрузки.
    3. Результат доставляется на S3 или в HDFS, что требует дополнительной инфраструктуры по доставке его конечному пользователю.


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

    Apache Storm

    В качестве альтернативы, сохраняющей преимущества MapReduce-подхода, но позволяющей получать результат обработки в приближенном к реальному времени, хорошо подходит Apache Storm. Этот фреймворк использовался для нужд Twitter (обработка аналитических событий) и приспособлен для потоков задач с миллионными размерами очередей.

    Инсталляция Storm в AWS Cloud хорошо продумана: существует готовые деплоймент-скрипты, автоматически запускающие все необходимые узлы плюс инстанс Zookeeper для поддержания жизнеспособности системы.
    Однако, при ближайшем рассмотрении (был сделан прототип) выяснилось, что и такое решение обладает рядом недостатков:

    1. Изменение конфигурации Storm-кластера (добавление узлов, деплоймент новых версий) “на лету” происходит непрозрачно. Если быть совсем точным, то во многих случаях изменения гарантированно подхватываются только после перезапуска кластера.
    2. Концепция обработки сообщений в Storm в режиме RPC преполагает, как минимум, три стадии для реализации MapReduce: разделение работы на части, процессинг части работы, объединение результатов. Каждый из этих этапов в общем случае выполняется на собственном узле. В свою очередь, это ведет к дополнительной сериализации-десериализации бинарного контента сообщений.
    3. Не самый простой подход к интеграционному тестированию — поднятие целого тестового кластера требует ресурсов и времени.
    4. Навязчивый API (из разряда вкусовщины, но тем не менее).


    Концепт, построенный с помощью Storm, удовлетворял требованиям, в том числе по скорости. Но из-за перманентно возникающих задач по обслуживанию этого решения (пункты 1 и 3) и временным потерям из-за “лишней” сериализации (пункт 2) было решено от него отказаться.

    Elastic Beanstalk

    Еще одним вариантом было написание собственного приложения с размещением в Amazon Elastic Beanstalk. Такой вариант мог бы решить все проблемы одним махом: набор EC2-инстансов для распределения нагрузки на CPU и сеть, автоматическое масштабирование, метрики и поддержание жизнеспособности всех узлов. Но при ближайшем рассмотрении возникли сомнения:

    1. Vendor lock-in. После обсуждения с заказчиком выяснилось, что помимо разработки публичного сервиса в его планы входит и поставка коробочных решений с похожей функциональностью. И если альтернативу Amazon EC2 и Amazon S3 с аналогичным функционалом можно найти в интранет-ориентированных продуктах (например — линейка продуктов Pivotal), то адекватной замены Beanstalk нет.
    2. Недостаточная гибкость в настройках масштабирования. Статистика по запросам пользователей говорила о явных всплесках, привязанных ко времени начала рабочего дня. Но привязать пред-разогрев серверов ко времени суток система не позволяла. [Cовсем недавно такая возможность появилась].
    3. Не самый надежный сервис по доставке сообщений Amazon SQS, являющийся частью Beanstalk. Форумы разработчиков Amazon заполнены проблемами при работе с SDK этого сервиса.
    4. Комплексная процедура деплоймента.


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

    Велосипед



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

    (о которой — в следующей части статьи).
    Поделиться публикацией
    AdBlock похитил этот баннер, но баннеры не зубы — отрастут

    Подробнее
    Реклама
    Комментарии 2
    • 0
      Рассматривался ли вариант Docker + Spark Streaming?
      • 0
        Да. Лично мне вообще очень нравится Apache Spark. Но алгоритм по обработке задачи содежит вызовы проприетарных библиотек заказчика, и потому плохо адаптируется под Spark.

        Spark хорошо подходит для создания классификаторов данных; его мы начинаем использовать для других задач в пределах этого же проекта.

        А Docker переживал свое раннее детство в момент имплементации решения (этот модуль появился два с небольшим года назад). Кроме того, EC2 и в данный момент немного легче с точки зрения maintenance, если остальная часть решения хостается на EC2.

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