【Zeppelin 以练促学】如何编写一个 Zeppelin 解释器

文章首发于公众号【大数据学徒】,感兴趣请搜索 dashujuxuetu 或者文末扫码关注。

这是我想深入研究 Apache Zeppelin 所做的一个尝试,毕竟如果想要了解内在的原理,有必要先将它暴露出来的功能都摸透,自己写一个 Zeppelin 解释器对于理解其它的解释器也非常有帮助,其实 官方文档 中已经给出了具体的方法,本文就是我 follow 官方文档的一次实践(虽然步骤并不完全一样),如果你也对 Zeppelin 感兴趣,就赶快和我一起来写吧。


内容提要:

  1. 环境说明
  2. 傻瓜解释器
  3. 编写代码
  4. 安装解释器
  5. 创建解释器
  6. 使用解释器
  7. 总结(包含可能遇到的问题)

代码已经上传至 github:https://github.com/iamabug/my-zeppelin-interpreter

1. 环境说明

操作系统:不限

JDK:1.8 以上

IDE:IntelliJ IDEA,并安装了 maven 插件

Zeppelin 版本:0.8.2,安装文档可以参考:如何安装启动Apache Zeppelin

2. 傻瓜解释器

因为我的目的只是了解相关的原理,所以只需要写一个“五脏俱全”的傻瓜解释器就行,所以我要写的解释器功能很简单,在用户的输入前加上调用次数和“hello”作为输出返回给用户,大概效果如下:

$ world
1. hello word

$ iamabug
2. hello iamabug

$ ...

3. 编写代码

在 IDEA 中新建一个 maven 项目,项目名为 my-zeppelin-interpreter,然后修改 pom.xml:

  1. 添加 org.apache.zeppelin:zeppelin-interpreter 依赖;
  2. 添加 maven 插件:maven-enforcer-plugin maven-dependency-plugin maven-resources-plugin

截图如下:

然后新建一个 Class,名为 com.iamabug.DummyInterpreter,让它继承自 org.apache.zeppelin.interpreter.Interpreter,这时因为继承了一个抽象类,IDEA 会提示有错,使用快捷键 Alt + Enter 直接生成构造函数以及和需要重写的方法,共有 6 个方法:

// 初始化解释器
public void open();

// 关闭解释器,释放资源
public void close();

// 运行解释器并返回结果,s 是在 Zeppelin 里输入的代码,interpreterContext 是额外的运行上下文信息
public InterpreterResult interpret(String s, InterpreterContext interpreterContext);

// 取消运行,会中断 interpret 方法的执行
public void cancel();

// 动态表格的处理类型,关于动态表格可以参考:https://zeppelin.apache.org/docs/0.8.2/usage/dynamic_form/intro.html
public ForType getFormType();

// 获取运行进度,返回值为 0-100
public int getProgress();

我编写的解释器类 DummyInterpreter 如下所示:

public class DummyInterpreter extends Interpreter {
  // 增加一个 int 成员变量,记录被调用的次数
  private int count;
  
  public DummyInterpreter(Properties properties) {
    super(properties);
  }
  
  // 其实在构造方法里初始化 count 更合适
  public void open() throws InterpreterException {
    count = 0;
  }
  
  // close 方法不需要做什么
  public void close(){}
  
  // 对输入进行处理,其实就是拼接字符串
  // 将结果封装成 InterpreterResult 类型
  // 其中 InterpreterResult.Code 是枚举类型,表明解释器执行结果的状态
  public InterpreterResult interpret(String s, InterpreterContext interpreterContext) {
    count ++;
    String res = count + ". " + "hello " + s;
    return new InterpreterResult(InterpreterResult.Code.SUCCESS, res);
  }

  // 不考虑 cancel 的情况
  public void cancel(InterpreterContext interpreterContext) {}

  // 动态表格类型,返回 None 枚举类型即可
  public FormType getFormType() {
      return FormType.NONE;
  }

  // 执行进度永远是 100
  public int getProgress(InterpreterContext interpreterContext) {
      return 100;
  }
}

4. 安装解释器

