zeppelin源码分析(1)——编译、调试和maven modules分析

来源:互联网 发布:js insertbefore 方法 编辑:程序博客网 时间:2024/05/17 23:14

Zeppelin,于2016-5-18日从Apache孵化器项目毕业成为Apache顶级项目,采用Java(主要)+Scala+R+PythonR+Bash+JS混合开发,采用maven作为build工具。涉及的主要技术stack如下:

1)      前台:AngularJS、Node.JS、WebSocket、Grunt、Bower、Highlight.js、BootStrap3js

2)      后台:Jetty(embedding)、Thrift、Shiro(权限)、Apache common-exec、Jersey REST API。

具体技术占比:


zeppelin本质上是一个web应用程序,它以独立的jvm进程的方式来启动Interpreter(解释器),交互式(repl)执行各种语言的代码片段,并将结果以html代码片段的形式返回给前端UI。

1     Zeppelin的编译

编译环境:Oracle JDK7.x、maven3.x+、Node.js(npm)

Git源码地址:https://github.com/apache/zeppelin.git(注意不要再从如下旧的git地址更新了https://github.com/apache/incubator-zeppelin.git)

以下将${ZEPPELIN_HOME}指代git clone之后源码的根目录。使用如下maven命令编译并生成zeppelin的发布包:

mvn cleaninstall -Pbuild-distr -Pspark-1.6 -Dspark.version=1.6.1 -Phadoop-2.6 -Dhadoop.version=2.7.2-Pyarn[-Pr|-Psparkr]-Ppyspark -DskipTests -X

解释:

1)      执行install是为了将artifact安装到maven本地仓库,便于之后import到IDE进行调试。

2)      -Pbuild-distr,表示启用build-distr这个maven profile是为了在zeppelin-distribution这个module中生成可分发包。

3)      [-Pr|-Psparkr]需要注意,表示这2个profile只能启用一个,这2个profile编译出来的Interpreter会bind到相同的名字%r,造成冲突(参见zeppelin的mailinglist)。–Pr,表示启用r这个mavenprofile,会将${ZEPPELIN_HOME}/r作为一个module参与编译,编译完成得到sparkR Interpreter。运行zeppelin自带的R Tutorial这个Note,需要改Interpreter。-Pspark-1.6这个profile并不会使得sparkr这个Interpreter被编译打包,因为该Interpreter的编译在${ZEPPELIN_HOME}/zeppelin-spark/pom.xml中采用id=exclude-sparkr,activeByDefault=true的profile默认禁用掉了。如下:

常见错误解决:

如果在maven build过程中,出现enforcer或者check-style相关的错误,注释掉${ZEPPELIN_HOME}/pom.xml中相关plugin的<executions></executions>部分,以禁用在mavenlifecycle中执行该plugin的相关goal。

2    distribution结构分析

编译完成之后,会在zeppelin-distribution/target/目录下生成如下结构的分发包:

2.1    bin

bin目录存储了zeppelin的启停控制脚本:

各个脚本作用如下:

脚本

作用

zeppelin-daemon.sh

提供以daemon形式启停

org.apache.zeppelin.server.ZeppelinServer

服务,并调用common.sh和function.sh设置env和classpath

zeppelin.sh

以foreground的形式启动ZeppelinServer

Interpreter.sh

采用单独进程启动

org.apache.zeppelin.interpreter.remote.RemoteInterpreterServer

服务,该脚本不会被其他脚本直接调用,实际是通过apache common-exec来调用的

common.sh

设置zeppelin运行时需要的env和classpath,如果${ZEPPELIN_HOME}/conf/目录中存在zeppelin-env.sh,则会调用该脚本

function.sh

一些公共基础函数

2.2    conf

配置文件

作用

shiro.ini

供apache shiro框架使用的权限控制文件

zeppelin-env.sh

供${ZEPPELIN_HOME}/bin/common.sh脚本调用,设置诸如:SPARK_HOME、HADOOP_CONF_DIR等zeppelin与外围环境集成的环境变量

zeppelin-site.xml.template

zeppelin的配置模板,被注释掉的property是zeppelin的默认配置,可以rename成zeppelin-site.xml然后根据需要override

2.3    interpreter

每个针对具体的某种语言实现的Interpreter,存放的是编译好的jar包,以及该interpreter的依赖,其中spark子目录的结构如下:

需要注意的是:如果定义了SPARK_HOME环境变量,该目录下的zeppelin-spark*.jar脚本将通过${SPARK_HOME}/bin/spark-submit到spark集群上去执行。

