如何在 Apache Flink 中使用 Python API?

大濤學長發表於2019-09-11
本文根據 Apache Flink 系列直播課程整理而成,由 Apache Flink PMC,阿里巴巴高階技術專家 孫金城 分享。重點為大家介紹 Flink Python API 的現狀及未來規劃,主要內容包括:Apache Flink Python API 的前世今生和未來發展;Apache Flink Python API 架構及開發環境搭建;Apache Flink Python API 核心運算元介紹及應用。

一.Apache Flink Python API 的前世今生和未來發展

1.Flink 為什麼選擇支援 Python

Apache Flink 是流批統一的開源大資料計算引擎,在 Flink 1.9.0 版本開啟了新的 ML 介面和全新的Python API架構。那麼為什麼 Flink 要增加對 Python 的支援,下文將進行詳細分析。

  • 最流行的開發語言

1.jpg

Python 本身是非常優秀的開發語言,據 RedMonk 資料統計,除 Java 和 JavaScript 之外,受歡迎度排名第三。

RedMonk 是著名的以開發人員為中心的行業分析公司,其更詳細的分析資訊,大家在拿到我的PPT之後,可以點選連結進行詳細查閱。好了,那麼Python的火熱,與我們今天向大家分享的流批統一的大資料計算引擎,Apache Flink有什麼關係呢?帶著這個問題,我們大家想想目前與大資料相關的著名的開源元件有哪些呢?比如說最早期的批處理框架Hadoop?流計算平臺Storm,最近異常火熱的Spark?異或其他領域數倉的Hive,KV儲存的HBase?這些都是非常著名的開源專案,那麼這些專案都無一例外的進行了Python API的支援。

  • 眾多開源專案支援

2.jpg

Python 的生態已相對完善,基於此,Apache Flink 在 1.9 版本中也投入了大量的精力,去推出了一個全新的 Pyflink。除大資料外,人工智慧與Python也有十分密切的關係。

  • ML青睞的語言

3.jpg

從上圖統計資料可以發現,Python API 本身已經佔機器學習崗位需求語言的 0.129%。相對於 R 語言,Python 語言似乎更受青睞。Python 作為解釋型語言,語法的設計哲學是”用一種方法並且只有一種方法來做一件事”。其簡潔和易用性使其成為了世界上最受歡迎的語言,在大資料計算領域都有著很好的生態建設,同時Python在機器學習 在機器學習方面也有很好的前景,所以我們在近期釋出的Apache Flink 1.9 以全新的架構推出新的 Python API

Flink 是一款流批統一的計算引擎,社群非常重視和關注 Flink 使用者,除 Java 語言或者 Scala 語言,社群希望提供多種入口,多種途徑,讓更多的使用者更方便的使用 Flink,並收穫 Flink 在大資料算力上帶來的價值。因此 Flink 1.9 開始,Flink 社群以一個全新的技術體系來推出 Python API,並且已經支援了大部分常用的一些運算元,比如如 JOIN,AGG,WINDOW 等。

2.Python API – RoadMap

4.jpg

在 Flink 1.9 中雖然 Python 可以使用 Java 的 User-defined Function,但是還缺乏 Python native 的 User-defined function 的定義,所以我們計劃在 Flink 1.10 中進行支援 Python User-defined function 的支援。並技術增加對資料分析工具類庫 Pandas 的支援,在 Flink 1.11 增加對 DataStream API 和 ML API 的支援。

二.Python API架構及開發環境搭建

1.Python Table API架構

5.jpg

新的 Python API 架構分為使用者 API 部分,PythonVM 和 Java VM 的通訊部分,和最終將作業提交到 Flink 叢集進行執行的部分。那麼 PythonVM 和 JavaVM 是怎樣通訊的呢?我們在Python 端會會有一個 Python 的 Gateway 用於保持和 Java 通訊的連結,在 Java 部分有一個 GateWayServer 用於接收 Python 部分的呼叫請求。

關於 Python API 的架構部分,在 1.9 之前,Flink 的 DataSet 和 DataStream 已經有了對 Python API 的支援,但是擁有 DataSet API 和 DataStream API 兩套不同的 API。對於 Flink 這樣一個流批統一的流式計算引擎來講,統一的架構至關重要。並且對於已有的 Python DataSet API 和 DataStream API 而言,採用了JPython 的技術體系架構,而 JPython 本身對目前 Python 的 3.X 系列無法很好的支援,所以 Flink 1.9 釋出後,決定將原有的 Python API 體系架構廢棄,以全新的技術架構出現。這套全新的 Python API 基於 Table API 之上。

