我们设计一个需求就是统计一个文件里面各个单词出现的次数。
一、批处理
1、maven项目搭建
<dependency>
<groupId>org.apache.flink</groupId>
<artifactId>flink-clients_2.10</artifactId>
<version>1.3.2</version>
</dependency>
<!--flink核心包-->
<dependency>
<groupId>org.apache.flink</groupId>
<artifactId>flink-java</artifactId>
<version>1.7.2</version>
</dependency>
<!--flink流处理包-->
<dependency>
<groupId>org.apache.flink</groupId>
<artifactId>flink-streaming-java_2.12</artifactId>
<version>1.7.2</version>
<scope>provided</scope>
</dependency>
2、Java代码编写
/**
* @description: 单词统计(批数据处理)
* @date: 2022-3-21 22:17
* @version: 1.0
*/
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.operators.DataSource;
import org.apache.flink.api.java.operators.FlatMapOperator;
import org.apache.flink.api.java.operators.UnsortedGrouping;
import org.apache.flink.api.java.tuple.Tuple2;
import org.apache.flink.util.Collector;
// 这里都是flink的包,注意了
/**
* 单词统计(批数据处理)
*/
public class WordCount {
public static void main(String[] args){
// 1、获取flink的运行环境
ExecutionEnvironment env = ExecutionEnvironment.getExecutionEnvironment();
// 2、用flink的运行环境,去获取待分析的数据
String input = "E:\\file\\input\\sourceFile.txt";
String output = "E:\\file\\output";
// 3、处理数据
// 3.1、将文本内容打散成一个个单词,存在DataSource中,其实就是个集合,这里是存的每一行数据,还没打散呢
DataSource<String> lines = env.readTextFile(input);
// 把每一行元素做一个施加作用,得到最后的一个结果,这里就是对上文的每一行都做一个拆分,打散为单词,SplitFun就是个实现类,下面我们实现了
FlatMapOperator<String, Tuple2<String, Integer>> wordAndOne = lines.flatMap(new SplitFun());
/**
* 3.2、把相同的单词聚合到一起,根据单词内容进行聚合,意思就是把相同单词做一个聚合
* 这里说明一下,在上一步,我们拆分了每一行的字符串,成为一个单词和计数1组成的二元组<hello,1>这样的,这一步我们将进行分组统计,言下之意
* 就是我们统计一下hello有几个,直接用groupBy做分组,传参是0,意思就是我们以这个二元组的下标为0的元素做分组,也就是前面的单词,不按计数分组
* 这个很好理解,因为你就是统计的单词的个数,自然就以单词分组。UnsortedGrouping就是没排序的分组集合。
**/
UnsortedGrouping<Tuple2<String, Integer>> grouped = wordAndOne.groupBy(0);
/**
* 3.3、把聚合到一起的数据进行累加处理,DataSet是批处理最主要的结构,这里累加的就是后面那个1了,所以下标传1,这里还是处理的上面那个二元组
* 虽然他分组了,但是还是一个个的二元组。这里用DataSet这个父类接收,他有批处理的功能,我们就用这个。他是个多态的设计。
**/
DataSet<Tuple2<String, Integer>> result = grouped.sum(1);
// 4、保存处理结果
result.writeAsText(output);
// 5、触发程序执行,随便传个执行语句,不传也行,不传就是走他的默认值
try {
env.execute("wordCount batch process");
} catch (Exception exception) {
exception.printStackTrace();
}
}
/**
* @Description //把输入进来的每一行元素根据空格切分,切分成一个一个的单词再把切分好的单词变成(单词,1)的组合
* @Date 23:27 2022-3-21
* @Param * @param null
* @return
**/
static class SplitFun implements FlatMapFunction<String,Tuple2<String,Integer>>{
// value参数就是每一行字符串,out最后你处理完的输出到这里
@Override
public void flatMap(String value, Collector<Tuple2<String, Integer>> out) throws Exception {
// 将文本内容打散成一个个单词,返回为一个字符串数组
String[] words = value.split(" ");// hello you按照空格拆分转化为(hello,1)(you,1)后面聚合的时候直接把各个1相加就行了,就能直接计算总数了
for (String word : words) {
// 这里就是把单词放到Tuple2这个结构,比如hello,放进去成为hello,1这个元祖,每个单词都计数一次1,最后聚合的时候把各自的1相加,就知道有几个了
Tuple2<String, Integer> wordAndOne = new Tuple2<>(word, 1);
out.collect(wordAndOne);
}
}
}
}
3、数据准备,运行程序,查看结果
数据准备一个文件读取:
执行程序,查看输出路径,看一下输出文件我们看到you出现了三次统计完成。
4、总结
总结我们看一个流程图:
二、流处理
批处理和流处理不同,批处理我们是准备了一个文件让他去读取,而流处理是不断的数据过来,让他处理。这里我们模拟一个socket程序,不断的发数据过来,然后flink程序这里做处理。
Socket模拟实时发送单词,使用Flink实时接收数据,对指定时间窗口内(如5s)的数据进行聚合统计,每隔1s汇总计算一次,并且把时间窗口内计算结果打印出来。
1、 代码实现
/**
* @description: Socket模拟实时发送单词,使用Flink实时接收数据,对指定时间窗口内(如5s)的数据进行聚合统计,
* 每隔1s汇总计算一次,并且把时间窗口内计算结果打印出来。
* teacher2 ip : 113.31.105.128
* @date: 2022-3-21 23:33
* @version: 1.0
*/
import org.apache.flink.api.common.functions.FlatMapFunction;
import org.apache.flink.api.java.tuple.Tuple2;
import org.apache.flink.streaming.api.datastream.DataStreamSource;
import org.apache.flink.streaming.api.datastream.SingleOutputStreamOperator;
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实时接收数据,对指定时间窗口内(如5s)的数据进行聚合统计,每隔1s汇总计算一次,并且把时间窗口内计算结果打印出来。
teacher2 ip : 113.31.105.128
*/
public class WordCount {
public static void main(String[] args) throws Exception {
// 监听的ip和端口号,以main参数形式传入,约定第一个参数为ip,第二个参数为端口
String ip = "127.0.0.1";
int port = 8888;
// 获取Flink流执行环境
StreamExecutionEnvironment streamExecutionEnvironment = StreamExecutionEnvironment.getExecutionEnvironment();
// 获取socket输入数据
DataStreamSource<String> textStream = streamExecutionEnvironment.socketTextStream(ip, port);
SingleOutputStreamOperator<Tuple2<String, Long>> tuple2SingleOutputStreamOperator = textStream.flatMap(new FlatMapFunction<String, Tuple2<String, Long>>() {
@Override
public void flatMap(String value, Collector<Tuple2<String, Long>> collector) throws Exception {
String[] splits = value.split(" ");
for (String word : splits) {
collector.collect(Tuple2.of(word, 1L));
}
}
});
// 根据key进行分组聚合,具体属性就是word
SingleOutputStreamOperator<Tuple2<String, Long>> word = tuple2SingleOutputStreamOperator.keyBy(0)
//.timeWindow(Time.seconds(2), Time.seconds(1))
.sum(1);
// 打印数据
System.out.println("********************分割符**********************");
word.print();
// 触发任务执行
streamExecutionEnvironment.execute("wordcount stream process");
}
}
2、启动程序
直接run
3、在netcat上面执行发送字符串命令
至于如何安装netcat自己百度即可。https://blog.csdn.net/junR_980218/article/details/125374526