Сегодня рассмотрим, что такое процессор ExecuteScript в Apache NiFi, как с его помощью реализовать собственную бизнес-логику обработки потоков данных на мульти-парадигмальном языке программирования TypeScript и чем это будет лучше кода на JavaScript. Краткий ликбез для дата-инженеров.
Процессор ExecuteScript в Apache NiFi
Напомним, за обработку потоков данных в Apache NiFi отвечают специализированные обработчики – процессоры, которые предоставляют интерфейс доступа к потоковым файлам (FlowFile), их содержимому и атрибутам. Фреймворк предоставляет более 300 готовых процессоров, но дата-инженер их может написать и самостоятельно, о чем мы уже упоминали здесь. Собственный процессор может объединять несколько готовых, а также выполнять уникальные операции с нетиповыми источниками, реализуя оригинальную бизнес-логику обработки потокового файла.
Для реализации собственного процессора в NiFi уже есть заготовка – процессор ExecuteScript, который выполняет пользовательский сценарий, поддерживающий движки для разных языков программирования (Clojure, ECMAScript, Groovy, lua, Python, Ruby) с учетом FlowFile и сеанса процесса. Сценарий отвечает за обработку входящего потокового файла и создание новых FlowFile. Если обработка неполная или некорректная, сеанс процесса будет отменен.
Процессор ExecuteScript имеет следующие переменные:
- Session – сеанс процесса, переменная типа org.apache.NiFi.processor.ProcessSession, позволяет выполнять типовые операции с FlowFile — create(), putAttribute(), transfer(), read() и write();
- Context – контекст, переменная типа apache.NiFi.processor.ProcessContext, которую можно использовать для получения свойств процессора, отношений, служб контроллера и менеджера состояний (StateManager);
- REL_SUCCESS — отношение «успех», определяющее маршрут успешного выполнения операции обработки данных;
- REL_FAILURE— отношение «сбой», определяющее маршрут неудачного выполнения операции обработки данных;
- Dynamic Properties — динамические свойства, определенные в ExecuteScript, передаются механизму сценариев в виде переменных, установленные как объект PropertyValue. Это позволяет получить значение свойства, привести значение к соответствующему типу данных и пр. Поддерживает внутренний язык выражений NiFi и обновляет свойство обработчика сценариев, указанное ключом с заданным значением динамического свойства.
Чтобы написать свою бизнес-логику, следует выбрать движок для выполнения скрипта (Script Engine) и указать расположение файла Script File со скриптом или сам скрипт Script Body. Как уже было отмечено выше, движок выполнения скрипта процессора ExecuteScript поддерживает Clojure, ECMAScript, Groovy, lua, Python, Ruby. Язык программирования TypeScript относится к семейству ECMAScript, а что именно он представляет собой и чем лучше JavaScript, мы рассмотрим далее. А пример кода на Groovy для постраничного извлечения данных из реляционной базы показан здесь.
Что такое TypeScript и чем он хорош
TypeScript — язык программирования, представленный Microsoft в 2012 году и позиционируемый как средство разработки веб-приложений, расширяющее возможности JavaScript. Спецификации языка открыты и опубликованы в рамках соглашения Open Web Foundation Specification Agreement (OWFa 1.0). TypeScript обратно совместим с JavaScript и компилируется в него: после компиляции TypeScript-код можно выполнять в почти любом браузере или использовать совместно с серверной платформой Node.js.
В отличие от JavaScript, в TypeScript можно явно статически назначать типы данных и использовать полноценные классы как в традиционных ООП-языках. Также в TypeScript есть поддержка подключения модулей, чтобы повысить скорость разработки, облегчить читаемость, рефакторинг и повторное использование кода, быстрее находить ошибки на этапе разработки и компиляции, и ускорить выполнение программ. Поскольку стандарт ECMAScript поддерживает ООП-подход, в TypeScript добавлена статическая типизация, что позволяет статически анализировать язык, облегчая оснастки и IDE поддержку. TypeScript добавляет из стандарта ECMAScript 6 поддержку следующих конструкций: классов, модулей и синтаксиса некоторых функций.
Как внедрить TypeScript-код в процессор ExecuteScript
Применение TypeScript с ECMAScript 6 в процессорах ExecuteScript с сохранением кода под контролем версий в репозитории отдельно от потоков дает следующие преимущества по сравнению с JavaScript на ECMAScript 5.1:
- больше современных возможностей при написании скриптов;
- использование внешних библиотек, таких как lodash;
- повторное использование кода между процессорами ExecuteScript;
- улучшенная ревизия кода и управление версиями;
- улучшенные абстракции с помощью оболочек привязок NiFi/Java;
- модульное тестирование.
Однако, воспользоваться этими преимуществами не так-то просто. Последняя на текущий момент версия Apache NiFi 1.16 использует Nashorn в качестве движка ECMAScript для процессора ExecuteScript, который совместим с релизом 5.1 и поддерживает только автономные сценарии. Поэтому скрипты должны быть написаны на старой версии JavaScript без поддержки современных функций массивов и внешних библиотек, таких как lodash и пр. Тем не менее, можно использовать TypeScript для написания NiFi -процессоров ExecuteScript, используя транскомпиляторы Babel, TypeScript и Webpack, чтобы преобразовать его в синтаксис ECMAScript 5.1 и связать в один файл.
Это решение состоит в следующем:
- Настройка конвейера сборки для переноса и связывания кода TypeScript с ES1:
- TypeScript для преобразования кода в современный JavaScript.
- транскомпилятор Babel для переноса этого кода JavaScript в ES5.1 и добавления необходимых полифилов — кода, который реализует функциональные возможности, ранее не поддерживаемые некоторыми версиями веб-браузеров;
- транскомпилятор Webpack для объединения всего в отдельный скрипт.
- Добавление инструментов форматирования и тестирования, например, Prettier, ESlint и Jest.
- Добавление типов для привязок NiFi /Java;
- Добавление абстракций для лучшей работы с чтением и записью контента, а также атрибутов FlowFile, получения и маршрутизации потоковых файлов, обработки HTTP-запросов;
- создания процессоров для обработки потоковых файлов;
- создание проекта;
- копирование артефактов сборки в NiFi-процессоры ExecuteScript, настроенные на использование ECMAScript;
- отслеживание исходного кода и версий артефактов в процессорах через добавление комментариев в обработчик с идентификатором исходного кода в проекте, например, путь, и версии и/или создание двух новых параметров «имя» и «версия», чтобы проверять их на соответствие имени и версии кода.
Решение предназначено для использования в простых случаях использования, например, выполнение сложных преобразований данных в JSON, чего нет в готовых процессорах NiFi. Для более сложных вариантов использования типа взаимодействия со службами контроллера или связи с внешними сервисами рекомендуется использовать собственные процессоры NiFi, написанные на Java.
По сравнению с разработкой пользовательских процессоров NiFi на Java для простых случаев использование TypeScript позволяет использовать гибкость ExecuteScript, чтобы ускорить проверку концепции или применять в незрелых проектах с частыми изменениями. Такую гибкость обусловливает простое развертывание при отсутствии CI/CD-конвейера доставки пользовательских процессоров Java в экземпляр NiFi и более низкий порог входа в технологию: писать на TypeScript/JavaScript, проще чем на Java. Кроме того, так начинающим дата-инженерам не придется разбираться с жизненным циклом процессора. А еще в TypeScript проще иметь дело с нетипизированными и частично типизированными объектами. Какие исключения и ошибки могут возникнуть при разработке собственного процессора, мы рассказываем в этом материале.
Для зрелых проектов, подверженных менее частым изменениям дизайна, лучше писать собственные процессоры NiFi на Java, поскольку они стабильнее, эффективнее и обеспечивают лучшую интеграцию с инфраструктурой самого фреймворка. Кроме того, стоит помнить, что не все библиотеки совместимы с ExecuteScript. Например, библиотеки, основанные на некоторых API-интерфейсах JavaScript, например, AWS SDK. Если нужно выполнять HTTP-запросы, использовать криптографические функции и пр., лучше использовать собственные пакеты Java через языковые привязки. О том, чем скриптовые процессоры отличаются от скриптов, читайте в нашей новой статье. А о разнице свойств Script Body и Script File вы узнаете здесь.
Больше практических приемов по администрированию и эксплуатации Apache NiFi для эффективной аналитики больших данных вы узнаете на специализированных курсах в нашем лицензированном учебном центре обучения и повышения квалификации для разработчиков, менеджеров, архитекторов, инженеров, администраторов, Data Scientist’ов и аналитиков Big Data в Москве:
- https://medium.com/@tutihashi.william/using-typescript-in-NiFi -executescript-5b8af487cf42
- https://NiFi .apache.org/docs/NiFi -docs/components/org.apache.NiFi /NiFi -scripting-nar/1.5.0/org.apache.NiFi .processors.script.ExecuteScript/index.html
- https://habr.com/ru/company/rostelecom/blog/504954/
- https://ru.wikipedia.org/wiki/TypeScript
- https://github.com/williamtutihashi/nifi-typescript-execute-script-processor