本文比较简单,是大数据入门的基本程序——word count。程序虽然简单,但是麻雀虽小,五脏俱全,这里面包含了Flink程序最最基本的组件。
Flink 流处理Word Count
依赖
在flink1.11以后需要导入flink-clients_2.11,否则会报异常。
<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_2.11</artifactId>
<version>${flink.version}</version>
</dependency>
<dependency>
<groupId>org.apache.flink</groupId>
<artifactId>flink-clients_2.11</artifactId>
<version>1.11.1</version>
</dependency>
Java程序
/**
* 从socket中读取数据,进行word count计算
*/
public class SocketDemo {
public static void main(String[] args) throws Exception {
//1.创建执行环境
StreamExecutionEnvironment env = StreamExecutionEnvironment.getExecutionEnvironment();
//2.从socket流中读取数据源(程序的source部分)
DataStreamSource<String> socketTextStream = env.socketTextStream("localhost", 9999);
//3.执行业务逻辑(word count操作)
DataStream<Tuple2<String, Integer>> resStream = socketTextStream.flatMap(new FlatMapFunction<String, Tuple2<String, Integer>>() {
@Override
public void flatMap(String s, Collector<Tuple2<String, Integer>> collector) throws Exception {
Arrays.stream(s.split(" ")).forEach(word -> collector.collect(new Tuple2<>(word, 1)));
}
}).keyBy((KeySelector<Tuple2<String, Integer>, String>) value -> value.f0).sum(1);
//4.将结果输出到控制台(程序的sink部分)
resStream.print();
//5.启动程序(Flink的流处理任务需要手动触发一下)
env.execute("socket");
}
}
以上是flink Java 流处理的基本程序。可以看到程序共分为五部分:
1. 得到运行环境。写过Spark的都知道,Spark集群方式、本地方式有不同的获取Spark执行环境的API,但是Flink比较智能,在本地运行他可以自动判断是本地环境,集群自动判断是集群环境。
2. 得到数据源。Flink可以有多种数据源,有时间会写一篇专门总结flink不同数据源的文章。
3. 实际业务逻辑处理。比如上面的wc程序,首先将读入的一行字符串按单词分割、对每个单词首先标记为数量1、将数据按单词分组、最后sum计数。
4. 业务逻辑处理完成以后可以将数据sink到不同的系统中去。可以是上面这样的用于调试的直接输出到控制台,也可以将其sink到不同存储系统中,甚至可以将数据通过某种方式(比如通过http)交给其他程序。关于sink的种类和方式,后面有时间也会专门写一篇文章。
5. 流处理需要手动执行execute启动程序。
Flink批处理 Word Count
/**
* 批处理入门程序,简单的word count
*/
public class BatchDemo {
public static void main(String[] args) throws Exception {
//1.得到运行环境
ExecutionEnvironment env = ExecutionEnvironment.getExecutionEnvironment();
//2.读取文件数据源
DataSource<String> source = env.readTextFile("/Users/aspirin/Downloads/hello.txt");
//3.编写业务逻辑
AggregateOperator<Tuple2<String, Integer>> res = source.flatMap(new FlatMapFunction<String, Tuple2<String, Integer>>() {
@Override
public void flatMap(String s, Collector<Tuple2<String, Integer>> collector) throws Exception {
String[] s1 = s.split(" ");
Arrays.stream(s1).forEach(word -> collector.collect(new Tuple2<>(word, 1)));
}
})
.groupBy(0)
.sum(1);
//4.输出
res.print("batch word count");
}
}
流处理和批处理在api上看起来大同小异。这里暂且只讲三点:
1. 流处理环境类是StreamExecutionEnvironment,而批处理是ExecutionEnvironment。
2. 流处理分组中的keyBy算子,而批处理用的groupBy算子
3. 流处理需要五步操作,最后要手动执行execute。批处理只写前四步,最后一步程序会自动执行