Flink入门案例-WordCount
新建一个maven工程,在开发之前,要模拟Flink的开发环境,搭建本地的Flink的开发环境,引入依赖
<dependencies>
<dependency>
<groupId>org.apache.flink</groupId>
<artifactId>flink-java</artifactId>
<version>1.10.1</version>
</dependency>
<dependency>
<groupId>org.apache.flink</groupId>
<artifactId>flink-streaming-java_2.12</artifactId>
<version>1.10.1</version>
</dependency>
</dependencies>
Flink是基于数据流的处理方式,但是在处理数据的同时,也提供了批处理的处理方式,所以分别测试一下批处理和流处理的不同
一、批处理方式
1:创建执行环境
// 创建执行环境
ExecutionEnvironment env = ExecutionEnvironment.getExecutionEnvironment();
2:从文件中读取数据
// 从文件中读取数据
String inputPath = "resources/hello.txt";
DataSource<String> inputDataSet = env.readTextFile(inputPath);
3:对数据集进行处理,转换成(word,1)统计
// 对数据集进行处理,按照空格分词展开,转换成(word,1)这样的二元组进行统计
DataSet<Tuple2<String, Integer>> result = inputDataSet
.flatMap(new MyFlatMapper())
.groupBy(0) // 按照第一个位置的word进行分组
.sum(1); // 将第二个位置上的数据求和
result.print();
注意:这里需要在flatMap方法中传入一个自定义的类,用于数据的处理逻辑
4:自定义类,实现FlatMapFunction接口
// 自定义类,实现FlatMapFunction接口
// 定义泛型,FlatMapFunction<输入类型,输出类型>
public static class MyFlatMapper implements FlatMapFunction<String, Tuple2<String, Integer>> {
@Override
public void flatMap(String s, Collector<Tuple2<String, Integer>> collector) throws Exception {
// 按照空格分词
String[] words = s.split(" ");
// 遍历words,包成二元组输出
for (String word: words) {
collector.collect(new Tuple2<>(word, 1));
}
}
以上这些方法就是批处理的大致流程,整体代码如下:
public class WordCount {
public static void main(String[] args) throws Exception {
// 创建执行环境
ExecutionEnvironment env = ExecutionEnvironment.getExecutionEnvironment();
// 从文件中读取数据
String inputPath = "resources/hello.txt";
DataSource<String> inputDataSet = env.readTextFile(inputPath);
// 对数据集进行处理,按照空格分词展开,转换成(word,1)这样的二元组进行统计
DataSet<Tuple2<String, Integer>> result = inputDataSet.flatMap(new MyFlatMapper())
.groupBy(0) // 按照第一个位置的word进行分组
.sum(1); // 将第二个位置上的数据求和
result.print();
}
// 自定义类,实现FlatMapFunction接口
public static class MyFlatMapper implements FlatMapFunction<String, Tuple2<String, Integer>> {
@Override
public void flatMap(String s, Collector<Tuple2<String, Integer>> collector) throws Exception {
// 按照空格分词
String[] words = s.split(" ");
// 遍历words,包成二元组输出
for (String word: words) {
collector.collect(new Tuple2<>(word, 1));
}
}
}
}
二、流处理
1:创建执行环境
// 创建执行环境(流处理的执行环境)
StreamExecutionEnvironment env = StreamExecutionEnvironment
.getExecutionEnvironment();
// 可以设置线程数
env.setParallelism(8);
2:从文件读取数据的做法和批处理的一致,现在实现一下监听端口处理数据
在实际的开发环境中,监听的主机名和端口号都是动态获取的,并不是固定的一个写在代码里
①用parameter tool工具从程序启动参数中配置
// 用parameter tool 工具从程序启动参数中提取配置项
ParameterTool parameterTool = ParameterTool.fromArgs(args);
// host 和 port 是在数据配置项中配置的,可以更改名字
String host = parameterTool.get("host");
int port = parameterTool.getInt("port");
②从socket文本读取数据
// 从socket文本流读取数据
DataStreamSource<String> inputDataStream = env.socketTextStream(host, port);
3:基于数据流进行转换操作
// 基于数据流进行转换计算
SingleOutputStreamOperator<Tuple2<String, Integer>> result =
inputDataStream.flatMap(new WordCount.MyFlatMapper())
.keyBy(0)
.sum(1);
4:指定任务
// 指定任务
env.execute();
5:自定义类,实现FlatMapFunction接口
// 自定义类,实现FlatMapFunction接口
public static class MyFlatMapper implements FlatMapFunction<String, Tuple2<String, Integer>> {
@Override
public void flatMap(String s, Collector<Tuple2<String, Integer>> collector) throws Exception {
// 按照空格分词
String[] words = s.split(" ");
// 遍历words,包成二元组输出
for (String word: words) {
collector.collect(new Tuple2<>(word, 1));
}
}
以上这些方法就是流处理的大致流程,整体代码如下:
public class StreamWordCount {
// 流式处理
public static void main(String[] args) throws Exception {
// 创建执行环境(流处理的执行环境)
StreamExecutionEnvironment env = StreamExecutionEnvironment
.getExecutionEnvironment();
// 可以设置线程数
env.setParallelism(8);
// 用parameter tool 工具从程序启动参数中提取配置项
ParameterTool parameterTool = ParameterTool.fromArgs(args);
String host = parameterTool.get("host");
int port = parameterTool.getInt("port");
// 从socket文本流读取数据
DataStreamSource<String> inputDataStream = env.socketTextStream(host, port);
// 基于数据流进行转换计算
SingleOutputStreamOperator<Tuple2<String, Integer>> result = inputDataStream.flatMap(new WordCount.MyFlatMapper())
.keyBy(0)
.sum(1);
result.print();
// 指定任务
env.execute();
}
// 自定义类,实现FlatMapFunction接口
public static class MyFlatMapper implements FlatMapFunction<String, Tuple2<String, Integer>> {
@Override
public void flatMap(String s, Collector<Tuple2<String, Integer>> collector) throws Exception {
// 按照空格分词
String[] words = s.split(" ");
// 遍历words,包成二元组输出
for (String word: words) {
collector.collect(new Tuple2<>(word, 1));
}
}
}
}
三、批处理和流处理的区别
1:批处理就是在处理的时候根据批为单位进行处理,等到数据达到一批的数量之后,一批一批的处理,这时候数据处理就不能做到实时性。流处理就是将数据以流的形式进行传输处理,当数据流过来的时候就开始处理,具有很好的实时性
2:在代码实现上,创建执行环境时候的所调用的类也是不同的
批处理调用的类是ExecutionEnvironment类,而流处理调用的类是StreamExecutionEnvironment类,但是两者调用的方法都是getExecutionEnvironment方法获得执行环境
3:流处理的时候需要指定任务才可以启动程序执行,否则不会输出结果
4:在转换操作的时候也是一样,批处理返回的对象是DataSet类型,而流处理返回的对象是SingleOutputStreamOperator类型