文章首發(fā)于公眾號(hào)【大數(shù)據(jù)學(xué)徒】,感興趣請(qǐng)搜索 dashujuxuetu 或者文末掃碼關(guān)注。
這是我想深入研究 Apache Zeppelin 所做的一個(gè)嘗試,畢竟如果想要了解內(nèi)在的原理,有必要先將它暴露出來的功能都摸透,自己寫一個(gè) Zeppelin 解釋器對(duì)于理解其它的解釋器也非常有幫助,其實(shí) 官方文檔 中已經(jīng)給出了具體的方法,本文就是我 follow 官方文檔的一次實(shí)踐(雖然步驟并不完全一樣),如果你也對(duì) Zeppelin 感興趣,就趕快和我一起來寫吧。
內(nèi)容提要:
- 環(huán)境說明
- 傻瓜解釋器
- 編寫代碼
- 安裝解釋器
- 創(chuàng)建解釋器
- 使用解釋器
- 總結(jié)(包含可能遇到的問題)
代碼已經(jīng)上傳至 github:https://github.com/iamabug/my-zeppelin-interpreter
1. 環(huán)境說明
操作系統(tǒng):不限
JDK:1.8 以上
IDE:IntelliJ IDEA,并安裝了 maven 插件
Zeppelin 版本:0.8.2,安裝文檔可以參考:如何安裝啟動(dòng)Apache Zeppelin
2. 傻瓜解釋器
因?yàn)槲业哪康闹皇橇私庀嚓P(guān)的原理,所以只需要寫一個(gè)“五臟俱全”的傻瓜解釋器就行,所以我要寫的解釋器功能很簡單,在用戶的輸入前加上調(diào)用次數(shù)和“hello”作為輸出返回給用戶,大概效果如下:
$ world
1. hello word
$ iamabug
2. hello iamabug
$ ...
3. 編寫代碼
在 IDEA 中新建一個(gè) maven 項(xiàng)目,項(xiàng)目名為 my-zeppelin-interpreter,然后修改 pom.xml:
- 添加
org.apache.zeppelin:zeppelin-interpreter依賴; - 添加 maven 插件:
maven-enforcer-pluginmaven-dependency-pluginmaven-resources-plugin
截圖如下:
然后新建一個(gè) Class,名為 com.iamabug.DummyInterpreter,讓它繼承自 org.apache.zeppelin.interpreter.Interpreter,這時(shí)因?yàn)槔^承了一個(gè)抽象類,IDEA 會(huì)提示有錯(cuò),使用快捷鍵 Alt + Enter 直接生成構(gòu)造函數(shù)以及和需要重寫的方法,共有 6 個(gè)方法:
// 初始化解釋器
public void open();
// 關(guān)閉解釋器,釋放資源
public void close();
// 運(yùn)行解釋器并返回結(jié)果,s 是在 Zeppelin 里輸入的代碼,interpreterContext 是額外的運(yùn)行上下文信息
public InterpreterResult interpret(String s, InterpreterContext interpreterContext);
// 取消運(yùn)行,會(huì)中斷 interpret 方法的執(zhí)行
public void cancel();
// 動(dòng)態(tài)表格的處理類型,關(guān)于動(dòng)態(tài)表格可以參考:https://zeppelin.apache.org/docs/0.8.2/usage/dynamic_form/intro.html
public ForType getFormType();
// 獲取運(yùn)行進(jìn)度,返回值為 0-100
public int getProgress();
我編寫的解釋器類 DummyInterpreter 如下所示:
public class DummyInterpreter extends Interpreter {
// 增加一個(gè) int 成員變量,記錄被調(diào)用的次數(shù)
private int count;
public DummyInterpreter(Properties properties) {
super(properties);
}
// 其實(shí)在構(gòu)造方法里初始化 count 更合適
public void open() throws InterpreterException {
count = 0;
}
// close 方法不需要做什么
public void close(){}
// 對(duì)輸入進(jìn)行處理,其實(shí)就是拼接字符串
// 將結(jié)果封裝成 InterpreterResult 類型
// 其中 InterpreterResult.Code 是枚舉類型,表明解釋器執(zhí)行結(jié)果的狀態(tài)
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) {}
// 動(dòng)態(tài)表格類型,返回 None 枚舉類型即可
public FormType getFormType() {
return FormType.NONE;
}
// 執(zhí)行進(jìn)度永遠(yuǎn)是 100
public int getProgress(InterpreterContext interpreterContext) {
return 100;
}
}
4. 安裝解釋器
安裝分為以下幾步:
將傻瓜解釋器的代碼打成 jar 包;
-
切換到 Zeppelin 的安裝目錄下,創(chuàng)建
interpreter/dummy子目錄:mkdir interpreter/dummy -
將第 1 步中的 jar 包拷貝到第 2 步創(chuàng)建的目錄中:
# 這是在我機(jī)器上的路徑,僅供參考 cp ~/workspace/Zeppelin/my-zeppelin-interpreter/target/my-zeppelin-interpreter-1.0-SNAPSHOT.jar ~/workspace/Zeppelin/zeppelin-0.8.2-bin-all/interpreter/dummy -
在
interpreter/dummy目錄下創(chuàng)建解釋器配置文件interpreter-setting.json,內(nèi)容如下,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" } } } ] -
編輯
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 步中我為傻瓜解釋器指定了兩個(gè)配置參數(shù),分別是
properties1和properties2,當(dāng)然這兩個(gè)參數(shù)毫無用處,但是我們注意到每個(gè) property 都有一個(gè)envName和propertyName,看起來應(yīng)該是提供了兩種配置方式,一種是在頁面配置,另一種是通過環(huán)境變量,這樣之前給 Spark 解釋器配置參數(shù)有兩種方式也就解釋的通了,可以查看interpreter/spark/interpreter-setting.json進(jìn)行驗(yàn)證。
5. 創(chuàng)建解釋器
為什么其它的解釋器比如 Spark 不需要在頁面上創(chuàng)建?我推測內(nèi)置的解釋器在啟動(dòng)時(shí)會(huì)通過代碼創(chuàng)建,額外加的解釋器做不到,所以只好在頁面上手動(dòng)創(chuàng)建了。
使用 bin/zeppelin-daemon.sh restart重啟 Zeppelin,然后打開瀏覽器,點(diǎn)擊右上角的 anonymous 菜單,選擇 Interpreter 子菜單,然后在新頁面中點(diǎn)擊右上角的 Create 按鈕,出現(xiàn)如下頁面:

