尚硅谷-flink
一、介绍
1.简介
flink是一个开源的分布式流处理框架
优势:高性能处理、高度灵活window操作、有状态计算的Exactly-once等
详情简介,参考官网:https://flink.apache.org/flink-architecture.html
中文参考:https://flink.apache.org/zh/flink-architecture.html
flink组件介绍:
1)部署:支持本地、集群(支持yarn资源管理)、云
2)核心层:提供了计算的核心
3)API:提供了面向流处理的DataStream和面向批处理的DataSet
4)类库:支持Table/SQL
基本架构为 DataSource(数据源) -> Transfromation(算子处理数据) ->DataSink(数据目的)
分层API:
··
二、快速上手
wordcount:
1.新建maven项目:
2.导入依赖(提交到服务区的,可以对flink的依赖使用<provided>)
<properties> <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> <flink.version>1.17.0</flink.version> </properties> <dependencies> <dependency> <groupId>junit</groupId> <artifactId>junit</artifactId> <version>3.8.1</version> <scope>test</scope> </dependency> <dependency> <groupId>org.apache.flink</groupId> <artifactId>flink-streaming-java</artifactId> <version>${flink.version}</version> </dependency> <dependency> <groupId>org.apache.flink</groupId> <artifactId>flink-clients</artifactId> <version>${flink.version}</version> </dependency> </dependencies>
3.创建用于测试的txt文件
4.执行步骤
1、创建流处理环境:
2、从文件中读取数据:
3、进行WordCount操作:
4、打印结果到控制台:
5、执行任务:
代码如下:
package org.example; 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.util.Collector; /** * Hello world! */ public class App { public static void main(String[] args) throws Exception { // 创建flink执行环境 StreamExecutionEnvironment env = StreamExecutionEnvironment.getExecutionEnvironment(); // 从文件读取数据 DataStreamSource<String> source = env.readTextFile("input/word.txt"); // 处理数据,执行wordcount操作 SingleOutputStreamOperator<Tuple2<String, Integer>> summed = source.flatMap(new Tokenizer()) .keyBy(0) .sum(1); // 打印结果 summed.print(); // 启动执行 env.execute("WordCount"); } // 自定义FlatMapFunction,用于分词 public static class Tokenizer implements FlatMapFunction<String, Tuple2<String, Integer>> { @Override public void flatMap(String value, Collector<Tuple2<String, Integer>> out) { // 将输入的字符串按空格分割 String[] words = value.split("\\s+"); // 遍历每个单词,并生成 (word, 1) 的元组 for (String word : words) { out.collect(new Tuple2<>(word, 1)); } } } }
三、flink集群
集群角色:
四、运行时核心概念
并行度:特定算子的子任务的并行度,
并行度设置:
1.代码中设置:
SingleOutputStreamOperator<Tuple2<String, Integer>> summed = source.flatMap(new Tokenizer()) .setParallelism(2) .keyBy(0) .sum(1);
还可以通过env和提交时指定
算子 > env > 提交时设置
插槽、运行提交流程等。。。
五、DataStream API
是flink的核心API,flink的运行流程:
1、创建流处理环境:
2、读取数据:
3、转换操作:
4、输出结果:
5、执行任务:(程序是懒执行)
DS主要负责1和5
fromSource是新API
算子:
map-一进一出,改造完出来重新做人
// 获取运行环境(可以通过conf配置) StreamExecutionEnvironment env = StreamExecutionEnvironment.getExecutionEnvironment(); env.setParallelism(1); // 从集合中读取数据 DataStreamSource<WaterSenor> source = env.fromElements(new WaterSenor("sensor_1", 1547718199L, 35), new WaterSenor("sensor_2", 1547718191L, 31), new WaterSenor("sensor_3", 1547718192L, 32)); // 转换数据 SingleOutputStreamOperator<String> map = source.map(s -> s.getId()); map.print(); // 执行 env.execute();
记得执行的步骤!
当然,工作中一般建议定义一个类来实现,如果通过lambda表达式,很难通用,且改起来费劲。推荐的用法如下(用一个service包来进行算子转换)
实现MapFunction接口,两个泛型分别是输入输出类型:
package service; import bean.WaterSenor; import org.apache.flink.api.common.functions.MapFunction; public class MyMapFunction implements MapFunction<WaterSenor, String> { @Override public String map(WaterSenor value) throws Exception { return value.getId() + ":" + value.getVc(); } }
使用的话new一个就行:
// 获取运行环境(可以通过conf配置) StreamExecutionEnvironment env = StreamExecutionEnvironment.getExecutionEnvironment(); env.setParallelism(1); // 从集合中读取数据 DataStreamSource<WaterSenor> source = env.fromElements(new WaterSenor("sensor_1", 1547718199L, 35), new WaterSenor("sensor_2", 1547718191L, 31), new WaterSenor("sensor_3", 1547718192L, 32)); // 转换数据 SingleOutputStreamOperator<String> map = source.map(new MyMapFunction()); map.print(); // 执行 env.execute();
filter过滤,为true则保留,否则过滤掉
同理,实现一个接口,泛型是要过滤的数据的类型:
package service; import bean.WaterSenor; import org.apache.flink.api.common.functions.FilterFunction; public class MyFilterFunction implements FilterFunction<WaterSenor> { @Override public boolean filter(WaterSenor value) throws Exception { return "sensor_1".equalsIgnoreCase(value.getId()); } }
使用的时候使用.filter传入函数即可:
// 获取运行环境(可以通过conf配置) StreamExecutionEnvironment env = StreamExecutionEnvironment.getExecutionEnvironment(); env.setParallelism(1); // 从集合中读取数据 DataStreamSource<WaterSenor> source = env.fromElements(new WaterSenor("sensor_1", 1547718199L, 35), new WaterSenor("sensor_2", 1547718191L, 31), new WaterSenor("sensor_3", 1547718192L, 32)); // 转换数据 SingleOutputStreamOperator<WaterSenor> map = source.filter(new MyFilterFunction()); map.print(); // 执行 env.execute();
flatMap,扁平映射,一进多出,比如wordcount的时候,一行返回多个单词
也是实现一个类,泛型表示输入输出类型:
package service; import bean.WaterSenor; import org.apache.flink.api.common.functions.FlatMapFunction; import org.apache.flink.util.Collector; public class MyFlatMapFunction implements FlatMapFunction<WaterSenor, String> { @Override public void flatMap(WaterSenor value, Collector<String> out) throws Exception { if ("sensor_1".equalsIgnoreCase(value.getId())) { out.collect(value.getTs().toString()); } else if ("sensor_2".equalsIgnoreCase(value.getId())){ out.collect(value.getTs().toString()); out.collect(value.getVc().toString()); } } }
使用的时候,new一个类,这里flatmap可以0输出,所以这里的sensor_3不输出,不处理:
// 获取运行环境(可以通过conf配置) StreamExecutionEnvironment env = StreamExecutionEnvironment.getExecutionEnvironment(); env.setParallelism(1); // 从集合中读取数据 DataStreamSource<WaterSenor> source = env.fromElements(new WaterSenor("sensor_1", 1547718199L, 35), new WaterSenor("sensor_2", 1547718191L, 31), new WaterSenor("sensor_3", 1547718192L, 32)); // 转换数据 SingleOutputStreamOperator<String> map = source.flatMap(new MyFlatMapFunction()); map.print(); // 执行 env.execute();