编写一个新的解释器

什么是Apache Zeppelin解释器

Apache Zeppelin 解释器是一个语言后端。例如,要在 Zeppelin 中使用 scala 代码,你需要一个 scala 解释器。 每个解释器都属于一个InterpreterGroup。 同一 InterpreterGroup 中的解释器可以相互引用。例如,SparkSqlInterpreter 可以引用 SparkInterpreter 以从中获取 SparkContext,只要它们在同一个组中。

InterpreterSetting 是给定 InterpreterGroup 的配置,也是启动/停止解释器的单位。 同一 InterpreterSetting 中的所有解释器都在一个单独的 JVM 进程中启动。解释器通过 Thrift 与 Zeppelin 引擎通信。

在“每个笔记的独立解释器(作用域/隔离)”模式下,您可以在创建新解释器时在解释器设置菜单中看到,每个笔记将创建一个新的解释器实例。但是,如果它们在相同的InterpreterSettings中,它们仍然在同一个JVM上运行。

创建你自己的解释器

创建一个新的解释器非常简单。只需扩展org.apache.zeppelin.interpreter抽象类并实现一些方法。 对于你的解释器项目,你需要将interpreter-parent作为你的父项目,并使用插件maven-enforcer-pluginmaven-dependency-pluginmaven-resources-plugin。这里有一个示例pom.xml

<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
    <modelVersion>4.0.0</modelVersion>

    <parent>
        <artifactId>interpreter-parent</artifactId>
        <groupId>org.apache.zeppelin</groupId>
        <version>0.9.0-SNAPSHOT</version>
        <relativePath>../interpreter-parent</relativePath>
    </parent>

    ...

    <dependencies>
        <dependency>
            <groupId>org.apache.zeppelin</groupId>
            <artifactId>zeppelin-interpreter</artifactId>
            <version>${project.version}</version>
            <scope>provided</scope>
        </dependency>
    </dependencies>

    <build>
        <plugins>
            <plugin>
                <artifactId>maven-enforcer-plugin</artifactId>
            </plugin>
            <plugin>
                <artifactId>maven-dependency-plugin</artifactId>
            </plugin>
            <plugin>
                <artifactId>maven-resources-plugin</artifactId>
            </plugin>
        </plugins>
    </build>

</project>

你应该在pom.xml中包含org.apache.zeppelin:zeppelin-interpreter:[VERSION]作为你的解释器的依赖。 并且你应该将你的jar包放在具有特定目录名称的解释器目录下。Zeppelin服务器会递归读取解释器目录并初始化解释器,包括你自己的解释器。

有三个位置可以存储您的解释器组、名称和其他信息。Zeppelin 服务器会尝试查找以下位置。接下来,Zeppelin 会尝试在您的解释器 jar 中查找 interpreter-setting.json

{ZEPPELIN_INTERPRETER_DIR}/{YOUR_OWN_INTERPRETER_DIR}/interpreter-setting.json

这里是一个关于您自己的解释器的interpreter-setting.json的示例。

[
  {
    "group": "your-group",
    "name": "your-name",
    "className": "your.own.interpreter.class",
    "properties": {
      "properties1": {
        "envName": null,
        "propertyName": "property.1.name",
        "defaultValue": "propertyDefaultValue",
        "description": "Property description",
        "type": "textarea"
      },
      "properties2": {
        "envName": PROPERTIES_2,
        "propertyName": null,
        "defaultValue": "property2DefaultValue",
        "description": "Property 2 description",
        "type": "textarea"
      }, ...
    },
    "editor": {
      "language": "your-syntax-highlight-language",
      "editOnDblClick": false,
      "completionKey": "TAB"
    },
    "config": {
      "runOnSelectionChange": true/false,
      "title": true/false,
      "checkEmpty": true/false
    }
  },
  {
    ...
  }
]

最后,Zeppelin 使用以下静态初始化:

static {
  Interpreter.register("MyInterpreterName", MyClassName.class.getName());
}

静态初始化已被弃用,并将支持到0.6.0版本。

名称稍后将在解释器配置过程中出现在解释器名称选项框中。 解释器的名称是您稍后编写的,用于标识应使用此解释器解释的段落。

%MyInterpreterName
some interpreter specific code...

解释器的编辑器设置

你可以将editor对象添加到interpreter-setting.json文件中以指定段落编辑器设置。

语言

如果解释器使用特定的编程语言(如Scala、Python、SQL),通常建议在笔记段落编辑器中添加支持该语言的语法高亮。

要查看支持的语言列表,请参阅zeppelin-web/bower_components/ace-builds/src-noconflict下的mode-*.js文件或从github.com/ajaxorg/ace-builds查看。