安装分为以下几步:

  1. 将傻瓜解释器的代码打成 jar 包;

  2. 切换到 Zeppelin 的安装目录下,创建 interpreter/dummy 子目录:

    mkdir interpreter/dummy
    
  3. 将第 1 步中的 jar 包拷贝到第 2 步创建的目录中:

    # 这是在我机器上的路径,仅供参考
    cp ~/workspace/Zeppelin/my-zeppelin-interpreter/target/my-zeppelin-interpreter-1.0-SNAPSHOT.jar ~/workspace/Zeppelin/zeppelin-0.8.2-bin-all/interpreter/dummy
    
  4. 在 interpreter/dummy 目录下创建解释器配置文件 interpreter-setting.json,内容如下,group 和 name 都是 dummy,className 是 com.iamabug.DummyInterpreter:

    [
      {
        "group": "dummy",
        "name": "dummy",
        "className": "com.iamabug.DummyInterpreter",
        "properties": {
          "properties1": {
            "envName": null,
            "propertyName": "properties1",
            "defaultValue": "old dummy",
            "description": "kidding",
            "type": "textarea"
          },
          "properties2": {
            "envName": PROPERTIES2,
            "propertyName": null,
            "defaultValue": "little dummy",
            "description": "for fun",
            "type": "textarea"
          }
        }
      }
    ]
    
  5. 编辑 conf/zeppelin-site.xml ,给 zepplin.interpreters 增加 com.iamabug.DummyInterpreter:

    <property>
     <name>zeppelin.interpreters</name>
      <value>com.iamabug.DummyInterpreter,org.apache.zeppelin.spark.SparkInterpreter,...</value>
      <description>Comma separated interpreter configurations. First interpreter become a default</description>
    </property>
    

在第 4 步中我为傻瓜解释器指定了两个配置参数,分别是 properties1 和 properties2,当然这两个参数毫无用处,但是我们注意到每个 property 都有一个 envName 和 propertyName,看起来应该是提供了两种配置方式,一种是在页面配置,另一种是通过环境变量,这样之前给 Spark 解释器配置参数有两种方式也就解释的通了,可以查看 interpreter/spark/interpreter-setting.json 进行验证。

5. 创建解释器

为什么其它的解释器比如 Spark 不需要在页面上创建?我推测内置的解释器在启动时会通过代码创建,额外加的解释器做不到,所以只好在页面上手动创建了。

使用 bin/zeppelin-daemon.sh restart重启 Zeppelin,然后打开浏览器,点击右上角的 anonymous 菜单,选择 Interpreter 子菜单,然后在新页面中点击右上角的 Create 按钮,出现如下页面:

image

在 Interpreter Name 中输入 dummy,点击 Interpreter group 下拉菜单,选择 dummy,如下图所示:

image

可以看到在配置文件里的两个配置项 properties1 和 properties2,点击蓝色的 Save 按钮。

6. 使用解释器

回到首页,创建一个新的 note,选择默认解释器为 dummy,如下图所示:

image

(激动人心的时刻来了!)

在打开的笔记本中随意输入字符,然后运行,运行截图:

image

和预期的效果完全一致。注意,因为 dummy 是默认解释器,所以加不加 %dummy 都可以。

7. 总结

这次实验算是达到了预期,中途遇到的问题有:

  1. getFormType() 方法如果返回 null,会报错;
  2. interpreter/dummy 下的 json 配置文件名字必须叫做 interpreter-setting.json,否则找不到配置;
  3. 创建的解释器的名称和 interpreter 目录下的子目录名称需要保持一致,在本文中都是 dummy ,否则会报 ClassNotFound 的错。

希望本文对你有用。

欢迎交流讨论,吐槽建议,分享收藏。

勤学似春起之苗,不见其增,日有所长
辍学如磨刀之石,不见其损,日有所亏
关注【大数据学徒】,用技术干货助你日有所长

大数据学徒

©著作权归作者所有,转载或内容合作请联系作者
【社区内容提示】社区部分内容疑似由AI辅助生成,浏览时请结合常识与多方信息审慎甄别。
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

相关阅读更多精彩内容

  • 前言 本文基于Apache Zeppelin 0.72版本对Zeppelin的源代码进行分析。 什么是Zeppel...
    柴诗雨阅读 6,475评论 0赞 9
  • 从不在意他人眼光,在自己的世界自由生长
    Fireda阅读 389评论 0赞 0
  • 晴光猜知暖阳悬, 佳人可是独凭栏? 清水自能出芙蓉, 叶底方窥白荷面。
    木石散人阅读 755评论 8赞 32
  • 2018.6.14 今天是致良知四合院APP线上学习,正心班的作业第一天。 反观一路走来,从立志班(30天),到勤...
    若嘉阅读 319评论 1赞 3
  • 忧郁女孩喜欢阴天雨天,觉得灰蒙蒙的一切最美,喜欢看书写字。阳光男孩喜欢晴天,觉得阳光洒下的地方最让人着迷,喜欢...
    阿吉0528阅读 823评论 0赞 1

友情链接更多精彩内容