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之间的依赖关系如下:
- zeppelin源码分析(1)——编译、调试和maven modules分析
- zeppelin源码分析(7)——interpreter调试
- zeppelin源码分析——server端
- Zeppelin源码分析-调度和资源分析(1)
- zeppelin源码分析(2)——distribution assembly过程分析
- zeppelin源码分析(0)——zeppelin要解决什么问题
- zeppelin源码分析(5)——notebook的持久化
- zeppelin源码分析(6)——note的执行过程
- zeppelin源码分析(6)——note的执行过程
- zeppelin源码分析(4)——interpreter的调度和任务封装
- Zeppelin源码分析-调度和资源分析(2)
- zeppelin源码分析(3)——主要的class分析(上)
- zeppelin源码分析(3)——主要的class分析(中)
- zeppelin源码分析(4)——主要的class分析(下)
- Zeppelin源码分析-Interpreter 相关类(1)
- zeppelin源码分析(3)——重要类的class diagram
- Zeppelin源码分析-独立解释器 JVM 相关分析(1)
- 如何源码编译zeppelin
- JDK8与JDK7并存时切换的问题
- Servlet学习笔记
- 最小生成树prim
- hive介绍
- Lua中__index和__newindex实践
- zeppelin源码分析(1)——编译、调试和maven modules分析
- unix编程(九)进程间通信
- 十进制、二进制互转
- 数组------和为定值的多个数
- JAVA-反射学习(3)
- CI框架中pdo的使用方法
- 【Android 学习】AndroidMainfest.xml详解
- c++开发ocx入门实践三--基于opencv的简易视频播发器ocx
- 字典树trie