創建第一個 Flink 項目(Java版)

一、運行環境介紹


Flink執行環境主要分爲本地環境集羣環境,本地環境主要爲了方便用戶編寫和調試代碼使用,而集羣環境則被用於正式環境中,可以藉助Hadoop Yarn、k8s 或 Mesos等不同的資源管理器部署自己的應用。
環境依賴:【1】JDK環境:Flink核心模塊均使用 Java開發,所以運行環境需要依賴 JDK,JDK版本需要保證在1.8以上。
【2】Maven編譯環境:Flink的源代碼目前僅支持通過 Maven進行編譯,所以如果需要對源代碼進行編譯,或通過 IDE開發Flink Application,則建議使用 Maven作爲項目工程編譯方式。需要注意的是,Flink程序需要 Maven的版本在3.0.4及以上,否則項目編譯可能會出問題,建議用戶根據要求進行環境的搭建。
【3】Hadoop環境:對於執行在Hadoop Yarn資源管理器的 Flink應用,則需要配置對應的 Hadoop環境參數。目前 Flink官方提供的版本支持hadoop2.4、2.6、2.7、2.8等主要版本,所以用戶可以在這些版本的Hadoop Yarn中直接運行自己的 Flink應用,而不需要考慮兼容性的問題。

二、Flink項目模板


Flink爲了對用戶使用 Flink進行應用開發進行簡化,提供了相應的項目模板來創建開發項目,用戶不需要自己引入相應的依賴庫,就能夠輕鬆搭建開發環境,前提是在JDK(1.8及以上)和Maven(3.0.4及以上)的環境已經安裝好且能正常執行。在 Flink項目模板中,Flink提供了分別基於Java和Scala實現的模板,下面就 Java項目模板進行介紹和應用。

【1】創建項目:通過 Maven archetype命令進行創建:在項目目錄下執行如下命令(第一行就行),注意:groupIdartifactIdversionpackage 等信息根據自己的需求進行修改,當然你也可以用我默認的。

F:\Project\flink_project>mvn archetype:generate     -DarchetypeGroupId=org.apache.flink     -DarchetypeArtifactId=flink-quickstart-java     -DarchetypeVersion=1.10.0     -DgroupId=my-flink-project     -DartifactId=my-flink-project     -Dversion=0.1     -Dpackage=myflink     -DinteractiveMode=false

