1. 程式人生 > >一文帶你弄懂Livy——基於Apache Spark的REST服務

一文帶你弄懂Livy——基於Apache Spark的REST服務

背景

Apache Spark作為當前最為流行的開源大資料計算框架,廣泛應用於資料處理和分析應用,它提供了兩種方式來處理資料:一是互動式處理,比如使用者使用spark-shell或是pyspark指令碼啟動Spark應用程式,伴隨應用程式啟動的同時Spark會在當前終端啟動REPL(Read–Eval–Print Loop)來接收使用者的程式碼輸入,並將其編譯成Spark作業提交到叢集上去執行;二是批處理,批處理的程式邏輯由使用者實現並編譯打包成jar包,spark-submit指令碼啟動Spark應用程式來執行使用者所編寫的邏輯,與互動式處理不同的是批處理程式在執行過程中使用者沒有與Spark進行任何的互動。

兩種處理互動方式雖然看起來完全不一樣,但是都需要使用者登入到Gateway節點上通過指令碼啟動Spark程序。這樣的方式會有什麼問題嗎?

首先將資源的使用和故障發生的可能性集中到了這些Gateway節點。由於所有的Spark程序都是在Gateway節點上啟動的,這勢必會增加Gateway節點的資源使用負擔和故障發生的可能性,同時Gateway節點的故障會帶來單點問題,造成Spark程式的失敗。

其次難以管理、審計以及與已有的許可權管理工具的整合。由於Spark採用指令碼的方式啟動應用程式,因此相比於Web方式少了許多管理、審計的便利性,同時也難以與已有的工具結合,如Apache Knox。

同時也將Gateway節點上的部署細節以及配置不可避免地暴露給了登陸使用者。

為了避免上述這些問題,同時提供原生Spark已有的處理互動方式,並且為Spark帶來其所缺乏的企業級管理、部署和審計功能,本文將介紹一個新的基於Spark的REST服務:Livy。

Livy

Livy是一個基於Spark的開源REST服務,它能夠通過REST的方式將程式碼片段或是序列化的二進位制程式碼提交到Spark叢集中去執行。它提供了以下這些基本功能:

提交Scala、Python或是R程式碼片段到遠端的Spark叢集上執行;

提交Java、Scala、Python所編寫的Spark作業到遠端的Spark叢集上執行;

提交批處理應用在叢集中執行。

從Livy所提供的基本功能可以看到Livy涵蓋了原生Spark所提供的兩種處理互動方式。與原生Spark不同的是,所有操作都是通過REST的方式提交到Livy服務端上,再由Livy服務端傳送到不同的Spark叢集上去執行。說到這裡我們首先來了解一下Livy的架構。

Livy的基本架構

Livy是一個典型的REST服務架構,它一方面接受並解析使用者的REST請求,轉換成相應的操作;另一方面它管理著使用者所啟動的所有Spark叢集。具體架構可見圖1。
一文帶你弄懂Livy——基於Apache Spark的REST服務

圖1 Livy的基本架構

使用者可以以REST請求的方式通過Livy啟動一個新的Spark叢集,Livy將每一個啟動的Spark叢集稱之為一個會話(session),一個會話是由一個完整的Spark叢集所構成的,並且通過RPC協議在Spark叢集和Livy服務端之間進行通訊。根據處理互動方式的不同,Livy將會話分成了兩種型別:

互動式會話(interactive session),這與Spark中的互動式處理相同,互動式會話在其啟動後可以接收使用者所提交的程式碼片段,在遠端的Spark叢集上編譯並執行;

批處理會話(batch session),使用者可以通過Livy以批處理的方式啟動Spark應用,這樣的一個方式在Livy中稱之為批處理會話,這與Spark中的批處理是相同的。

可以看到,Livy所提供的核心功能與原生Spark是相同的,它提供了兩種不同的會話型別來代替Spark中兩類不同的處理互動方式。接下來我們具體瞭解一下這兩種型別的會話。

互動式會話(Interactive Session)

使用互動式會話與使用Spark所自帶的spark-shell、pyspark或sparkR相類似,它們都是由使用者提交程式碼片段給REPL,由REPL來編譯成Spark作業並執行。它們的主要不同點是spark-shell會在當前節點上啟動REPL來接收使用者的輸入,而Livy互動式會話則是在遠端的Spark叢集中啟動REPL,所有的程式碼、資料都需要通過網路來傳輸。