Table API 和 Python API 之間的通訊採用了一種簡單的辦法,利用 Python VM 和 Java VM 進行通訊。在 Python API 的書寫或者呼叫過程中,以某種方式來與 Java API 進行通訊。操作 Python API 就像操作 Java 的 Table API一樣。新架構中可以確保以下內容:

  • 不需要另外建立一套新的運算元,可以輕鬆與 Java 的 Table API 的功能保持一致;
  • 得益於現有的 Java Table API 最佳化模型,Python 寫出來的API,可以利用 Java API 最佳化模型進行最佳化,可以確保 Python 的 API 寫出來的 Job 也能夠具備極致效能。

5.jpg

如圖,當 Python 發起對Java的物件請求時候,在 Java 段建立物件並儲存在一個儲存結構中,並分配一個 ID 給 Python 端,Python 端在拿到 Java 物件的 ID 後就可以對這個物件進行操作,也就是說 Python 端可以操作任何 Java 端的物件,這也就是為什麼新的架構可以保證Python Table API 和 Java Table API功能一致,並且能過服用現有的最佳化模型。

6.jpg

在新的架構和通訊模型下,Python API 呼叫 Java API 只需要在持有 Java 物件的 ID,將呼叫方法的名字和引數傳遞給 Java VM,就能完成對 Java Table API 的呼叫,所以在這樣的架構中開發 Python Table API 與開發 Java Table API 的方式完全一致,接下來我為大家詳細介紹如何開發一個簡單的 Python API 作業。

2.Python Table API – Job開發

7.jpg

通常來講一個 Python Table Job 一般會分成四個部分,首先要根據目前的現狀,要決定這個Job 是以批的方式執行,還是流的方式執行。當然後續版本使用者可以不考慮,但當前 1.9 版本還是需要考慮。

在決定第一步以怎樣的方式執行 Job 後,我們需要了解資料從哪裡來,如何定義 Source、結構資料型別等資訊。然後需要寫計算邏輯,然後就是對資料進行計算操作,但最終計算的結果需要持久化到某個系統。最後定義 Sink,與 Source 類似,我們需要定義 Sink Schema,以及每一個欄位型別。

下面將詳細分享如何用 Python API 寫每一步?首先,我們建立一個執行環境,對於執行環境本身來講,首先需要一個 ExecutionEnvironment,根本上我們需要一個 TableEnvironment。那麼在 TableEnvironment 中,有一個引數 Table Config,Table Config 中會有一些在執行過程中的配置引數,可以傳遞到 RunTime 層。除此之外,還提供了一些個性化的配置項,可以在實際業務開發中進行使用。

8.jpg

在拿到 Environment 後,需要對資料來源表進行定義,以 CSV 格式檔案為例,用"逗號"分隔,用 Field 來表明這個檔案中有哪些欄位。那麼會看到,目前裡面用逗號分隔,並且只有一個欄位叫 word,型別是 String。

9.jpg

在定義並描述完資料來源資料結構轉換成 Table 資料結構後,也就是說轉換到 Table API 層面之後是怎樣的資料結構和資料型別?下面將透過 with_schema 新增欄位及欄位型別。這裡只有一個欄位,資料型別也是 String,最終註冊成一個表,註冊到 catlog 中,就可以供後面的查詢計算使用了。

10.jpg

建立結果表,當計算完成後需要將這些結果儲存到持久化系統中,以 WordCount 為例,首先儲存表會有一個 word 以及它的計數兩個欄位,一個是 String 型別的 word,另一個是 Bigint 的計數,然後把它註冊成 Sink。

11.jpg

編寫註冊完 Table Sink 後,再來看如何編寫邏輯。其實用 Python API 寫 WordCount 和 Table API 一樣非常簡單。因為相對於 DataSream 而言 Python API 寫一個 WordCount 只需要一行。比如 group by,先掃描Source表,然後 group by 一個 Word,再進行 Select word 並加上聚合統計Count ,最終將最資料結果插入到結果表裡面中。

3.Python Table API – 環境搭建

12.jpg

那麼WordCount 怎樣才能真正的執行起來?首先需要搭建開發環境,不同的機器上可能安裝的軟體版本不一樣,這裡列出來了一些版本的需求和要求,其中括號中是示例機器上的版本。

14.jpg

第二步,構建一個 Java 的二進位制釋出包,以從原始碼進行構建,那麼這一頁面就是從原始碼獲取我們的主幹程式碼,並且拉取 1.9 的分支。當然大家可以用 Mater,但是 Master 不夠穩定,還是建議大家在自己學習的過程中,最好是用 1.9 的分支去做。接下來進行實戰演練環節,首先驗證 PPT 的正確性。首先編譯程式碼,示例如下:

//下載原始碼git clone 拉取1.9分支cd flink; git fetch origin release-1.9git checkout -b release-1.9 origin/release-1.9//構建二進位制釋出包mvn clean install -DskipTests -Dfast