详情参见${ZEPPELIN_HOME}/bin/interpreter.sh脚本。

2.4    notebook

该目录是默认的notebook的持久化存储目录,zeppelin默认的notebook持久化实现类是org.apache.zeppelin.notebook.repo.VFSNotebookRepo,该实现会以zeppelin.notebook.dir配置参数指定的路径来存储notebook(默认是json格式)

<property>  <name>zeppelin.notebook.dir</name>  <value>notebook</value>  <description>path or URI for notebook persist</description></property>

由于该value指定的uri不带schema,默认会在${ZEPPELIN_HOME}目录下创建notebook子目录用于存储各个notebook,以notebook的id为子目录名字。

3   zeppelin源码调试

1)      首先必须保证执行过mvn install,该命令保证所有的artifact均已安装到maven的本地仓库。

2)      以idea为例,安装maven和scala插件。然后import现有的maven的工程。

3)      新建Maven Debug Configuration,有2点需要注意:

a)  working directory的设置必须到zeppelin-server,不能直接到zeppelin.git(我本机的${ZEPPELIN_HOME},zeppelin-server的上一级)。

b) 使用maven 的exec:javaplugin来执行,让maven管理classpath。

4)      打开org.apache.zeppelin.server.ZeppelinServer,在main之后设置断点即可启动调试。

4     源码结构分析

4.1    module组成

zeppelin的maven项目共有26个module,其中7个框架相关的module如下:

Module

作用

开发语言

zeppelin-server

项目的主入口,通过内嵌Jetty的方式提供Web UI和REST服务,并且提供了基本的权限验证服务

java

zeppelin-zengine

实现Notebook的持久化、检索

实现interpreter的自动加载,以及maven式的依赖自动加载

java

zeppelin-interpreter

为了支持多语言Notebook,抽象出了每种语言都要事先的Interpreter接口,包括:显示、调度、依赖以及和zeppelin-engine之间的Thirft通信协议

java

zeppelin-web

AngluarJS开发的web页面

Javascript(主要是AngularJS、Node.JS以及使用websocket)

zeppelin-display

实现向前台Angular元素绑定后台数据

scala

zeppelin-spark-dependencies

无具体功能,maven的最佳实践,将多个module都要依赖的公共类单独抽离出来,供其他module依赖。目前zeppelin-zinterpreter和zeppelin-spark这2个module依赖它

 

zeppelin-distribution

为了将整个项目打包成发布版,而设置的module,打包格式见src/assembly/distribution.xml。

 

zeppelin的框架部分代码主要是以上几个module,余下19个module全部是为了支持各种语言的interpreter实现的module,如下:

Module

作用

开发语言

zeppelin-spark

实现Spark、PySpark、SparkR、SparkSql等Interpreter

java+scala

zeppelin-zinterpreter

实现R Interpreter (PS:需要在${ZEPPELIN_HOME}/pom.xml中增加<module>r</module>)

R+java+scala

zeppelin-hive

实现HiveQL Interpreter,需要hive client

java

zeppelin-hbase

实现HBase Interpreter,需要hbase client,实际使用ruby脚本${HBASE_HOME}/bin/hirb.rb,来执行UI传入的脚本

java

zeppelin-shell

实现shell interpreter

java

zeppelin-file

使用WebHDFS实现hdfs fs命令

java

zeppelin-postgresql

实现带自动补全功能的psql interpreter,使用jline实现自动补全

java

zeppelin-jdbc

实现通用的jdbc sql Interpreter

java

zeppelin-markdown

实现MarkDown Interpreter

java

zeppelin-phoenix

实现phoenixInterpreter

java

zeppelin-elasticsearch

实现ES interpreter

java

zeppelin-canssandra

实现canssandra Interpreter

java+scala

zeppelin-kylin

实现支持kylin OLAP引擎的interpreter

java

zeppelin-angular

实现支持angularJS引擎

java

zeppelin-alluxio

实现alluxio Interpreter,原tacyon

java

zeppelin-lens

实现lens interpreter

java

zeppelin-ignite

实现ignite Interpreter

java

zeppelin-flink

实现flink interpreter

java

zeppelin-tajo

实现tajo Interpreter

java

关于如何定制interpreter支持新语言,参见how to write a zeppelin interpreter。

4.2     module间依赖关系

Module之间的依赖关系如下:


1 0
原创粉丝点击