我們接下來看看如何使用互動式會話。

建立互動式會話

POST /sessions

一文帶你弄懂Livy——基於Apache Spark的REST服務

使用互動式會話的前提是需要先建立會話。當我們提交請求建立互動式會話時,我們需要指定會話的型別(“kind”),比如“spark”,Livy會根據我們所指定的型別來啟動相應的REPL,當前Livy可支援spark、pyspark或是sparkr三種不同的互動式會話型別以滿足不同語言的需求。

當建立完會話後,Livy會返回給我們一個JSON格式的資料結構表示當前會話的所有資訊:
一文帶你弄懂Livy——基於Apache Spark的REST服務

其中需要我們關注的是會話id,id代表了此會話,所有基於該會話的操作都需要指明其id。

提交程式碼

POST /sessions/{sessionId}/statements
一文帶你弄懂Livy——基於Apache Spark的REST服務

建立完互動式會話後我們就可以提交程式碼到該會話上去執行。與建立會話相同的是,提交程式碼同樣會返回給我們一個id用來標識該次請求,我們可以用id來查詢該段程式碼執行的結果。

查詢執行結果

GET /sessions/{sessionId}/statements/{statementId}
一文帶你弄懂Livy——基於Apache Spark的REST服務

Livy的REST API設計為非阻塞的方式,當提交程式碼請求後Livy會立即返回該請求id而並非阻塞在該次請求上直到執行完成,因此使用者可以使用該id來反覆輪詢結果,當然只有當該段程式碼執行完畢後用戶的查詢請求才能得到正確結果。

當然Livy互動式會話還提供許多不同的REST API來操作會話和程式碼,在這就不一一贅述了。

使用程式設計API

在互動式會話模式中,Livy不僅可以接收使用者提交的程式碼,而且還可以接收序列化的Spark作業。為此Livy提供了一套程式設計式的API供使用者使用,使用者可以像使用原生Spark API那樣使用Livy提供的API編寫Spark作業,Livy會將使用者編寫的Spark作業序列化併發送到遠端Spark叢集中執行。表1就是使用Spark API所編寫PI程式與使用Livy API所編寫的程式的比較。
一文帶你弄懂Livy——基於Apache Spark的REST服務

表1 使用Spark API所編寫PI程式與使用Livy API所編寫程式的比較

可以看到除了入口函式不同,其核心邏輯完全一致,因此使用者可以很方便地將已有的Spark作業遷移到Livy上。

Livy互動式會話是Spark互動式處理基於HTTP的實現。有了Livy的互動式會話,使用者無需登入到Gateway節點上去啟動Spark程序並執行程式碼。以REST的方式進行互動式處理提供給使用者豐富的選擇,也方便了使用者的使用,更為重要的是它方便了運維的管理。

批處理會話(Batch Session)

在Spark應用中有一大類應用是批處理應用,這些應用在執行期間無須與使用者進行互動,最典型的就是Spark Streaming流式應用。使用者會將業務邏輯編譯打包成jar包,並通過spark-submit啟動Spark叢集來執行業務邏輯:

一文帶你弄懂Livy——基於Apache Spark的REST服務
Livy也為使用者帶來相同的功能,使用者可以通過REST的方式來建立批處理應用:
一文帶你弄懂Livy——基於Apache Spark的REST服務
通過使用者所指定的“className”和“file”,Livy會啟動Spark叢集來執行該應用,這樣的一種方式就稱為批處理會話。

至此我們簡單介紹了Livy的兩種會話型別,與它相對應的就是Spark的兩種處理互動方式,因此可以說Livy以REST的方式提供了Spark所擁有的兩種互動處理方式。

企業級特性

前面我們介紹了Livy的核心功能,相比於核心功能的完整性,Livy的企業級特性則更體現了其相比於原生Spark處理互動方式的優勢。本章節將介紹Livy幾個關鍵的企業特性。

多使用者支援

假定使用者tom向Livy服務端發起REST請求啟動一個新的會話,而Livy服務端則是由使用者livy啟動的,這個時候所創建出來Spark叢集使用者是誰呢,會是使用者tom還是livy?在預設情況下這個Spark叢集的使用者是livy。這會帶來訪問許可權的問題:使用者tom無法訪問其擁有許可權的資源,而相對的是他卻可以訪問使用者livy所擁有的資源。