編譯完成後,需要在相應目錄下找到釋出包:

cd flink-dist/target/flink-1.9.0-bin/flink-1.9.0tar -zcvf flink-1.9.0.tar.gz flink-1.9.0

在構建完 Java 的 API 之後進行檢驗,我們要構建一個 Python 的釋出包。

15.jpg

因為大多數 Python 的使用者我們都知道我們需要 pip install 方式,將需要的依賴庫進行與本地的 Python 環境進行整合或者安裝。

那麼 Flink 也是一樣,PyFlink 也需要打包一個 Pypip 能夠識別的資源進行安裝,在實際的使用中,也可以按這種命令去複製,在自己的環境中嘗試。

cd flink-Python;Python setup.py sdist

這個過程只是將 Java 包囊括進來,再把自己 PyFlink 本身模組的一些 Java 的包和 Python 包打包成一起,它會在 dist 目錄下,有一個 apache-flink-1.9.dev0.tar.gz。

cd dist/

在 dist 目錄的 apache-flink-1.9.dev0.tar.gz 就是我們可以用於 pip install 的 PyFlink 包。在1.9版本,除了 Flink Table,還有 Flink Table Blink。Flink 同時會支援兩個 plan,如果大家可以嘗試,我們可以自由的切換是 Flink 原有的 Planner,還是 Blink 的 Planner,大家可以去嘗試。完成打包後,就可以嘗試把包安裝到我們的實際環境當中。

16.jpg

接下來是一個非常簡單的命令,首先檢查命令的正確性,在執行之前,我們用 pip 檢查一下 list,我們要看在已有的包裡有沒有,現在嘗試把剛才打包的包再安裝。在實際的使用過程中,如果升級版,也要有這個過程,要把新的包要進行安裝。

