Flink Streaming流式滑動窗口單詞計數_With IntelliJ IDEA

Flink Streaming流式滑動窗口單詞計數_With IntelliJ IDEA

1. 需求分析

任務描述

手工模擬流式數據產生,通過socket實時產生一些單詞,使用Flink實時接收數據,對指定時間窗口內(例如:2秒)的數據進行聚合統計,並且把時間窗口內計算的結果打印出來。

Flink程序開發步驟

  1. 獲得一個執行環境

  2. 加載/創建 初始化數據

  3. 指定操作數據的transaction算子

  4. 指定把計算好的數據放在哪

  5. 調用execute()觸發執行程序

    【注意】Flink程序是延遲計算的,只有最後調用execute()方法的時候纔會真正觸發執行程序。(跟Spark中算子的執行一樣,都可以稱爲懶(lazy)執行)。

    延遲計算的好處:在開發一個複雜程序時,Flink可以講複雜的程序轉化成一個執行計劃,將執行計劃作爲一個整體的單元執行!(提高計算效率)

執行環境

  • Ubuntu 18.04

  • Java 1.8

  • Flink 1.9.1

  • Maven 3.3.9

2. 啓動Flink

進入Flink的安裝目錄

cd /usr/local/flink
./bin/start-cluster.sh

jps查看啓動的java線程,可以看到TaskManagerRunner和StandaloneSessionClusterEntrypoint已啓動。

3. 在IntelliJ IDEA中開發調試SlidingWindowWordCount程序

3.1 新建Project

啓動進入IDEA,如下圖所示,新建一個項目。

執行如下圖所示的操作:(注意不要勾選"Create from archetype"前面的小方框)


如下圖所示,填寫GroupId和ArtifactId。這裏的GroupId是cn.stu.silver ,ArtifactId是streaming-wordcount。

這時生成的項目目錄結構如下圖所示。

3.2 修改pom.xml

該程序依賴Flink Java API,因此,我們需要通過Maven進行編譯打包。打開pom.xml,然後,將pom.xml內容修改如下,用來聲明該獨立應用程序的信息以及與Flink的依賴關係:

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <groupId>cn.stu.silver</groupId>
    <artifactId>streaming-wordcount</artifactId>
    <version>1.0-SNAPSHOT</version>

    <dependencies>
        <dependency>
            <groupId>org.apache.flink</groupId>
            <artifactId>flink-java</artifactId>
            <version>1.9.1</version>
        </dependency>
        <dependency>
            <groupId>org.apache.flink</groupId>
            <artifactId>flink-streaming-java_2.11</artifactId>
            <version>1.9.1</version>
        </dependency>
        <dependency>
            <groupId>org.apache.flink</groupId>
            <artifactId>flink-clients_2.11</artifactId>
            <version>1.9.1</version>
        </dependency>
        <dependency>
            <groupId>org.apache.flink</groupId>
            <artifactId>flink-scala_2.11</artifactId>
            <version>1.9.1</version>
        </dependency>
        <dependency>
            <groupId>org.apache.flink</groupId>
            <artifactId>flink-streaming-scala_2.11</artifactId>
            <version>1.9.1</version>
        </dependency>

    </dependencies>


</project>

3.3 創建package

如下圖所示,創建Package。

如下圖所示,輸入package的名稱爲“cn.stu.silver”。

如下圖所示,新建一個java class文件。

如下圖所示,輸入文件名稱SlidingWindowWordCount。

###3.4 SlidingWindowWordCount.java

package cn.stu.silver;

import org.apache.flink.api.common.functions.FlatMapFunction;
import org.apache.flink.api.java.utils.ParameterTool;
//import org.apache.flink.runtime.state.filesystem.FsStateBackend;
//import org.apache.flink.runtime.state.memory.MemoryStateBackend;
import org.apache.flink.streaming.api.datastream.DataStream;
import org.apache.flink.streaming.api.datastream.DataStreamSource;
import org.apache.flink.streaming.api.environment.StreamExecutionEnvironment;
import org.apache.flink.streaming.api.windowing.time.Time;
import org.apache.flink.util.Collector;

/**
 * 滑動窗口計算
 *
 * 通過socket模擬產生單詞數據
 * flink對數據進行統計計算
 *
 * 需要實現每隔1秒對最近2秒內的數據進行彙總計算
 *
 */
public class SlidingWindowWordCount {

    public static void main(String[] args) throws Exception{
        //獲取需要的端口號
        int port;
        try {
            ParameterTool parameterTool = ParameterTool.fromArgs(args);
            port = parameterTool.getInt("port");
        }catch (Exception e){
            System.err.println("No port set. use default port 9000--java");
            port = 9000;
        }

        //獲取flink的運行環境
        StreamExecutionEnvironment env = StreamExecutionEnvironment.getExecutionEnvironment();

        String hostname = "ubuntu";
        String delimiter = "\n";
        //連接socket獲取輸入的數據
        DataStreamSource<String> text = env.socketTextStream(hostname, port, delimiter);

        // a a c

        // a 1
        // a 1
        // c 1
        DataStream<WordWithCount> windowCounts = text.flatMap(new FlatMapFunction<String, WordWithCount>() {
            public void flatMap(String value, Collector<WordWithCount> out) throws Exception {
                String[] splits = value.split("\\s");
                for (String word : splits) {
                    out.collect(new WordWithCount(word, 1L));
                }
            }
        }).keyBy("word")
                .timeWindow(Time.seconds(2), Time.seconds(1))//指定時間窗口大小爲2秒,指定時間間隔爲1秒
                .sum("count");//在這裏使用sum或者reduce都可以
                /*.reduce(new ReduceFunction<WordWithCount>() {
                                    public WordWithCount reduce(WordWithCount a, WordWithCount b) throws Exception {

                                        return new WordWithCount(a.word,a.count+b.count);
                                    }
                                })*/
        //把數據打印到控制檯並且設置並行度
        windowCounts.print().setParallelism(1);

        //這一行代碼一定要實現,否則程序不執行
        env.execute("Socket window count");

    }

    public static class WordWithCount{
        public String word;
        public long count;
        public  WordWithCount(){}
        public WordWithCount(String word,long count){
            this.word = word;
            this.count = count;
        }
        @Override
        public String toString() {
            return "WordWithCount{" +
                    "word='" + word + '\'' +
                    ", count=" + count +
                    '}';
        }
    }
}

注意修改程序中hostname變量爲自己的hostname,如果不清楚的話可以在終端中輸入hostname查看自己的主機名。

3.5 執行前的處理

編寫完代碼以後會發現代碼中會出現大量標紅,說明相關的依賴沒有導入。

如下圖所示,在左側目錄樹的pom.xml文件上單擊鼠標右鍵,在彈出的菜單中選擇Maven,再在彈出的菜單中選擇Generate Sources and Update Folders,接着再在彈出的菜單中選擇Reimport。

如果是第一次下載相關依賴需要等待幾分鐘:

3.6 運行結果

打開SlidingWindowWordCount.java代碼文件,在這個代碼文件的代碼區域,鼠標右鍵單擊,彈出菜單中選中“Run SlidingWindowWordCount.main()”。

同時在終端中輸入

nc -l 9000

接着可以在終端中輸入一下字符,按下回車會發現IntelliJ IDEA控制檯會打印出窗口內出現的字符計數,結果如下:

完成!

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