如果你想添加一组新的语法高亮,

  1. mode-*.js文件添加到zeppelin-web/bower.json(构建时,zeppelin-web/src/index.html将自动更改)。
  2. editor对象添加language字段。请注意,如果您不指定语言字段,您的解释器将使用纯文本模式进行语法高亮。假设您想将语言设置为java,然后添加:

    "editor": {
      "language": "java"
    }
    

双击编辑

如果你的解释器使用标记语言,如markdown或HTML,将editOnDblClick设置为true,以便在双击段落时打开文本编辑器并在段落运行时关闭。否则将其设置为false

"editor": {
  "editOnDblClick": false
}

完成键(可选)

默认情况下,Ctrl+dot(.) 在编辑器中会触发自动补全列表。 通过 completionKey,每个解释器可以配置自动补全键。 目前 TAB 是唯一可用的选项。

"editor": {
  "completionKey": "TAB"
}

笔记本段落显示标题(可选)

笔记本段落默认不显示标题。 你可以通过config.title=true来让笔记本显示标题。

"config": {
  "title": true  # default: false
}

选择更改时运行Notebook(可选)

笔记本中的动态表单在选择修改时会触发执行。 您可以通过设置config.runOnSelectionChange=false使笔记本中的动态表单在选择修改后不触发执行。

"config": {
  "runOnSelectionChange": false # default: true
}

在运行前检查段落是否为空(可选)

如果笔记本的段落为空,则默认不会运行。 您可以设置config.checkEmpty=false,以便在笔记本的段落为空时也运行。

"config": {
  "checkEmpty": false # default: true
}

安装您的解释器二进制文件

一旦你构建了你的解释器,你可以将其及其所有依赖项放置在解释器目录下。

[ZEPPELIN_HOME]/interpreter/[INTERPRETER_NAME]/

配置您的解释器

要配置您的解释器,您需要按照以下步骤操作:

  1. 通过运行./bin/zeppelin-daemon.sh start来启动Zeppelin。

  2. 在解释器页面,点击+Create按钮并配置您的解释器属性。 现在您已完成并准备好使用您的解释器。

注意: 随 Zeppelin 发布的解释器有一个默认配置,当没有 conf/zeppelin-site.xml 时使用。

使用你的解释器

0.5.0

在笔记中,%[INTERPRETER_NAME] 指令将调用您的解释器。 请注意,zeppelin.interpreters 中的第一个解释器配置将是默认的。

例如,

%myintp

val a = "My interpreter"
println(a)

0.6.0 及以后版本

在笔记内部,%[INTERPRETER_GROUP].[INTERPRETER_NAME] 指令将调用您的解释器。

你可以省略[INTERPRETER\_GROUP][INTERPRETER\_NAME]。如果你省略[INTERPRETER\_NAME],那么将在[INTERPRETER\_GROUP]中选择第一个可用的解释器。 同样地,如果你跳过[INTERPRETER\_GROUP],那么将从默认的解释器组中选择[INTERPRETER\_NAME]

例如,如果你在组mygrp中有两个解释器myintp1myintp2,你可以这样调用myintp1

%mygrp.myintp1

codes for myintp1

你可以这样调用 myintp2

%mygrp.myintp2

codes for myintp2

如果您省略解释器名称,它将选择组中第一个可用的解释器(myintp1)。

%mygrp

codes for myintp1

只有当您的解释器组被选为默认组时,您才能省略您的解释器组。

%myintp2

codes for myintp2

示例

查看一些默认随Zeppelin发布的解释器。

为Zeppelin版本贡献一个新的解释器

我们欢迎对新解释器的贡献。请遵循以下步骤:

  • 首先,查看一般贡献指南 这里
  • 按照上面创建自己的解释器部分和解释器的编辑器设置中的步骤操作。
  • 按照上面的配置你的解释器部分添加你的解释器;同时将其添加到示例模板zeppelin-site.xml.template中。
  • 添加测试!它们会针对所有更改运行,确保它们是自包含的非常重要。
  • 将您的解释器作为模块包含在pom.xml中。
  • docs/interpreter/下添加关于如何使用你的解释器的文档。遵循Markdown风格,如这个示例。确保你列出配置设置,并在Markdown的代码框中提供使用你的解释器的工作示例。适当链接到图片(图片应放在docs/assets/themes/zeppelin/img/docs-img/)。并在导航菜单中添加你的文档链接(docs/_includes/themes/zeppelin/_navigation.html)。
  • 最重要的是,确保所有依赖项的传递闭包的许可证都列在许可证文件中。
  • 提交您的更改并在项目的Pull Request上打开一个GitHub镜像;检查以确保Travis CI构建通过。