Как стать автором
Обновить
Neoflex
Создаем ИТ-платформы для цифровой трансформации

Управление сложностью legacy-кода в Big Data проектах с помощью инструмента Datalog

Время на прочтение7 мин
Количество просмотров2K
Самый простой Big Data проект сложнее проекта из мира привычного ПО. Имеется ввиду не сложность собственно алгоритмов или архитектуры, но анализа того, что представляет собой проект, как он работает с данными, как собирается та или иная витрина, какие для нее берутся данные.

Например, нужно решить такую задачу:

  1. Загрузить таблицу из Oracle;
  2. Посчитать в ней сумму по какого-нибудь полю, сгруппировав по ключу;
  3. Результат сохранить в витрину в Hive.

Набор инструментов будет выглядеть примерно так:

  • Oracle
  • Apache Sqoop
  • Oozie
  • Apache Spark
  • Hive

Простая задача неожиданно приводит к появлению проекта, включающего три независимых инструмента с тремя независимыми папками исходных файлов. И как понять – что происходит в проекте?

Если рассмотреть более типичный случай, то набор артефактов простого проекта в Big Data представляет собой:

  • SH управляющие файлы;
  • Sqoop скрипты;
  • набор Airflow Dag или Oozie Workflow;
  • SQL скрипты собственно преобразований;
  • Исходники на PySpark или Scala Spark;
  • DDL скрипты создания объектов.

Также, особенностью является то, что если пользоваться Cloudera или Hortonworks, то среда не предоставляет удобных средств разработки и отладки.

Облачные среды, такие как AWS или Azure, предлагают все делать в их оболочке, объединяющей все требуемые артефакты в удобном интерфейсе.

Вот, например, картинка с сайта Microsoft Azure:



Но это если есть AWS или Azure. А если есть только Cloudera?

Как ответить на вопрос – что, собственно, в проекте написано? При этом этот вопрос крайне интересует и заказчика тоже, так как в случае обычного ПО ему все равно то, как всё устроено внутри, а в случае с Big Data заказчику важно понимать, что данные получаются правильно.
В мире обычного программирования есть набор паттернов, подходов, применение которых позволяет структурировать код. А как структурировать код, представляющий из себя зоопарк независимых SQL-файлов, SH-скриптов вперемешку с Oozie Workflow?

Конечно, обычным решением является ведение подробной документации. Но документация устаревает в момент создания, а в случае авралов, разработка ведется вообще без обновления документов. Хочется автоматически собирать сведения о структуре данных, раскрывая Dataflow проекта.

Еще одним подходом является создание в компании Data Catalog, в котором будет регистрироваться каждый источник данных, и который будет являться единственным источником информации о датасетах, Source of Truth.

Существуют различные инструменты для создания Data Catalog:

  • Cloudera Navigator;
  • Alation;
  • Colibra.

Эти инструменты, например, с помощью Data Crawlers, мониторят события, происходящие в области данных и строят каталог объектов, пытаясь построить Lineage там, где это возможно. Например, подключаются к событиям Spark и вынимают оттуда данные об объектах. Это иногда позволяет не только записать в каталог объект, но и восстановить его Lineage. В результате появляется каталог как единый Source of Truth для данных, что сильно облегчает понимание их структуры и взаимосвязей.

Картинка с сайта Cloudera Navigator:



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

Мы в компании Neoflex разработали и применяем несколько другой подход, который реализовали в инструменте Datalog или, более полно – Data Topology. Инструмент предоставляет возможность раскрывать топологию объектов проекта в разрезе Dataflow, создавая автообновляемую документацию проекта в разрезе диаграм Dataflow на основе исходных кодов.

Проект Big Data представляет собой исходники для самых разных инструментов, но их объединяет одно – общая доменная модель. Имеется ввиду то, что все артефакты проекта – SQL-скрипты, SH-скрипты, исходники Spark и прочее описывают только одно – Dataflow.
Это значит, что если извлечь из артефактов (скриптов и исходников) данные о таблицах, которые используются в каждом из компонентов, то можно построить диаграмму Dataflow проекта. В большинстве случаев этого более чем достаточно, чтобы сделать содержимое проекта прозрачным и доступным анализу.

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

val df = spark.sql(“select * from Table1”) 
val df = spark.sql(“select * from ${source_table}”) 
val df = spark.sql(“${sql}”)

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

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

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

Как это выглядит на практике?

Допустим есть проект, который представляет из себя последовательность SQL -скриптов, исполняемые через hive и запускаемые через oozie. Сначала три скрипта готовят промежуточные данные, а последний – строит целевую витрину.

Запускающий файл выглядит так:

run-hive.sh:
hive -f $1

SQL -скрипты выглядят так:

insert into targetdb1.table1
select f1, f2
from
sourcedb.table1 t1 inner join sourcedb.table2 t2 on t1.id = t2.id

