《大数据跟我学系列文章001-轻松通关 Flink-01-Flink 入门程序 WordCount 和 SQL 实现》

大数据跟我学系列文章-轻松通关 Flink

——-01.Flink 入门程序 WordCount 和 SQL 实现

分别从DataSet(批处理)和 DataStream(流处理)两种方式如何进行单词计数开发;最后介绍 Flink Table 和 SQL 的使用



前言

本文为拉勾课程《 42讲轻松通关 Flink》笔记,本着“只有亲身实践过并整理成体系才属于自己真正掌握的知识” 的理念写出本篇文章,后续每天更新,持续关注,欢迎留言讨论~。


提示:以下是本篇文章正文内容,下面案例可供参考

一、Flink 开发环境

Flink 一个以 Java 及 Scala 作为开发语言的开源大数据项目,通常我们推荐使用 Java 1.8来作为开发语言,Maven 3 作为编译和包管理工具进行项目构建和编译。对于大多数开发者而言,JDK、Maven 和 Git 这三个开发工具是必不可少的。

二、开发步骤

1.工程创建

通过 IDE 创建工程,可以自己新建工程,添加 Maven 依赖,或者直接用 mvn 命令创建应用:

mvn   archetype:generate  \
-DarchetypeGroupId=org.apache.flink \
-DarchetypeArtifactId=flink-quickstart-java \
-DarchetypeVersion=1.10.0

指定 Maven 工程的三要素,即 GroupId、ArtifactId、Version 来创建一个新的工程,出现 Build Success 信息,我们可以在本地目录看到一个已经生成好的名为 quickstart 的工程。

curl https://flink.apache.org/q/quickstart.sh | bash -s 1.10.0

自动生成的项目 pom.xml 文件中对于 Flink 的依赖注释掉 scope:
在这里插入图片描述

2.DataSet WordCount

1)程序编写

WordCount 程序是大数据处理框架的入门程序,俗称“单词计数”。用来统计一段文字每个单词的出现次数,该程序主要分为两个部分:一部分是将文字拆分成单词;另一部分是单词进行分组计数并打印输出结果。:

package org.myorg.quickstart;
import org.apache.flink.api.common.functions.FlatMapFunction;
import org.apache.flink.api.java.DataSet;
import org.apache.flink.api.java.ExecutionEnvironment;
import org.apache.flink.api.java.tuple.Tuple2;
import org.apache.flink.util.Collector;

/**
 * @author Administrator
 */
public class BatchJob {
    
    
	public static void main(String[] args) throws Exception {
    
    

		//创建Flink运行的上下文环境
		final ExecutionEnvironment env = ExecutionEnvironment.getExecutionEnvironment();
		env.setParallelism(5);
		// get input data
		// 创建DataSet,这里是一行行文本
		DataSet<String> text = env.fromElements(
				"Flink Spark Storm",
				"Flink Flink Flink",
				"Spark Spark Spark",
				"Storm Storm Storm"
		);

		// 通过 Flink 内置的转换函数进行计算
		DataSet<Tuple2<String, Integer>> counts =
				text.flatMap(new LineSplitter())
						.groupBy(0)
						.sum(1).setParallelism(1);
		// 结果打印
		counts.printToErr();

	}


	public static final class LineSplitter implements FlatMapFunction<String, Tuple2<String, Integer>> {
    
    


		@Override
		public void flatMap(String value, Collector<Tuple2<String, Integer>> out) {
    
    
			// normalize and split the line
			String[] tokens = value.toLowerCase().split("\\W+");

			for (String token : tokens) {
    
    
				if (token.length() > 0) {
    
    
					out.collect(new Tuple2<String, Integer>(token, 1));
				}
			}
		}
	}
}

2)步骤解析

首先,我们需要创建 Flink 的上下文运行环境。

ExecutionEnvironment env = ExecutionEnvironment.getExecutionEnvironment();

然后,使用 fromElements 函数创建一个 DataSet 对象,该对象中包含了我们的输入,使用 FlatMap、GroupBy、SUM 函数进行转换。

最后,直接在控制台打印输出。

3)运行结果

我们可以直接右键运行一下 main 方法,在控制台会出现我们打印的计算结果:在这里插入图片描述

3.DataSet WordCount

1)程序编写

为了模仿一个流式计算环境,我们选择监听一个本地的 Socket 端口,并且使用 Flink 中的滚动窗口,每 5 秒打印一次计算结果。代码如下:

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

public class StreamingJob {
    
    
    public static void main(String[] args) throws Exception{
    
    
        // 创建Flink流式计算环境
        final StreamExecutionEnvironment env = StreamExecutionEnvironment.getExecutionEnvironment();
        //监听本地9000端口
        DataStream<String> text = env.socketTextStream("127.0.0.1"(此处为消息发送端的端IP),9000,"\n");
        //将接收的数据进行拆分,分组,窗口计算并且进行聚合
        DataStream<WordWithCount> windowCounts = text
                .flatMap(new FlatMapFunction<String, WordWithCount>() {
    
    
                    @Override
                    public void flatMap(String value, Collector<WordWithCount> out){
    
    
                        for (String word:value.split("\\s")) {
    
    
                            //\s代表正则表达式中的一个空白字符(可能是空格、制表符、其他空白)
                            out.collect(new WordWithCount(word, 1L));
                        }
                    }
                })
                .keyBy("word")
                .timeWindow(Time.seconds(5),Time.seconds(1))
                .reduce(new ReduceFunction<WordWithCount>() {
    
    
                    @Override
                    public WordWithCount reduce(WordWithCount a,WordWithCount b){
    
    
                        return new WordWithCount(a.word,a.count+b.count);
                    }
                });
        //打印结果
        windowCounts.print().setParallelism(1);
        env.execute("Socket Window WordCount");

    }
    // 词频统计
    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 word + ":" + count;
        }
    }
}