執行結果如下表示成功
[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESS
[INFO] ------------------------------------------------------------------------
[INFO] Total time: 59.208 s
[INFO] Finished at: 2020-07-01T15:38:00+08:00
[INFO] Final Memory: 18M/312M
[INFO] ------------------------------------------------------------------------

【2】我們可以看到的項目結構如下圖所示,可以看到自己定義的 artifactId等信息。該項目已經是一個相對比較完善的 Maven項目,其中創建出來對應的Java實例代碼,分別是 BatchJob.javaStreaming.java兩個文件,分別對應 Flink批量接口DataSet的實例代碼和流式接口 DataStream的實例代碼。在創建好上述項目後,建議用戶將項目導入到 IDE進行後續開發。啓動IntelliJ IDEA,選擇File→Open,在文件選擇框中選擇創建好的項目(quickstart),點擊確定,IDEA將自動進行項目的導入;

【3】編譯項目:項目經過上述步驟創建後,可以使用 Maven Command命令 mvn clean package對項目進行編譯,編譯完成後在項目同級目錄會生成 target/-.jar,則該可執行 Jar包就可以通過 Flink命令或者 Web客戶端提交到集羣上執行。

注意: 通過 Maven創建Java應用,用戶可以在 Pom中指定 Main Class,這樣提交執行過程中就具有默認的入口Main Class,否則需要用戶在執行的 Flink App的Jar應用中指定Main Class。

【4】開發應用:在項目創建和檢測完成後,我們就可以選擇在模板項目中的代碼上編寫應用,也可以定義 Class調用DataSet API或DataStream API進行Flink應用的開發,然後通過編譯打包,上傳並提交到集羣上運行。

三、Flink開發環境配置(自動生成可忽略)


對於通過項目模板生成的項目,項目中的主要參數配置已被初始化,所以無須額外進行配置,如果用戶通過手工進行項目的創建,則需要創建Flink項目並進行相應的基礎配置,包括Maven Dependences、Scala的Version等配置信息。
【1】Flink基礎依賴庫:對於Java版本,需要在項目的 pom.xml文件中配置如下依賴庫,其中 flink-java和 flink-streaming-java分別是批量計算 DataSet API和流式計算 DataStream API的依賴庫,{flink.version}是官方的發佈的版本號,用戶可根據自身需要進行選擇:

<flink.version>1.6.1</flink.version>
<dependencies>
	<dependency>
		<groupId>org.apache.flink</groupId>
		<artifactId>flink-java</artifactId>
		<version>${flink.version}</version>
		<scope>compile</scope>
	</dependency>
	<dependency>
		<groupId>org.apache.flink</groupId>
		<artifactId>flink-streaming-java_${scala.binary.version}</artifactId>
		<version>${flink.version}</version>
		<scope>compile</scope>
	</dependency>
</dependencies>

另外在上述 Maven Dependences配置中,核心的依賴庫配置的Scope爲provided,主要目的是在編譯階段能夠將依賴的Flink基礎庫排除在項目之外,當用戶提交應用到 Flink集羣的時候,就避免因爲引入Flink基礎庫而導致 Jar包太大或類衝突等問題。而對於 Scope配置成 provided的項目可能出現本地 IDE中無法運行的問題,可以在 Maven中通過配置 Profile的方式,動態指定編譯部署包的 scope爲provided,本地運行過程中的 scope爲compile,從而解決本地和集羣環境編譯部署的問題。

scope 的作用範圍:
【1】compile:默認值,適用於所有階段(表明該 jar 包在編譯、運行以及測試中路徑均可見),並且會隨着項目一起發佈。
【2】test:只在測試時使用,用於編譯和運行測試代碼,不會隨項目發佈。
【3】runtime:無需參與項目的編譯,不過後期的測試和運行週期需要其參與,與 compile 相比,跳過了編譯。如 JDBC 驅動,適用運行和測試階段。
【4】provided:編譯和測試時有效,但是該依賴在運行時由服務器提供,並且打包時也不會被包含進去。如 servlet-api。
【5】system:類似 provided,需要顯式提供包含依賴的jar,不會從 maven 倉庫下載,而是從本地文件系統獲取,需要添加 systemPath 的屬性來定義路徑。

【2】 Flink Connector 和 Lib依賴庫:除了上述Flink項目中應用開發必須依賴的基礎庫之外,如果用戶需要添加其他依賴,例如Flink中內建的Connector,或者其他第三方依賴庫,需要在項目中添加相應的Maven Dependences,並將這些Dependence的Scope需要配置成 compile。如果項目中需要引入Hadoop相關依賴包,和基礎庫一樣,在打包編譯的時候將 Scope註明爲 provided,因爲 Flink集羣中已經將 Hadoop依賴包添加在集羣的環境中,用戶不需要再將相應的 Jar包打入應用中,否則容易造成 Jar包衝突。

注意:對於有些常用的依賴庫,爲了不必每次都要上傳依賴包到集羣上,用戶可以將依賴的包可以直接上傳到 Flink安裝部署路徑中的 lib目錄中,這樣在集羣啓動的時候就能夠將依賴庫加載到集羣的 ClassPath中,無須每次在提交任務的時候上傳依賴的 Jar包。

四、編寫 Flink 程序


src/main/java/myflink 下創建 SocketWindowWordCount.java 文件:具體步驟見註解

import org.apache.flink.api.common.functions.FlatMapFunction;
import org.apache.flink.api.java.tuple.Tuple2;
import org.apache.flink.streaming.api.datastream.DataStream;
import org.apache.flink.streaming.api.datastream.SingleOutputStreamOperator;
import org.apache.flink.streaming.api.environment.StreamExecutionEnvironment;
import org.apache.flink.streaming.api.windowing.time.Time;
import org.apache.flink.util.Collector;

/**
 * @description: 第一個 flink wordcount 項目
 * @author: zzx
 * @createDate: 2020/7/1
 * @version: 1.0
 */
public class SocketWindowWordCount {
    public static void main(String[] args) {
        //1、Flink 程序的第一步是創建一個 StreamExecutionEnvironment 流執行環境 。
        //   這是一個入口類,可以用來設置參數和創建數據源以及提交任務。所以讓我們把它添加到 main 函數中:
        StreamExecutionEnvironment env = StreamExecutionEnvironment.getExecutionEnvironment();
        //2、將創建一個從本地端口號 9000 的 socket ,通過連接 socket 獲取輸入數據,如果端口被佔,自行更換
        DataStream<String> text = env.socketTextStream("localhost", 9000, "\n");
        /**
         * 這創建了一個字符串類型的 DataStream。
         * DataStream 是 Flink 中做流處理的核心 API,上面定義了非常多常見的操作(如,過濾、轉換、聚合、窗口、關聯等)。
         * 在本示例中,我們感興趣的是每個單詞在特定時間窗口中出現的次數,比如說5秒窗口。
         * 爲此,我們首先要將字符串數據解析成單詞和次數(使用Tuple2<String, Integer>表示),
         * 第一個字段是單詞,第二個字段是次數,次數初始值都設置成了1。
         * 我們實現了一個flatmap,因爲一行數據中可能有多個單詞。
         *
         * 解析數據,按 word 分組,開窗,聚合
         */
        SingleOutputStreamOperator<Tuple2<String, Integer>> sum = text.flatMap(new FlatMapFunction<String, Tuple2<String, Integer>>() {

            @Override
            public void flatMap(String value, Collector<Tuple2<String, Integer>> out) throws Exception {
                // \\s 表示按照空格拆分
                for (String word : value.split("\\s")) {
                    out.collect(Tuple2.of(word, 1));
                }
            }
            //根據map中的key進行分組,0表示位置
        }).keyBy(0)
                .timeWindow(Time.seconds(5))
                //安裝 value 進行統計 1表示位置
                .sum(1);

        //將結果打印到控制檯,這是設置並行度爲1,表示單線程打印,一般我們都是打印到文件的,如果不是1就會打印到多個文件
        sum.print().setParallelism(1);

        try {
            env.execute("Scoket Window WordCount");
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

Linux運行程序:要運行示例程序,首先我們在終端啓動 netcat 獲得輸入流:nc -lk port 永久監聽 TCP端口。安裝鏈接

nc -lk 9000

Window運行程序:可以通過 ncat 運行,安裝鏈接

ncat -lk 9000

然後直接運行 SocketWindowWordCount的 main 方法。只需要在 netcat 控制檯輸入單詞,就能在 SocketWindowWordCount 的輸出控制檯看到每個單詞的詞頻統計。如果想看到大於1的計數,請在5秒內反覆鍵入相同的單詞。

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