pip install dist/*.tar.gz
pip list|grep flink

17.jpg

安裝完成後,就可以用剛才寫的 WordCount 例子來驗證環境是否正確。驗證一下剛才的正確性,怎麼驗證?為了大家方便,可以直接克隆 enjoyment.code 倉庫。

git clone 

接下來體驗並嘗試。在這個目錄下,我們剛才開發的 WordCount 例子。直接用 Python 或檢驗環境是否 OK。這個時候 Flink Python API 會啟動一個 Mini 的 Cluster,會將剛才 WordCount Job 進行執行,提交到一個 Mini Cluster 進行執行。現在 Run 的過程中其實已經在叢集上進行執行了。其實在這個程式碼裡面是讀了一個 Source 檔案,把結果寫到 CSV 檔案,在當前目錄,是有一個 Sink CSV 的。具體的操作步驟可以檢視Flink中文社群影片Apache Flink Python API 現狀及規劃

18.jpg

IDE 的配置在正常的開發過程中,其實我們大部分還是在本地進行開發的,這裡推薦大家還是用 Pychram 來開發 Python 相關的邏輯或者 Job。

同時由於有很大量的截圖存在,也把這些內容整理到了部落格當中,大家可以掃描二維碼去關注和檢視那麼一些詳細的注意事項,部落格詳細地址: 。這裡有一個很關鍵的地方,大家要注意,就是可能你的環境中有多種 Python 的環境,這時候選擇的環境一定是剛才 pip install 環境。具體操作詳見Apache Flink Python API 現狀及規劃。

4.Python Table API – 作業提交

19.jpg

還有哪些方式來提交 Job 呢?這是一個 CLI 的方式,也就是說真正的提交到一個現有的叢集。首先啟動一個叢集。構建的目錄一般在 target 目錄下,如果要啟動一個叢集,直接啟動就可以。這裡要說一點的是,其中一個叢集外部有個 Web Port,它的埠的地址都是在 flink-conf.yaml 配置的。按照 PPT 中命令,可以去檢視日誌,看是否啟動成功,然後從外部的網站訪問。如果叢集正常啟動,接下來看如何提交 Job 。

20.jpg

Flink 透過 run 提交作業,示例程式碼如下:

./bin/flink run -py  ~/training/0806/enjoyment.code/myPyFlink/enjoyment/word_count_cli.py

用命令列方式去執行,除了用 PY 引數,還可以指定 Python 的 module,以及其他一些依賴的資原始檔、JAR等。

21.jpg

在 1.9 版本中還為大家提供一種更便利的方式,就是以 Python Shell 互動式的方式來寫 Python API 拿到結果。有兩種方式可執行,第一種方式是 Local,第二種方式 Remote,其實這兩種沒有本質的差異。首先來看 Local ,命令如下:

bin/pyflink-shell.sh local

啟動一個mini Cluster ,當輸出後,會出來一個 Python 的 Flink CLI 同時會有一些示例程式,供大家來體驗,按照上面的案例就能夠達到正確的輸出和提交,既可以寫 Streaming,也可以寫 Batch。詳細步驟大家參考影片操作即可。

到目前為止,大家應該已經對 Flink 1.9 上 Python API 架構有了大概瞭解,同時也瞭解到如何搭建 Python API 環境。並且以一個簡單的 WordCount 示例,體驗如何在 IDE 裡面去執行程式,如何以 Flink run 和互動式的方式去提交 Job。同時也體驗了現有一些互動上的一種方式來使用 Flink Python API。那麼介紹完了整個 Flink 的一些環境搭建和一個簡單的示例後。接下來詳細介紹一下在1.9裡面所有的核心運算元。

三.Flink Python API 核心運算元介紹及應用

1.Python Table API 運算元

22.jpg

上面分享建立一個 Job 的過程,第一要選擇執行的方式是Streaming還是Batch;第二個要定義使用的表,Source、Schema、資料型別;第三是開發邏輯,同時在寫 WordCount 時,使用 Count 的函式。最後,在 Python API 裡面內建了很多聚合函式,可以使用count,sum, max,min等等。

所以在目前 Flink 1.9 版本中,已經能夠滿足大多數常規需求。除了剛才講到的 count。Flink Table API 運算元 1.9 中也已經支援。關於 Flink Table API 運算元,不論是 Python Table API 還是 Java 的Table API,都有以下幾種型別的操作。第一單流上的操作,比如說做一些SELECT、Filter,同時還可以在流上做一些聚合,包括開窗函式的 windows 視窗聚合以及列的一些操作,比如最下面的 add_columns 和 drop_columns。

除了單流,還有雙流的操作,比如說雙流 JOIN、雙流 minus、union ,這些運算元在Python Table API 裡面都提供了很好的支援。Python Table API 在 Flink 1.9 中,從功能的角度看幾乎完全等同於Java Table API,下面以實際程式碼來看上述運算元是怎麼編寫的以及怎麼去開發Python運算元。
2.Python Table API 運算元-Watermark定義

23.jpg

細心的同學可能會注意到,我們尚未提到流的一個特質性 -> 時序。流的特性是來的順序是可能亂序,而這種亂序又是流上客觀存在的一種狀態。在 Flink 中一般採用 Watermark 機制來解決這種亂序的問題。

在 Python API 中如何定義 Watermark?假設有一個 JSON 資料,a 欄位 String,time 欄位 datetime。這個時候定義 Watermark 就要在增加 Schema 時增加 rowtime 列。rowtime 必須是 timestamps 型別。

Watermark 有多種定義方式,上圖中 watermarks_periodic_bounded 即會週期性的去發 Watermark,6萬單位是毫秒。如果資料是亂序的,能夠處理一分鐘之內的亂序,所以這個值調的越大,資料亂序接受程度越高,但是有一點資料的延遲也會越高。關於 Watermark 原理大家可以檢視我的blog:  。

3.Python Table API – Java UDF

24.jpg

最後,跟大家分享一下 Java UDF在 Flink 1.9 版本中的應用, 雖然在1.9中不支援 Python 的 UDF ,但 Flink 為大家提供了可以在 Python 中使用 Java UDF。在 Flink 1.9 中,對 Table 模組進行了最佳化和重構,目前開發 Java UDF 只需要引入 Flink common 依賴就可以進行 Python API 開發。

25.jpg

接下來以一個具體的示例給大家介紹利用 Java UDF 開發 Python API UDF,假設我們開發一個求字串長度的 UDF,在 Python 中需要用 Java 中的 register_java_function,function 的名字是包全路徑。然後在使用時,就可以用註冊的名字完成UDF的呼叫,詳細可以查閱我的Blog:  。

26.jpg

那怎樣來執行?可以用 Flink run 命令去執行,同時需要將UDF的JAR包攜帶上去。

Java UDF 只支援 Scalar Function?其實不然,在 Java UDF中既支援 Scalar Function,也支援 Table Function和Aggregate Function。如下所示:

27.jpg

4.Python Table API 常用連結

28.jpg

上面所講到的一些東西,有一些長鏈的文件和連結,也放在PPT上方便大家查閱,同時最下面我也有個人部落格。希望對大家有幫助。

四.總結

簡單的總結一下,本篇首先是介紹了Apache Flink Python API 歷史發展的過程,介紹了Apache Flink Python API架構變更的原因以及當前架構模型;任何對未來 Flink Python API 是的規劃與功能特性繼續詳細介紹。

️本文作者: 孫金城(金竹)
本文為雲棲社群原創內容,未經允許不得轉載。


來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/69947441/viewspace-2656738/,如需轉載,請註明出處,否則將追究法律責任。

相關文章