5分鐘實現第一個Flink程序

因爲網絡上很多資料都過時了,有的是版本太老了,本文針對最新版本的1.13.2快速構建一個WordCount程序

項目介紹

本文創建一個可以從網絡上讀取輸入,然後每5秒鐘輸出每個單詞個數的項目

創建maven項目

mvn archetype:generate \
    -DarchetypeGroupId=org.apache.flink \
    -DarchetypeArtifactId=flink-quickstart-java \
    -DarchetypeVersion=1.13.2 \
    -DgroupId=mflink \
    -DartifactId=mflink \
    -Dversion=0.1 \
    -Dpackage=myflink \
    -DinteractiveMode=false

用IDE打開這個項目,裏面已經創建了兩個類StreamingJob和BatchJob,本文使用StreamingJob來完成一個實時統計單詞的任務

可以修改後面一些自定義的參數

編寫邏輯

  • 創建StreamExecutionEnvironment: 這是一個入口類,可以用來設置參數和創建數據源以及提交任務
// set up the streaming execution environment
final StreamExecutionEnvironment env = StreamExecutionEnvironment.getExecutionEnvironment();
  • 從socket讀取數據: 從本地端口號 9000 的 socket 中讀取數據的數據源
DataStream<String> text = env.socketTextStream("localhost", 9000, "\n");

這創建了一個字符串類型的 DataStream。DataStream 是 Flink 中做流處理的核心 API,上面定義了非常多常見的操作(如,過濾、轉換、聚合、窗口、關聯等)。

  • 拆分單詞: 將字符串數據解析成單詞和次數(使用Tuple2<String, Integer>表示)(類似於MapReduce中的Map)
DataStream<Tuple2<String, Integer>> wordCounts = text
        .flatMap(new FlatMapFunction<String, Tuple2<String, Integer>>() {
          @Override
          public void flatMap(String value, Collector<Tuple2<String, Integer>> out) {
            for (String word : value.split("\\s")) {
              out.collect(Tuple2.of(word, 1));
            }
          }
        });
  • 統計單詞個數(類似於MapReduct中的Reduce)
DataStream<Tuple2<String, Integer>> windowCounts = wordCounts
        .keyBy((KeySelector<Tuple2<String, Integer>, Object>) tuple -> tuple.f0)
        .window(TumblingProcessingTimeWindows.of(Time.seconds(5)))
        .sum(1);
  • 輸出到標準輸出
windowCounts.print().setParallelism(1);
  • 開始執行
// execute program
env.execute("Socket Window WordCount");

最後的 env.execute 調用是啓動實際Flink作業所必需的。所有算子操作(例如創建源、聚合、打印)只是構建了內部算子操作的圖形。只有在execute()被調用時纔會在提交到集羣上或本地計算機上執行。

完整代碼

public class StreamingJob {
    public static void main(String[] args) throws Exception {
        // set up the streaming execution environment
        final StreamExecutionEnvironment env = StreamExecutionEnvironment.getExecutionEnvironment();

        // 通過連接 socket 獲取輸入數據,這裏連接到本地9000端口,如果9000端口已被佔用,請換一個端口
        DataStream<String> text = env.socketTextStream("localhost", 9000, "\n");

        // 解析數據,按 word 分組,開窗,聚合
        DataStream<Tuple2<String, Integer>> wordCounts = text
                .flatMap(new FlatMapFunction<String, Tuple2<String, Integer>>() {
                    @Override
                    public void flatMap(String value, Collector<Tuple2<String, Integer>> out) {
                        for (String word : value.split("\\s")) {
                            out.collect(Tuple2.of(word, 1));
                        }
                    }
                });


        DataStream<Tuple2<String, Integer>> windowCounts = wordCounts
                .keyBy((KeySelector<Tuple2<String, Integer>, Object>) tuple -> tuple.f0)
                .window(TumblingProcessingTimeWindows.of(Time.seconds(5)))
                .sum(1);

        // 將結果打印到控制檯,注意這裏使用的是單線程打印,而非多線程
        windowCounts.print().setParallelism(1);

        // execute program
        env.execute("Socket Window WordCount");
    }
}

運行程序

使用netcat往端口輸入

nc -lk 9000

啓動StreamingJob統計

直接在IDE中啓動就可以了


常見錯誤

java.lang.ClassNotFoundException: org.apache.flink.api.common.functions.FlatMapFunction

解決方法: 把pom.xml文件中的<scope>provided</scope>註釋掉

Is the time characteristic set to 'ProcessingTime', or did you forget to call 'DataStream.assignTimestampsAndWatermarks(...)'?

解決方案: .window(TumblingProcessingTimeWindows.of(Time.seconds(5)))

參考

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