為了解決這個問題Livy引入了Hadoop中的代理使用者(proxy user)模式,代理使用者模式廣泛使用於多使用者的環境,如HiveServer2。在此模式中超級使用者可以代理成普通使用者去訪問資源,並擁有普通使用者相應的許可權。開啟了代理使用者模式後,以使用者tom所建立的會話所啟動的Spark叢集使用者就會是tom。
一文帶你弄懂Livy——基於Apache Spark的REST服務

圖2 Livy多使用者支援

為了使用此功能使用者需要配置“livy.impersonation.enabled”,同時需要在Hadoop中將Livy服務端程序的使用者配置為Hadoop proxyuser 。當然還會有一些Livy的額外配置就不在這展開了。

有了代理使用者模式的支援,Livy就能真正做到對多使用者的支援,不同使用者啟動的會話會以相應的使用者去訪問資源。

端到端安全

在企業應用中另一個非常關鍵的特性是安全性。一個完整的Livy服務中有哪些點是要有安全考慮的呢?

客戶端認證

當用戶tom發起REST請求訪問Livy服務端的時候,我們如何知道該使用者是合法使用者呢?Livy採用了基於Kerberos的Spnego認證。在Livy服務端配置Spnego認證後,使用者發起Http請求之前必須先獲得Kerberos認證,只有通過認證後才能正確訪問Livy服務端,不然的話Livy服務端會返回401錯誤。

HTTPS/SSL

那麼如何保證客戶端與Livy服務端之間HTTP傳輸的安全性呢?Livy使用了標準的SSL來加密HTTP協議,以確保傳輸的Http報文的安全。為此使用者需要配置Livy服務端SSL相關的配置已開啟此功能。

SASL RPC

除了客戶端和Livy服務端之間的通訊,Livy服務端和Spark叢集之間也存在著網路通訊,如何確保這兩者之間的通訊安全性也是需要考慮的。Livy採用了基於SASL認證的RPC通訊機制:當Livy服務端啟動Spark叢集時會產生一個隨機字串用作兩者之間認證的祕鑰,只有Livy服務端和該Spark叢集之間才有相同的祕鑰,這樣就保證了只有Livy服務端才能和該Spark叢集進行通訊,防止匿名的連線試圖與Spark叢集通訊。

將上述三種安全機制歸結起來就如圖3所示。

一文帶你弄懂Livy——基於Apache Spark的REST服務

圖3 Livy端到端安全機制

這樣構成了Livy完整的端到端的安全機制,確保沒有經過認證的使用者,匿名的連線無法與Livy服務中的任何一個環節進行通訊。

失敗恢復

由於Livy服務端是單點,所有的操作都需要通過Livy轉發到Spark叢集中,如何確保Livy服務端失效的時候已建立的所有會話不受影響,同時Livy服務端恢復過來後能夠與已有的會話重新連線以繼續使用?

Livy提供了失敗恢復的機制,當用戶啟動會話的同時Livy會在可靠的儲存上記錄會話相關的元資訊,一旦Livy從失敗中恢復過來它會試圖讀取相關的元資訊並與Spark叢集重新連線。為了使用該特性我們需要配置Livy使其開啟此功能:
一文帶你弄懂Livy——基於Apache Spark的REST服務

失敗恢復能夠有效地避免因Livy服務端單點故障造成的所有會話的不可用,同時也避免了因Livy服務端重啟而造成的會話不必要失效。

結語

本文從Spark處理互動方式的侷限引出了Livy這樣一個基於Spark的REST服務。同時全面介紹了其基本架構、核心功能以及企業級特性,Livy不僅涵蓋了Spark所提供了所有處理互動方式,同時又結合了多種的企業級特性,雖然Livy專案現在還處於早期,許多的功能有待增加和改進,我相信假以時日Livy必定能成為一個優秀的基於Spark的REST服務。

為了幫助大家讓學習變得輕鬆、高效,給大家免費分享一大批資料,幫助大家在成為大資料工程師,乃至架構師的路上披荊斬棘。在這裡給大家推薦一個大資料學習交流圈:658558542 歡迎大家進×××流討論,學習交流,共同進步。

當真正開始學習的時候難免不知道從哪入手,導致效率低下影響繼續學習的信心。

但最重要的是不知道哪些技術需要重點掌握,學習時頻繁踩坑,最終浪費大量時間,所以有有效資源還是很有必要的。

最後祝福所有遇到瓶疾且不知道怎麼辦的大資料程式設計師們,祝福大家在往後的工作與面試中一切順利。