Zeppelin 源碼分析-Interpreter 相關類(1)

和 Interpreter 直接相關類有以下幾個:
Interpreter, InterpreterFactory, RemoteInterpreter, InterpreterGroup, InterpreterSetting。
由於篇幅有限,這裏分開介紹。

Interpreter 類及其子類

Interpreter 是一個接口,所有的子類如下(只列舉出 SparkInterpreter ):

其中除了 SparkInterpreter 等具體的完成解釋功能的類,其餘的實現類全部運行在主進程中。

RomoteInterpreter

RomoteInterpreter 類是 SparkInterpreter 等具體的完成解釋功能的類的本地代理,其實就可以看成 Thrif 協議的客戶端,但是其實這個對象並沒有直接持有 Client 類對象的引用,而是在使用 Client 類的時候,用 RemoteInterpreterProcess 對象的方法獲得,這在解釋器工廠類的 createInterpretersForNote 會詳細介紹。
然後比較坑的就是官方那張圖:
圖片名稱
之前一直以爲Thrift 的 Server只有一個,但其實程序跑起來之後實際其實應該是這樣:

圖中的 RemoteInterpreterServer 類是一個線程,並實現了 RemoteInterpreterService.Iface 類,表明這是 Thrif 協議的服務器端( Thrift 協議簡單來說就是:有一個 Client 和 Server ,兩個運行在不同的 JVM,Server 對外開放指定端口,Client 可以通過服務器開放的端口來調用服務器相應的方法,相應方法在 XXX.thrift 文件中定義,然後可以直接使用 Thirft 官方提供的工具和 XXX.thrift 文件生成指定語言的代碼,然後使用時只需要遵循規範實現一些類即可),RemoteInterpreterServer 類中通過反射的方法將具體的解釋器進程啓動,它和具體的解釋器在同一個 JVM 線程中,啓動代碼如下:

Class<Interpreter> replClass = (Class<Interpreter>) Object.class.forName(className);
Properties p = new Properties();
p.putAll(properties);
setSystemProperty(p);

Constructor<Interpreter> constructor =
    replClass.getConstructor(new Class[] {Properties.class});
Interpreter repl = constructor.newInstance(p);
repl.setClassloaderUrls(new URL[]{});

RomoteInterpreter 類和 RemoteInterpreterServer 類是直接交互的類(依靠 Thrift 協議),當在主進程中調用 RomoteInterpreter 類的 Client 對象的方法時,其實會調用 RemoteInterpreterServer 類的同名的方法,RomoteInterpreter 類存有 RemoteInterpreterProcess 的對象(之後的文件會說這個類),通過這個對象可以獲取到 Thrift 的 Client 對象。

SparkInterpreter 等具體實現類

這些類是真正幹活的類,前面說過和 RomoteInterpreter 類直接交互的是 RemoteInterpreterServer 類,在 Thrift 客戶端調用服務器相應的方法時,服務器端會調用具體的解釋器的相應方法,比如 RemoteInterpreterServer 類的 interpret代碼如下:(雖然封裝成了 Job,但是最終還是調用了 SparkInterpreter 等具體實現類的 interpret 方法,這個調度問題在之後會說):

@Override
public RemoteInterpreterResult interpret(String noteId, String className, String st,
    RemoteInterpreterContext interpreterContext) throws TException {
  // 省略
  Interpreter intp = getInterpreter(noteId, className);
  InterpretJob job = new InterpretJob(
      interpreterContext.getParagraphId(),
      "remoteInterpretJob_" + System.currentTimeMillis(),
      jobListener,
      JobProgressPoller.DEFAULT_INTERVAL_MSEC,
      intp,
      st,
      context);
      }
  // 省略
}

ClassLoaderInterpreter 和 LazyOpenInterpreter

WrappedInterpreter 是一個接口,作用其實就是包裝 Interpreter 的實現類,他有兩個實現類:ClassLoaderInterpreter 和 LazyOpenInterpreter,該接口的定義如下:

public interface WrappedInterpreter {
  public Interpreter getInnerInterpreter();
}

ClassLoaderInterpreter 其實就是運行在主進程的具體解釋器的封裝,但是由於目前所有的具體解釋器都運行在獨立的 JVM 中,因此這個類其實沒有什麼作用,該類在 InterpreterFactor 被構造,關鍵代碼如下:

// InterpreterFactor 中該類被構造
Class<Interpreter> replClass = (Class<Interpreter>) cl.loadClass(className);
Constructor<Interpreter> constructor =
    replClass.getConstructor(new Class[]{Properties.class});
Interpreter repl = constructor.newInstance(property);
repl.setClassloaderUrls(ccl.getURLs());
LazyOpenInterpreter intp = new LazyOpenInterpreter(new ClassloaderInterpreter(repl, cl));

// InterpreterFactor 類字段
private ClassLoader cl;
private Interpreter intp;

LazyOpenInterpreter 正如其名,其實是對 RomoteInterpreter 的簡單封裝,存在的意義就是可以延後啓動,字段如下:

private Interpreter intp;
volatile boolean opened = false;
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章