Есть oozie workflow, запускающая последовательно такие задачи:

  1. Три параллельных скрипта, готовящих промежуточные данные;
  2. Финальная задача, строящая витрину на основе таблиц из задачи 1

собственно, вот такой workflow:

<workflow-app name="Hive1" xmlns="uri:oozie:workflow:0.5">
    <start to="fork1"/>
    <kill name="Kill" />
<fork name="fork-1"></fork>
<join name="join-1" to="Project2"/>
    <action name="sql1">
        <shell xmlns="uri:oozie:shell-action:0.1">
            <exec>run-hive.sh</exec>
              <argument>project1/sql/sql1.sql</argument>
              <capture-output/>
        </shell>
        <ok to="join-1"/>
        <error to="Kill"/>
    </action>
    <action name="sql2">
        <shell xmlns="uri:oozie:shell-action:0.1">
            <exec>run-hive.sh</exec>
              <argument>project1/sql/sql2.sql</argument>
              <capture-output/>
        </shell>
        <ok to="join-1"/>
        <error to="Kill"/>
    </action>
    <action name="sql3">
        <shell xmlns="uri:oozie:shell-action:0.1">
            <exec>run-hive.sh</exec>
              <argument>project1/sql/sql3.sql</argument>
              <capture-output/>
        </shell>
        <ok to="join-1"/>
        <error to="Kill"/>
    </action> 
    <action name="Project2">
        <shell xmlns="uri:oozie:shell-action:0.1">
            <exec>run-hive.sh</exec>
              <argument>project2/sql/sql1.sql</argument>
              <capture-output/>
        </shell>
        <ok to="end"/>
        <error to="Kill"/>
    </action> 
    <end name="End"/> 
</workflow-app>

Вся папка проекта выглядит так:



После анализа проекта составляются три простых правила извлечения информации о Dataflow:

  1. Workflow.xml и SH файл игнорируются, так как в них нет ничего существенного о Dataflow;
  2. project1 и project2 транслируются как этапы проекта, которые в терминах in-out передают один другому данные (project1->project2);
  3. Файлы SQL, лежащие в project1/ SQL и project2/ SQL транслируются через SQL-парсер.

После анализа структуры проекта правила извлечения данных из исходников условно можно записать так:

val dataflow = parseSqlFolder(path = "project1/sql/", componentName = "sample.project1")
dataflow ++= parseSqlFolder(path = "project2/sql/", componentName = "sample.project2")

Это что-то типа DSL для описания проекта.

Такая запись утверждает, что все существенное для этого проекта надо искать только в папках с SQL. Для данного проекта этого достаточно.

Вот, что получается на выходе:



Как выяснилось, в проекте строятся две независимые витрины.

Та же самая информация может быть представлена по-другому, если она будет в виде in-out, а именно – какой компонент цепочки какие объекты данных потребляет и кому их дальше передает:



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

Что дает такой подход:

  1. Для создания Dataflow диаграмм не требуется переделка процессов у заказчика. Данные извлекаются из существующих проектов. Не нужно создавать каталог данных, можно создавать каталог проектов. Кроме того, для применения этого подхода не нужна разработка какого-то глобального регламента работы с данными, как было бы в случае создания Data Catalog;
  2. Построение диаграммы, описывающей проект, опирается только на исходные коды. Это значит, что такая диаграмма может показывать и те этапы, которые не попадают, например, в Data Catalog, так как происходят за границами, скажем, кластера;
  3. Полученная диаграмма не устареет, так как опирается на исходные коды проекта и создается заново при открытии;
  4. Так как основная работа в Big Data осуществляется через SQL, то простое подключение SQL-парсера (в данном случае Spark Catalyst) решает проблему поиска токенов, и после написания правил подключение второго, третьего и далее проектов происходит очень быстро;
  5. Для описания проекта применяются не документация, а ряд правил, помогающих транслятору разбирать проект. Такие правила всегда есть, но обычно остаются в голове разработчика, который отвечает за проект. Здесь же они записаны и сохраняются. Это похоже на DSL того, как переводить проект в описание.

Недостатки такого подхода тоже очевидны:

  1. Правила извлечения данных должны эволюционировать вместе с проектом;
  2. То, что получается, описывает данный конкретный проект и вряд ли подходит для проектов другой структуры;
  3. Это все-таки не Data Catalog, в котором есть много чего еще помимо построения диаграм Dataflow.

Этот проект можно рассматривать как своего рода замену или дополнение Data Catalog, раскрывающие процессы построения данных в разрезе проектов. Лучше всего применение Datalog показывает себя при анализе больших legacy-проектов с многолетней историей.
Теги:
Хабы:
Всего голосов 3: ↑3 и ↓0+3
Комментарии8

Публикации

Информация

Сайт
www.neoflex.ru
Дата регистрации
Дата основания
Численность
1 001–5 000 человек
Местоположение
Россия