Livy Session 詳解(上)
本文基於 incubator-livy 0.4.0-incubating
從的介紹中我們可以知道,livy 共有兩種 job,分別是 session 和 batch。然而,在原始碼實現中,session 和 batch 都是 Session 的子類,rest api 中的 session 對應原始碼中的 InteractivateSession
;rest api 中的 batch 對應原始碼中的 BatchSession
。在之後關於 livy 的所有文章中,session 或 batch 對應 rest api 中的含義,InteractivateSession
和 BatchSession
及 Session
都對應程式碼中的含義。
session 和 batch 的建立過程也很不相同,batch 的建立以對應的 spark app 啟動為終點;而 session 除了要啟動相應的 spark app,還要能支援共享 sparkContext 來接受一個個 statements 的提交及執行,我將 session 的建立分為兩個大步驟:
client 端:執行在 LivyServer 中,接受 request 直到啟動 spark app(注意,這裡雖然叫 client 端,但是執行在 LivyServer 中的)
server 端:session 對應的 spark app driver 的啟動
這篇文章主要講講 client 端
都做了些什麼
一:整體流程
create session-livy client side.png
一圖勝千言,上圖就是建立一個 session 在 client 端的主要流程,我們將以註釋的方式來說明那些沒那麼重要或複雜的流程,而核心的流程都在下文中分小節進行剖析。
二:啟動 session 對應的 spark app
接下來直搗黃龍,直接到第 (8) 步 ContextLauncher#startDriver
看看 session 對應的 spark app 是如何啟動的。ContextLauncher#startDriver
可以分為兩個大步驟:
啟動 spark app
等待 SparkSubmit 退出
2.2:啟動 spark app
startDriver.png
如上圖,startDriver 無非就是 new 了一個 SparkLauncher
物件,進行了配置、資源、mainClass 等設定,然後呼叫 launch()
方法拿到了 SparkSubmit 程式的 對應的 Process 物件 process。
可以看到,session 對應的 spark app 的 mainClass 為 org.apache.livy.rsc.driver.RSCDriverBootstrapper
2.3:等待 SparkSubmit 退出
SparkLauncher#launch()
返回的程式是 SparkSubmit 程式,再返回 process 後,會 new 一個 ContextLauncher.ChildProcess
物件,在過程中會新啟動一個執行緒來一直等待 SparkSubmit 程式退出,該執行緒中的邏輯如下:若 SparkSubmit 非正常退出(exitCode != 0),表示 Spark App 啟動失敗,會拋異常
public void run() { try { int exitCode = child.waitFor(); if (exitCode != 0) { LOG.warn("Child process exited with code {}.", exitCode); fail(new IOException(String.format("Child process exited with code %d.", exitCode))); } } catch (InterruptedException ie) { LOG.warn("Waiting thread interrupted, killing child process."); Thread.interrupted(); child.destroy(); } catch (Exception e) { LOG.warn("Exception while waiting for child process.", e); } }
三:與 driver 建立連線
我們知道,session 最大的特點就是可以共享 SparkContext,讓使用者提交的多個程式碼片段都能跑在一個 SparkContext 上,這有兩個好處:
大大加速任務的啟動速度:我們知道,在 yarn 上啟動一個 app 是比較耗時的,一般都需要 20s 左右;而使用 session,除了啟動 session 也需要相當的耗時外,之後提交的程式碼片段都將立即執行
共享 RDD、table:持久化的 RDD、table 都可以被之後的程式碼片段使用,這在不同使用者需要在相同的 RDD、table 上做計算的場景非常有用
而共享 SparkContext 就需要 client 與 driver 之間建立起連線,能讓 client 向 driver 傳送程式碼片段、查詢執行狀態、獲取執行結果等
3.1:client 傳遞其 RpcServer 資訊給 driver
時序圖中的第 (5) 步:RSCClientFactory#createClient
,在該呼叫中建立了一個 org.apache.livy.rsc.rpc.RpcServer
(後文簡稱 RpcServer)物件賦值給成員 server。該 server 會在 driver 啟動時被 driver 中的 rpc client 連線並告知 driver 中的 RpcServer 的資訊,以便之後 client 端可以透過該資訊向 driver 中的 RpcServer 發起連線及請求。由於 driver 可能被 yarn 排程到任何一個節點啟動,所以無法由 LivyServer 主動與 driver 建立連線,而是預先在 client 端建立好 RpcServer 等待 driver 來連線。
另外,RpcServer 與 rpc client 是透過一個由 RpcServer 自身生成的 secret 進行匹配的。要能讓 driver 連線到該 RpcServer,還需要知道 LivyServer 的 host 和 port,這這些資訊都是透過 conf 傳給 driver 的,在 ContextLauncher
建構函式中實現:
// 生成 client idthis.clientId = UUID.randomUUID().toString();// 由server 生成 secretthis.secret = factory.getServer().createSecret(); ... conf.set(LAUNCHER_ADDRESS, factory.getServer().getAddress()); conf.set(LAUNCHER_PORT, factory.getServer().getPort()); conf.set(CLIENT_ID, clientId); conf.set(CLIENT_SECRET, secret);
這些配置最終也將作為啟動 driver 的 conf 的一部分傳給 driver,這樣 driver 在啟動後就知道 client 中的 RpcServer 的地址和 secret 了
3.2:driver 連線 client 並傳遞其 RpcServer 資訊
rscdriver-init.png
該過程在 RSCDriver#initializeServer
中實現,是 seesion driver 的初始化步驟
3.3:client 接收 driver rpcServer 地址資訊並連線
在 client 傳遞其 RpcServer 資訊給 driver
之前已經為 RSCClientFactory
物件的成員 server: RpcServer
註冊了 client 以及相應 client 成功連線的處理函式:
final RegistrationHandler handler = new RegistrationHandler(); factory.getServer().registerClient(clientId, secret, handler);
這裡的 clientId、secret 即 3.1 小節中傳遞給 driver 的。Registration
類用來處理 driver 端的 rpcClient 連線到 server 時的處理邏輯,即:
private void handle(ChannelHandlerContext ctx, RemoteDriverAddress msg) { ContextInfo info = new ContextInfo(msg.host, msg.port, clientId, secret); if (promise.trySuccess(info)) { timeout.cancel(true); } }
引數 RemoteDriverAddress msg
即在 3.2 小節中 driver 中的 rpcClient 傳送給 server 的 driver 中 rpcServer 的地址(包括 address、host),之後再結合 clientId、serrect 來構造 ContextInfo info
來觸發 promise.trySuccess(info)
,info 表名了 driver 中 rpcServer 的地址已經發起連線需要的 clientId、secret,這與 3.2 小節中 driver 中的 rpcServer 註冊的 client 資訊相符。
在建立 RSCClient 物件時會在 promise 上 add 相應的 listener,promise.trySuccess(info)
會觸發 onSuccess(ContextInfo info)
進而呼叫 connectToContext(info)
:
Utils.addListener(this.contextInfoPromise, new FutureListener<ContextInfo>() { @Override public void onSuccess(ContextInfo info) throws Exception { connectToContext(info); ... } @Override public void onFailure(Throwable error) { connectionError(error); ... } })
在 connectToContext(info)
方法中會使用拿到的 driver 端 rpcServer 的連線資訊發起連線得到 driverRpc,即用於向 driver 端 rpcServer 傳送 rpc 呼叫的 client,這是 RSCClient 的成員,之後 RSCClient 和 driver 之間的通訊都透過 driverRpc 來進行。
四:Session 的建立與初始化
new InteractiveSession and init
在與 driver 建立連線之後,會使用 rscClient、livyConf 等資訊來建立 InteractiveSession 物件並進行初始化,流程如上。初始化過程彙總,比較關鍵的步驟是將 session 資訊儲存到 state store 中以便livy server 掛掉後能進行 recovery;再就是向 driver 傳送一個空的 PingJob 來確定 driver 的狀態是否 ok,若 PingJob 成功執行,則說明 driver 狀態 ok,將 session 置為 running 狀態;若出錯或失敗,則說明 driver 出了一些問題,則將 session 的狀態置為 error。
在成功完成 session 的建立及初始化後,會將 session 新增到 SessionManager 中進行統一管理。SessionManager 的主要職責包括:
持有所有 sessions
清理過期 session
從 state store 中恢復 sessions
作者:牛肉圓粉不加蔥
連結:
來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/4650/viewspace-2819015/,如需轉載,請註明出處,否則將追究法律責任。
相關文章
- Cookie & Session詳解CookieSession
- v$Session詳解Session
- Cookie與Session詳解CookieSession
- http協議/cookie詳解/session詳解HTTP協議CookieSession
- Cookie,Session Filter,Listener詳解CookieSessionFilter
- cookie和session的詳解與區別CookieSession
- MQTT 持久會話與 Clean Session 詳解MQQT會話Session
- oracle中的processes,session,transaction引數詳解OracleSession
- cookie與session的區別(圖文詳解)CookieSession
- RabbitMQ詳解(上)MQ
- Docker詳解(上)Docker
- Node.js+Express 開發之Cookie、Session 使用詳解Node.jsExpressCookieSession
- appuploader 上架詳解大全(上)APP
- oreo上的notification詳解
- Binder 驅動詳解(上)
- 【詳解】Tomcat是如何監控並刪除超時Session的?TomcatSession
- 從koa-session原始碼解讀session原理Session原始碼
- 圖片上傳方案詳解
- koa 圖片上傳詳解
- Java Web(5)-Servlet詳解(上)JavaWebServlet
- Java物件導向詳解-上Java物件
- 詳解Vue生命週期【上】Vue
- SoC片上系統詳解
- appuploader 上架詳解大全(下)APP
- 詳解HashMap原始碼解析(上)HashMap原始碼
- keycloak~關於session idle和session max的解釋Session
- 不要用JWT替代session管理(上):全面瞭解Token,JWT,OAuth,SAML,SSOJWTSessionOAuth
- Kubernetes上的負載均衡詳解負載
- 檔案上傳漏洞思路詳解
- 軟體架構-nginx詳解上架構Nginx
- Springcloud及Git線上配置詳解SpringGCCloudGit
- 檔案上傳(解析)漏洞詳解
- Cookie&Session概念解讀CookieSession
- iOS AppStore上架流程圖文詳解2021版 (上)iOSAPP流程圖
- SpringBoot實現檔案上傳功能詳解Spring Boot
- 上萬字詳解Spark Core(建議收藏)Spark
- Laravel核心解讀–Session原始碼解析LaravelSession原始碼
- 你真的瞭解 Cookie 和 Session 嗎CookieSession