在 Interpreter Name 中輸入 dummy,點(diǎn)擊 Interpreter group 下拉菜單,選擇 dummy,如下圖所示:

可以看到在配置文件里的兩個(gè)配置項(xiàng) properties1 和 properties2,點(diǎn)擊藍(lán)色的 Save 按鈕。
6. 使用解釋器
回到首頁,創(chuàng)建一個(gè)新的 note,選擇默認(rèn)解釋器為 dummy,如下圖所示:

(激動(dòng)人心的時(shí)刻來了?。?/p>
在打開的筆記本中隨意輸入字符,然后運(yùn)行,運(yùn)行截圖:

和預(yù)期的效果完全一致。注意,因?yàn)?dummy 是默認(rèn)解釋器,所以加不加 %dummy 都可以。
7. 總結(jié)
這次實(shí)驗(yàn)算是達(dá)到了預(yù)期,中途遇到的問題有:
-
getFormType()方法如果返回null,會(huì)報(bào)錯(cuò); -
interpreter/dummy下的 json 配置文件名字必須叫做interpreter-setting.json,否則找不到配置; - 創(chuàng)建的解釋器的名稱和
interpreter目錄下的子目錄名稱需要保持一致,在本文中都是dummy,否則會(huì)報(bào)ClassNotFound的錯(cuò)。
希望本文對(duì)你有用。
歡迎交流討論,吐槽建議,分享收藏。
勤學(xué)似春起之苗,不見其增,日有所長
輟學(xué)如磨刀之石,不見其損,日有所虧
關(guān)注【大數(shù)據(jù)學(xué)徒】,用技術(shù)干貨助你日有所長
