因爲網絡上很多資料都過時了,有的是版本太老了,本文針對最新版本的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)))