Создание нового интерпретатора в Zeppelin

В данной статье описан процесс создания Zeppelin-интерпретатора "с нуля". Информация о добавлении интерпретаторов Zeppelin в существующую группу доступна в статье Добавление интерпретатора в группу.

Обзор сценария

Для создания нового интерпретатора необходим класс, наследующий абстрактный класс Interpreter. Данный класс в виде JAR необходимо поместить на хост ADH с компонентом Zeppelin Server. Разработка полноценного интерпретатора, способного корректно обрабатывать пользовательский код из заметок, подразумевает сложную логику и тестирование, что выходит за рамки данной статьи. В приведенном ниже примере представлена базовая реализация интерпретатора с методами-заглушками для демонстрации подключения и работоспособности тестового интерпретатора. Шаги в сценарии подходят для интерпретаторов любой сложности и являются лишь одним из возможных подходов к созданию интерпретатора.

Сценарий, описанный в статье, включает следующие шаги:

  1. Клонирование проекта Zeppelin.

  2. Создание интерпретатора на базе существующего модуля.

  3. Реализация класса org.apache.zeppelin.interpreter.Interpreter, упаковка в JAR.

  4. Добавление интерпретатора на хост ADH.

Шаг 1. Клонирование проекта Zeppelin

В этом примере предполагается использование проекта Zeppelin в качестве базы для создания нового интерпретатора. Такой подход облегчает управление зависимостями и структурой.

  1. Склонируйте репозиторий Zeppelin.

    $ git clone https://github.com/apache/zeppelin/tree/master
  2. Используйте ветку, соответствующую сборке Zeppelin-сервиса. Например:

    $ cd zeppelin
    $ git checkout 0.11.2

Шаг 2. Создание модуля интерпретатора

В этом примере новый интерпретатор создается путем копирования существующего модуля интерпретатора и изменения его содержимого.

  1. Скопируйте существующий модуль интерпретатора, например file.

    $ cp -r file ./mycustominterpreter
  2. В новом модуле удалите все классы и создайте тестовый Java-класс CustomInterpreter, наследующий org.apache.zeppelin.interpreter.Interpreter. В данном сценарии CustomInterpreter представляет собой класс-заглушку, который не парсит пользовательский код из заметок, однако создает записи в логе при вызове методов.

    Пример CustomInterpreter.java

     

    package io.arenadata.zeppelin.mycustominterpreter;
    
    import org.apache.zeppelin.interpreter.Interpreter;
    import org.apache.zeppelin.interpreter.InterpreterContext;
    import org.apache.zeppelin.interpreter.InterpreterException;
    import org.apache.zeppelin.interpreter.InterpreterResult;
    import org.slf4j.Logger;
    import org.slf4j.LoggerFactory;
    
    import java.util.Properties;
    
    public class CustomInterpreter extends Interpreter {
        public CustomInterpreter(Properties properties) {
            super(properties);
            Logger logger = LoggerFactory.getLogger(CustomInterpreter.class);
        }
    
        @Override
        public void open() throws InterpreterException {
            logger.info("Stub method called: open()");
        }
    
        @Override
        public void close() throws InterpreterException {
            logger.info("Stub method called: close()");
        }
    
        @Override
        public InterpreterResult interpret(String st, InterpreterContext context) throws InterpreterException {
            logger.info("Stub method called: interpret()");
            return null;
        }
    
        @Override
        public void cancel(InterpreterContext context) throws InterpreterException {
            logger.info("Stub method called: cancel()");
        }
    
        @Override
        public FormType getFormType() throws InterpreterException {
            logger.info("Stub method called: getFormType()");
            return null;
        }
    
        @Override
        public int getProgress(InterpreterContext context) throws InterpreterException {
            logger.info("Stub method called: getProgress()");
            return 0;
        }
    }
    РЕКОМЕНДАЦИЯ
    Код интерпретаторов, доступных в Zeppelin "из коробки", можно найти в GitHub-репозитории.

    Теперь проект имеет следующую структуру:

    zeppelin/
    +---alluxio
    +---angular
    +---bigquery
    +---bin
    +---build-tools
    +---cassandra
    +---conf
    +---custominterpreter
    |   |   pom.xml
    |   |
    |   +---src
    |   |   +---main
    |   |   |   +---java
    |   |   |   |   \---io
    |   |   |   |       \---arenadata
    |   |   |   |           \---zeppelin
    |   |   |   |               \---mycustominterpreter
    |   |   |   |                       CustomInterpreter.java <-- Interpreter logic here
    |   |   |   |
    |   |   |   \---resources
    |   |   |           interpreter-setting.json
    |   |   |
    |   |   \---test
    |   |
    |   \---target
    +---flink
    +---flink-cmd
    +---groovy
    ...
    // other modules
  3. Так как модуль был полностью скопированной директорией, необходимо немного рефакторинга, а именно:

    • Добавить новый интерпретатор в список модулей в родительском POM (zeppelin/pom.xml). Например:

       <module>mycustominterpreter</module>
    • Обновить поля artifactId и interpreter.name в POM-файле нового модуля (zeppelin/mycustominterpreter/pom.xml).

    • В zeppelin/mycustominterpreter/src/main/resources/interpreter-setting.json в поле className указать имя нового класса интерпретатора (CustomInterpreter). Также необходимо задать новые значения для name и group. Они будут использоваться для вызова интерпретатора в коде заметок, используя %<interpreter.group>.<interpreter.name>. Также в этом файле можно задать список параметров интерпретатора, которые будут доступны в Zeppelin UI. Подробная информация о таких параметрах, как editOnDblClick и completionSupport доступна в документации Zeppelin.

    • Исправить имена пакетов.

    • Удалить тест-классы.

Шаг 3. Сборка нового интерпретатора

Соберите проект Zeppelin с помощью Maven:

$ mvn clean package -DskipTests

В директории target нового модуля будет доступен JAR интерпретатора. Необходим Uber-JAR, включающий все зависимости и имеющий следующую структуру:

mycustominterpreter.jar
|   interpreter-setting.json
|
+---com
|   \---google
|       \--- ...
+---javassist
|   \--- ...
+---javax
|   \--- ...
+---jersey
|   \--- ...
+---META-INF
|   \--- ...
+---io
	+---arenadata
		\---zeppelin
			\---mycustominterpreter
				\---CustomInterpreter.class
    +---aopalliance
    +---apache
    +---slf4j
...

Шаг 4. Импорт JAR интерпретатора в Zeppelin

  1. Скопируйте JAR интерпретатора в директорию /usr/lib/zeppelin/interpreter/ на хосте ADH, где установлен компонент Zeppelin Server.

  2. Перезапустите сервис Zeppelin. После рестарта Zeppelin новый интерпретатор станет доступен в списке интерпретаторов в UI.

    Новый интерпретатор
    Новый интерпретатор
    Новый интерпретатор
    Новый интерпретатор
  3. Создайте тестовую заметку с новым интерпретатором. При создании заметки выберите новый интерпретатор по умолчанию либо используйте %mycustominterpreter в каждом параграфе. В данном сценарии отправка любых данных интерпретатору не вернет результатов, но создаст записи в логах. Используйте логи в /var/log/zeppelin/, чтобы проверить активность тестового интерпретатора, например:

$ grep -r "Stub method called:*" /var/log/zeppelin
Нашли ошибку? Выделите текст и нажмите Ctrl+Enter чтобы сообщить о ней