2)步骤解析

首先创建一个流式计算环境:

StreamExecutionEnvironment env = StreamExecutionEnvironment.getExecutionEnvironment();

然后进行监听本地(或者linux虚拟机的IP) 9000 端口,将接收的数据进行拆分、分组、窗口计算并且进行聚合输出。代码中使用了 Flink 的窗口函数,我们在后面的课程中将详细讲解。

我们在本地(或者作为消息发送方的linux虚拟机的IP)使用 netcat 命令启动一个端口:

nc -lk 9000

3)运行结果

linux虚拟机发送消息:![

StreamingJob实时消费消息
在这里插入图片描述

4. Flink Table & SQL WordCount

Flink SQL 是 Flink 实时计算为简化计算模型,降低用户使用实时计算门槛而设计的一套符合标准 SQL 语义的开发语言。
一个完整的 Flink SQL 编写的程序包括如下三部分。

  • Source Operator: 是对外部数据源的抽象, 目前 Apache Flink 内置了很多常用的数据源实现,比如
    MySQL、Kafka 等。
  • Transformation Operators:算子操作主要完成比如查询、聚合操作等,目前 Flink
    SQL 支持了 Union、Join、Projection、Difference、Intersection 及 window
    等大多数传统数据库支持的操作。
  • Sink Operator: 是对外结果表的抽象,目前 Apache Flink
    也内置了很多常用的结果表的抽象,比如 Kafka Sink 等。

1)程序编写

上面已经通过 DataSet/DataStream API 开发,那么实现同样的 WordCount 功能, Flink Table & SQL 核心只需要一行代码

//省略掉初始化环境等公共代码
SELECT word, COUNT(word) FROM table GROUP BY word;

	<dependencies>
		<dependency>
			<groupId>org.apache.flink</groupId>
			<artifactId>flink-java</artifactId>
			<version>${flink.version}</version>
		</dependency>
		<dependency>
			<groupId>org.apache.flink</groupId>
			<artifactId>flink-streaming-java_${scala.binary.version}</artifactId>
			<version>${flink.version}</version>
		</dependency>
		<dependency>
			<groupId>org.apache.flink</groupId>
			<artifactId>flink-table-api-java-bridge_2.11</artifactId>
			<version>1.10.0</version>
		</dependency>

		<dependency>
			<groupId>org.apache.flink</groupId>
			<artifactId>flink-table-planner-blink_2.11</artifactId>
			<version>1.10.0</version>
		</dependency>
		<dependency>
			<groupId>org.apache.flink</groupId>
			<artifactId>flink-table-api-scala-bridge_2.11</artifactId>
			<version>1.10.0</version>
		</dependency>

2)步骤解析

第一步,创建上下文环境:

ExecutionEnvironment fbEnv = ExecutionEnvironment.getExecutionEnvironment();
BatchTableEnvironment fbTableEnv = BatchTableEnvironment.create(fbEnv);

第二步,读取一行模拟数据作为输入:

import org.apache.flink.api.java.DataSet;
import org.apache.flink.api.java.ExecutionEnvironment;
import org.apache.flink.table.api.Table;
import org.apache.flink.table.api.java.BatchTableEnvironment;

import java.util.ArrayList;

public class WordCountSQL {
    
    
    public static void main(String[] args) throws Exception{
    
    
        //获取运行环境
        ExecutionEnvironment fbEnv = ExecutionEnvironment.getExecutionEnvironment();
        //创建一个tableEnvironment
        BatchTableEnvironment fbTableEnv = BatchTableEnvironment.create(fbEnv);

        String words = "hello flink hello Dog";
        String[] split = words.split("\\W+");
        ArrayList<WC> list = new ArrayList<>();

        for (String word:split
             ) {
    
    
            WC wc = new WC(word,1);
            list.add(wc);
        }
        DataSet<WC> input = fbEnv.fromCollection(list);

        //DataSet 转SQL,指定字段名称
        Table table = fbTableEnv.fromDataSet(input,"word,frequency");
        table.printSchema();

        //注册为一个表
        fbTableEnv.createTemporaryView("WordCount",table);
        Table table02 = fbTableEnv.sqlQuery("select word as word, sum(frequency) as frequency from WordCount GROUP BY word");

        //将表转为DataSet
        DataSet<WC> ds3 = fbTableEnv.toDataSet(table02,WC.class);
        ds3.printToErr();
    }

    public static class WC {
    
    
        public String word;
        public long frequency;
        public WC() {
    
    }
        public WC(String word,long frequency){
    
    
            this.word = word;
            this.frequency = frequency;
        }
        @Override
        public String toString(){
    
    return word + "," + frequency;}
    }

}

3)运行结果

我们直接运行该程序,在控制台可以看到输出结果:
在这里插入图片描述


总结

介绍了 Flink 的工程创建,如何搭建调试环境的脚手架,同时以 WordCount 单词计数这一最简单最经典的场景用 Flink 进行了实现。第一次体验了 Flink SQL 的强大之处,有一个直观的认识,为后续内容打好基础。加油奥利给!!!!!!。

猜你喜欢

转载自blog.csdn.net/weixin_45091011/article/details/113806332