Для управления кодом Spark-приложений мы используем подход, описанный в предыдущей статье.
Речь идет об управлении качеством кода при разработке Spark ETL, чтобы не превратить работу над проектом в полет души, пугающий даже автора. В результате Spark ETL application выглядит просто как последовательность Spark SQL-запросов. Сама ETL-трансформация описывается как объект в отдельном файле конфигурации.
Какие плюсы у такого подхода?
• Он обладает большой гибкостью. Собственно, код приложения не зависит от логики трансформации и легко может быть дописан или вообще написан с нуля на новом проекте. Например, в случае необходимости парсинга JSON или XML.
• Важно то, что код остается простым для освоения новым человеком в команде, какие бы сложные трансформации не встречались в проекте. Растет лишь число и объем файлов конфигурации, описывающих отдельные трансформации.
• Для расширения проекта можно нанимать людей, знающих всего лишь SQL.
Однако, такой подход имеет и недостатки, которые являются следствием того, что это не полноценный инструмент, а скорее внутренний регламент разработки. В результате нет многого из того, что хотелось бы. А хотелось бы следующее:
• Создавать автотесты
• Поддерживать шаблонизатор
• Создавать документацию по проекту
• Валидировать модель, описывающую трансформацию
• И главное – чтобы ряд очевидных вещей, типа витрины различного формата сохранения и поддержки полной, частичной и инкрементальной загрузки, поддерживались из коробки.
Как оказалось, такой инструмент уже есть и это приложение, основанное на похожих принципах, предоставляющее возможность описать ETL-трансформацию как набор SQL-запросов и выполнить их на Spark — Data Build Tool (DBT)
Приложение упоминается как очевидный к использованию инструмент для ETL. Более того, в этом можно убедиться, посмотрев, как этот инструмент продвигают Databriks или здесь, прочитав статью.
Мне самому очень понравился вот этот материал: DBT (Data Build Tool) Tutorial from Fishtown Analytics
DBT предлагает вести проект ETL-трансформации в виде иерархии SQL-запросов, поддерживает шаблонизатор, проверяет валидность ссылок-запросов друг на друга, генерит автотесты и документацию. Кроме того, поддерживает различные среды выполнения запросов, умеет создавать граф зависимостей задач проекта. Распространяется бесплатно, но содержит и платные версии с поддержкой среды разработки, а также поддерживается многими другими инструментами: например, есть много материалов по связке Dagster – DBT.
Как же справляется DBT с задачей, по мнению тех, кому пришлось решать те же самые проблемы самостоятельно?
Самое интересное как всегда скрыто в деталях, поэтому интересно посмотреть именно их.
Отлично, попробуем это приложение. Что же предлагает продукт?
1. Работа со Spark. Этот пункт понятен. DBT предлагает разные возможности запуска запросов, из которых состоит проект, в том числе и на Spark. К тому же к Spark можно подключаться несколькими способами: через Thrift Server или в облаке;
2. Разработка проекта как набора SQL файлов. Разработка проекта на DBT – это разработка SQL запросов, которые могут ссылаться друг на друга, и это – главная фишка DBT, как и в целом такого подхода;
3. Сохранение витрин в разных форматах. Результирующие витрины можно сохранять различными способами: как таблицу, витрину, с указанием опций партиционирования;
4. Опции обновления витрин. DBT позволяет настраивать полное, частичное и инкрементальное обновление витрины из коробки;
5. Наличие шаблонизатора. Запросы в DBT кастомизируются через Ninja Template и с добавлением макросов;
6. В DBT есть возможность выполнения addhook-запросов, например, заполнить таблицу с id сессии загрузки или раздать права на целевую таблицу;
7. DBT создает автотесты, документацию по проекту, а также строит граф зависимостей между запросами.
В общем, есть все, что так или иначе встречалось в подобных проектах и что приходилось добавлять в собственные разработки.
Единственное, с чем пришлось повозиться и это оказалось неожиданным – подключение к Spark. DBT предлагает различные варианты исполнения запросов. Нас интересует только Spark для подключения к которому тоже есть разные опции. Так как речь идет о собственных кластерах под управлением Cloudera, то нам остается вариант Spark Thrift-сервера. И тут внезапно оказывается, что Cloudera включает в дистрибутив Spark без Thrift-сервера.
Оказывается, они думают, что вам нужна Impala, поэтому старательно собирают дистрибутив Spark без Thrift и радостно включают его в дистрибутив кластера.
Кто виноват – ясно. Что делать?
Скачиваем нужный дистрибутив Spark, ставим его на ноду кластера. Указываем в настройках ссылку на /etc/hadoop/conf. Запускаем из дистрибутива Spark Thrift Server, после чего указываем host-port нашего Thrift-сервера в настройках DBT.
Может быть кто-то знает другой способ? Я не нашел. Ок. Создаем тестовый проект. Настраиваем профиль DBT:
В проекте модель, которая обращается к запросам одной из таблиц Hive, чтобы проверить, что настройки прочлись.
Сначала проверяем, что DBT видит Spark.
DBT debug
Теперь проверяем тестовую модель, которая Spark-запросом обращается в Hive:
Подключился, запросы проходят, все хорошо.