Всем привет!
Сегодня хочется рассказать об одной из типичных задач в области Cloud Computing и Big Data и подходе к ее решению, найденному нами в TeamDev.
Мы столкнулись с проблематикой BigData при разработке публичного сервиса для одной из компаний, занимающихся хранением и анализом результатов биологических исследований. Целью заказчика на очередном этапе стала визуализиция в реальном времени определенных срезов таких данных.
Попробуем формализировать задачу.
Исходные данные: десятки тысяч файлов, каждый из которых представляет собой несколько связанных матриц типа int и float. Размер одного файла колеблется и может составлять порядка 2-4 ГБайт. Все данные предполагается загружать в облачное хранилище.
Возвращаемые значения: набор точек, по которым можно построить изображение высокого разрешения. Процесс обработки предполагает суммирование и находжение максимальных значений в массивах с заданными границами, а потому является довольно активным потребителем CPU time. Размеры результатов зависят от запроса со стороны пользователя — от ~50 КБайт до ~20 МБайт. Размер исходных обрабатываемых данных для формирования одного ответа превосходит размер ответа в 30-200 раз. То есть чтобы отправить 100 КБайт ответа, нужно прочесть и обработать порядка 3-20 МБайт.
Требования:
Исходные позиции:
В качестве провайдера облачных технологий заказчик выбрал Amazon Web Services, используя Amazon S3 как “бесконечное” хранилище исходных данных и Amazon EC2 в качестве хостинга для рабочих узлов.
Фронт-энд, который должен отдавать изображения браузерам и десктоп-клиенту, написан на Java. Расположен на Amazon EC2.
Бэк-энд, определяющий бизнес-логику, включая контроль доступа к данным, написан на Java и расположен на другом инстансе EC2.
Описательная часть данных (где лежат, кому принадлежат, что из себя представляют) находится в MySQL на Amazon RDS.
С попытки решения проблемы “в лоб”! Что если создать одно приложение, обрабатывающее параллельно набор запросов от пользователей? Предлагается забирать данные с S3 и отдавать некую структуру, представляющую собой набор точек или рендерить готовое изображение.
Набор возникающих трудностей очевиден:
Amazon EC2 позволяет создавать разные по размеру инстансы, но самый большой из них — d2.8xlarge (36 x Intel Xeon E5-2676v3, 244 ГБайт ОЗУ) — решает только проблемы №1 и №2. Проблема №3 — время на загрузку данных — на два порядка превышает ожидаемую скорость возврата результатов. Кроме того, масштабируемость такого решения стремится к нулю.
Elastic MapReduce
Для решения подобных задач AWS предоставляет облачный Elastic MapReduce, он же — hosted Apache Hadoop. С его помощью удается преодолеть все возникавшие трудности за счет распределения нагрузки между узлами кластера. Однако, в этом варианте появляются новые проблемы:
В целом, Elastic MapReduce хорошо подходит для задач, не предполагающих условно моментальный результат. Но для решения нашей задачи его использовать невозможно, главным образом, из-за несоответствий требованиям ко времени процессинга запроса.
Apache Storm
В качестве альтернативы, сохраняющей преимущества MapReduce-подхода, но позволяющей получать результат обработки в приближенном к реальному времени, хорошо подходит Apache Storm. Этот фреймворк использовался для нужд Twitter (обработка аналитических событий) и приспособлен для потоков задач с миллионными размерами очередей.
Инсталляция Storm в AWS Cloud хорошо продумана: существует готовые деплоймент-скрипты, автоматически запускающие все необходимые узлы плюс инстанс Zookeeper для поддержания жизнеспособности системы.
Однако, при ближайшем рассмотрении (был сделан прототип) выяснилось, что и такое решение обладает рядом недостатков:
Концепт, построенный с помощью Storm, удовлетворял требованиям, в том числе по скорости. Но из-за перманентно возникающих задач по обслуживанию этого решения (пункты 1 и 3) и временным потерям из-за “лишней” сериализации (пункт 2) было решено от него отказаться.
Elastic Beanstalk
Еще одним вариантом было написание собственного приложения с размещением в Amazon Elastic Beanstalk. Такой вариант мог бы решить все проблемы одним махом: набор EC2-инстансов для распределения нагрузки на CPU и сеть, автоматическое масштабирование, метрики и поддержание жизнеспособности всех узлов. Но при ближайшем рассмотрении возникли сомнения:
Мы отказались от такого решения, в основном, из-за первого пункта. Но стоит отметить, что Beanstalk быстро развивается, и в следующих проектах мы обязательно обратим на него свое внимание.
В нашей среде широко распространены два мнения: “все написано до нас — нужно уметь искать” и “если хочешь что-то сделать хорошо, сделай это самостоятельно”. На основе опыта, полученного во время поисков, было принято решение в пользу самописной системы.
(о которой — в следующей части статьи).
Сегодня хочется рассказать об одной из типичных задач в области Cloud Computing и Big Data и подходе к ее решению, найденному нами в TeamDev.
Мы столкнулись с проблематикой 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 и отдавать некую структуру, представляющую собой набор точек или рендерить готовое изображение.
Набор возникающих трудностей очевиден:
- Средний объем ответа равен 4 МБайт. Для 100 одновременных или почти одновременных запросов суммарный объем результатов достингет 4 МБайт * 100 = 400 МБайт. Размер исходных данных превышает размер ответа в 30 и более раз. Значит, придется практически одновременно зачитать из хранилища не менее 30 * 400 МБайт ~ 12 ГБайт, а как максимум 200 * 400 МБайт ~ 80 ГБайт данных.
- Наличие 100 одновременных запросов, обработка каждого из которых требует процессорного времени, предполагает наличие сопоставимого количества CPU.
- Теоретическая максимальная пропускная способность сети между Amazon S3 и инстансом EC2 составляет 1 ГБит/c, то есть 125 МБайт/c. То есть, для того, чтобы зачитать [в лабораторных условиях] даже 12 ГБайт данных потребуется примерно 12 * 1024 / 125 ~ 98 секунд.
- Единственный инстанс никак не может обслуживать пользователей из разных частей планеты с равной скоростью.
Amazon EC2 позволяет создавать разные по размеру инстансы, но самый большой из них — d2.8xlarge (36 x Intel Xeon E5-2676v3, 244 ГБайт ОЗУ) — решает только проблемы №1 и №2. Проблема №3 — время на загрузку данных — на два порядка превышает ожидаемую скорость возврата результатов. Кроме того, масштабируемость такого решения стремится к нулю.
Готовое решение?
Elastic MapReduce
Для решения подобных задач AWS предоставляет облачный Elastic MapReduce, он же — hosted Apache Hadoop. С его помощью удается преодолеть все возникавшие трудности за счет распределения нагрузки между узлами кластера. Однако, в этом варианте появляются новые проблемы:
- Скорость старта Hadoop-задачи — секунды. Что в несколько раз медленнее, чем требуемое время формирования ответа.
- Необходимость предразогрева кластера и загрузки выбранных данных с S3 в HDFS. Это требует дополнительных телодвижений по выбору стратегии оперирования кластером (кластерами) для балансировки нагрузки.
- Результат доставляется на S3 или в HDFS, что требует дополнительной инфраструктуры по доставке его конечному пользователю.
В целом, Elastic MapReduce хорошо подходит для задач, не предполагающих условно моментальный результат. Но для решения нашей задачи его использовать невозможно, главным образом, из-за несоответствий требованиям ко времени процессинга запроса.
Apache Storm
В качестве альтернативы, сохраняющей преимущества MapReduce-подхода, но позволяющей получать результат обработки в приближенном к реальному времени, хорошо подходит Apache Storm. Этот фреймворк использовался для нужд Twitter (обработка аналитических событий) и приспособлен для потоков задач с миллионными размерами очередей.
Инсталляция Storm в AWS Cloud хорошо продумана: существует готовые деплоймент-скрипты, автоматически запускающие все необходимые узлы плюс инстанс Zookeeper для поддержания жизнеспособности системы.
Однако, при ближайшем рассмотрении (был сделан прототип) выяснилось, что и такое решение обладает рядом недостатков:
- Изменение конфигурации Storm-кластера (добавление узлов, деплоймент новых версий) “на лету” происходит непрозрачно. Если быть совсем точным, то во многих случаях изменения гарантированно подхватываются только после перезапуска кластера.
- Концепция обработки сообщений в Storm в режиме RPC преполагает, как минимум, три стадии для реализации MapReduce: разделение работы на части, процессинг части работы, объединение результатов. Каждый из этих этапов в общем случае выполняется на собственном узле. В свою очередь, это ведет к дополнительной сериализации-десериализации бинарного контента сообщений.
- Не самый простой подход к интеграционному тестированию — поднятие целого тестового кластера требует ресурсов и времени.
- Навязчивый API (из разряда вкусовщины, но тем не менее).
Концепт, построенный с помощью Storm, удовлетворял требованиям, в том числе по скорости. Но из-за перманентно возникающих задач по обслуживанию этого решения (пункты 1 и 3) и временным потерям из-за “лишней” сериализации (пункт 2) было решено от него отказаться.
Elastic Beanstalk
Еще одним вариантом было написание собственного приложения с размещением в Amazon Elastic Beanstalk. Такой вариант мог бы решить все проблемы одним махом: набор EC2-инстансов для распределения нагрузки на CPU и сеть, автоматическое масштабирование, метрики и поддержание жизнеспособности всех узлов. Но при ближайшем рассмотрении возникли сомнения:
- Vendor lock-in. После обсуждения с заказчиком выяснилось, что помимо разработки публичного сервиса в его планы входит и поставка коробочных решений с похожей функциональностью. И если альтернативу Amazon EC2 и Amazon S3 с аналогичным функционалом можно найти в интранет-ориентированных продуктах (например — линейка продуктов Pivotal), то адекватной замены Beanstalk нет.
- Недостаточная гибкость в настройках масштабирования. Статистика по запросам пользователей говорила о явных всплесках, привязанных ко времени начала рабочего дня. Но привязать пред-разогрев серверов ко времени суток система не позволяла. [Cовсем недавно такая возможность появилась].
- Не самый надежный сервис по доставке сообщений Amazon SQS, являющийся частью Beanstalk. Форумы разработчиков Amazon заполнены проблемами при работе с SDK этого сервиса.
- Комплексная процедура деплоймента.
Мы отказались от такого решения, в основном, из-за первого пункта. Но стоит отметить, что Beanstalk быстро развивается, и в следующих проектах мы обязательно обратим на него свое внимание.
Велосипед
В нашей среде широко распространены два мнения: “все написано до нас — нужно уметь искать” и “если хочешь что-то сделать хорошо, сделай это самостоятельно”. На основе опыта, полученного во время поисков, было принято решение в пользу самописной системы.
(о которой — в следующей части статьи).
nehaev
Рассматривался ли вариант Docker + Spark Streaming?
armiol Автор
Да. Лично мне вообще очень нравится Apache Spark. Но алгоритм по обработке задачи содежит вызовы проприетарных библиотек заказчика, и потому плохо адаптируется под Spark.
Spark хорошо подходит для создания классификаторов данных; его мы начинаем использовать для других задач в пределах этого же проекта.
А Docker переживал свое раннее детство в момент имплементации решения (этот модуль появился два с небольшим года назад). Кроме того, EC2 и в данный момент немного легче с точки зрения maintenance, если остальная часть решения хостается на EC2.