Flink任务如何跑起来之 2.算子 StreamOperator
Flink任务如何跑起来之 2.算子 StreamOperator
前文介绍了Transformation创建过程,大多数情况下通过UDF完成DataStream转换中,生成的Transformation实例中,核心逻辑是封装了SimpleOperatorFactory实例。
UDF场景下,DataStream到Transformationg过程中,SimpleOperatorFactory实例的创建过程大致如下伪代码所示。
// 具体的函数实例
Function function = ;
// 将函数实例封装到算子实例中
AbstractUdfStreamOperator operator = new AbstractUdfStreamOperator(function);
// 通过算子实例得到其SimpleOperatorFactory实例
SimpleOperatorFactory factory = SimpleOperatorFactory.of(operator)
这里的UDF可以简单理解为需要我们自己传入对应Function实现类的操作,如map、filter等。
问题:
StreamOperator是什么?
为什么需要将Function封装到StreamOperator中?
1. Flink算子
在应用程序中通过各种各样的Function完成DataStream转换,但是Function仅表示数据处理逻辑,并不关心数据从哪里来到哪里去。
以MapFunction为例,map方法中仅包含对每一条到来数据的具体处理逻辑,并不清楚map方法何时被调用,结果返回到哪。
一个完整的数据处理逻辑应该是获取数据->处理数据->输出数据,在Flink中这个最小的完整逻辑通过算子表示,顶层抽象接口为StreamOperator。
因此Function作为算子的一部分参与后续的数据加工。
算子包含生命周期、状态和容错管理、数据处理3个方面。设计时分为两条线:
- 生命周期、状态和容错管理,主要是
AbstractStreamOperator抽象类及其子类实现,以及未来的AbstractStreamOperatorV2抽象类。 - 数据处理,主要是
OneInputStreamOperator、TwoInputStreamOperator和MultipleInputStreamOperator接口,分别表示单流、双流和多流的数据处理。在接口中定义了数据的处理方法。
StreamOperator完整的顶层抽象如下。

- AbstractStreamOperator,所有流运算的基类。提供了生命周期和属性方法的默认实现。
包含UDF的算子需继承其AbstractUdfStreamOperator子类
对于其具体实现,还必须实现OneInputStreamOperator或TwoInputStreamOperator其中一个。
将来将会使用AbstractStreamOperatorV2替换该基类 - OneInputStreamOperator,支持单流输入的运算符接口,如果要实现自定义运算符,需要使用AbatractUdfStreamOperator作为基类
- TwoInputStreamOperator,支持双流输入的运算符基类。同样需要和AbstractStreamOperator一起使用。
- AbstractStreamOperatorV2,所有流运算符的新基类,旨在取代AbatractUdfStreamOperator。
当前仅仅用于和MultipleInputStreamOperator一起配合使用。
OneInputStreamOperator、TwoInputStreamOperator和MultipleInputStreamOperator分别对应了Tranformation实现类的OneInputTransformation、TwoInputTransformation和AbstractMultipleInputTransformation。
MultipleInputStreamOperator和AbstractStreamOperatorV2是高版本中才加入的。因此,flink中最初仅支持单流或双流的输入,多流场景下需要拆分成单流或双流进行处理。在支持不同输入的流的实现中,梳理数据的方法分别如下
// 单流输入
public interface OneInputStreamOperator<IN, OUT> extends StreamOperator<OUT>, Input<IN> {// 处理数据void processElement(StreamRecord<IN> element) throws Exception;
}// 双流输入
public interface TwoInputStreamOperator<IN1, IN2, OUT> extends StreamOperator<OUT> {// 处理双流输入中第一个流上的元素void processElement1(StreamRecord<IN1> element) throws Exception;// 处理双流输入中第二个流上的元素void processElement2(StreamRecord<IN2> element) throws Exception;
}// 多流输入,这里的Input和单流输入继承的Input父类为同一个
public interface MultipleInputStreamOperator<OUT> extends StreamOperator<OUT> {List<Input> getInputs();
}
在AbstractStreamOperator众多子类中,AbstractUdfStreamOperator抽象类中封装了Function接口,并且其中open、close等算子生命周期等方法,实际上就是调用Function实例的对应方法。
public abstract class AbstractUdfStreamOperator<OUT, F extends Function>extends AbstractStreamOperator<OUT> implements OutputTypeConfigurable<OUT> {// 封装Functionprotected final F userFunction;// 通过Function实现进行算子的实例化public AbstractUdfStreamOperator(F userFunction) {this.userFunction = requireNonNull(userFunction);checkUdfCheckpointingPreconditions();}// 算子生命周期的相关方法,实际上调用Function的方法@Overridepublic void open() throws Exception {super.open();FunctionUtils.openFunction(userFunction, new Configuration());}@Overridepublic void finish() throws Exception {super.finish();if (userFunction instanceof SinkFunction) {((SinkFunction<?>) userFunction).finish();}}@Overridepublic void close() throws Exception {super.close();FunctionUtils.closeFunction(userFunction);}
}
常用的实现类基本继承自AbstractUdfStreamOperator抽象类。
单流输入,如map、fliter、source、sink等实现类

sink算子有两个实现类,分别是SinkOperator和StreamSink<IN>。二者的关系为SinkOperator是StreamSink<RowData>的特例。
双流输入,如concat、intervalJoin等实现类

本文开头提到通过SimpleOperatorFactory.of方式生成SimpleOperatorFactory实例,该方法如下
public static <OUT> SimpleOperatorFactory<OUT> of(StreamOperator<OUT> operator) {if (operator == null) {return null;} else if (operator instanceof StreamSource&& ((StreamSource) operator).getUserFunction() instanceof InputFormatSourceFunction) {// 通过addSoure方法添加的Source方式,且SourceFunction为InputFormatSourceFunction的子类return new SimpleInputFormatOperatorFactory<OUT>((StreamSource) operator);} else if (operator instanceof StreamSink&& ((StreamSink) operator).getUserFunction() instanceof OutputFormatSinkFunction) {// 通过addSink方法添加的sink方式,且SinkFunction为OutputFormatSinkFunction的子类return new SimpleOutputFormatOperatorFactory<>((StreamSink) operator);} else if (operator instanceof AbstractUdfStreamOperator) {return new SimpleUdfStreamOperatorFactory<OUT>((AbstractUdfStreamOperator) operator);} else {return new SimpleOperatorFactory<>(operator);}
}
得到SimpleOperatorFactory实例后,在实际执行时,通过其createStreamOperator方法得到StreamOperator实例。
1.1. 算子生成示例
上述内容偏概念更多一些,通过map为例实际观察Function->StreamOperator->StreamOperatorFactory->Transformation的过程
// 步骤1,业务代码中使用map操作
DataStream<Tuple2<String, Integer>> counts = text.map(row -> Tuple2.of(row, 1))// 步骤2,将业务代码中提供的MapFunction封装成StreamMap
public <R> SingleOutputStreamOperator<R> map(MapFunction<T, R> mapper, TypeInformation<R> outputType) {// 将MapFunction封装成StreamMap,StreamMap为AbstractUdfStreamOperator子类return transform("Map", outputType, new StreamMap<>(clean(mapper)));
}// 步骤3,根据StreamMap获取其对应的SimpleOperatorFactory工厂实例
public <R> SingleOutputStreamOperator<R> transform(String operatorName,TypeInformation<R> outTypeInfo,OneInputStreamOperator<T, R> operator) {// 获取StreamMap对应的StreamOperatorFactory工厂类return doTransform(operatorName, outTypeInfo, SimpleOperatorFactory.of(operator));
}// 步骤4,将工厂实例传入到Transformation中
protected <R> SingleOutputStreamOperator<R> doTransform(String operatorName,TypeInformation<R> outTypeInfo,StreamOperatorFactory<R> operatorFactory) {OneInputTransformation<T, R> resultTransform =new OneInputTransformation<>(this.transformation,operatorName,// 将StreamOperatorFactory工厂实例,传入到Transformation中operatorFactory,outTypeInfo,environment.getParallelism());@SuppressWarnings({"unchecked", "rawtypes"})SingleOutputStreamOperator<R> returnStream =new SingleOutputStreamOperator(environment, resultTransform);getExecutionEnvironment().addOperator(resultTransform);return returnStream;
}
在步骤2中,将MapFunction封装成StreamMap,StreamMap是AbstractUdfStreamOperator的子类,并且同时实现了OneInputStreamOperator,进行数据处理逻辑。在处理数据时,实际上是调用MapFunction的map方法完成,即在业务代码中指定的row -> Tuple2.of(row, 1)的逻辑。
public class StreamMap<IN, OUT> extends AbstractUdfStreamOperator<OUT, MapFunction<IN, OUT>>implements OneInputStreamOperator<IN, OUT> {// 以下3个属性从父类继承// 函数实例protected final F userFunction;// 结果输出protected transient Output<StreamRecord<OUT>> output;// 默认算子链生成策略protected ChainingStrategy chainingStrategy = ChainingStrategy.HEAD;public StreamMap(MapFunction<IN, OUT> mapper) {super(mapper);// 实例化StreamMap时,指定ALWAYS的算子链生成策略chainingStrategy = ChainingStrategy.ALWAYS;}@Overridepublic void processElement(StreamRecord<IN> element) throws Exception {// userFunction即MapFunction处理数据时,实质调用MapFunction的map方法。output.collect(element.replace(userFunction.map(element.getValue())));}
}
要在Task中算子才会真正执行,这里仅仅是在逻辑上完成算子的定义。
2. 算子链
Flink中会将多个算子合并到一起,组成算子链从而提高算子的运行效率。同一个算子链意味着将在同一个线程中运行。flink中算子链使用OperatorChain抽象类表示。
算子的合并策略在ChainingStrateg枚举类中定义,详情如下
/*** StreamOperator 使用的默认值为 HEAD,这意味着算子不链接到其前身。大多数算子使用 ALWAYS 覆盖此操作,这意味着它们将尽可能链接到前身。 */
public enum ChainingStrategy {// 尽可能的将和上游算子链接到一起,大多数算子的默认值ALWAYS,// 当前算子不会上下游算子链接到一起NEVER,// 不会上游算子连接到一起,但是可以和下游算子链接到一起HEAD,// 此运算符将运行在链的头部(与 HEAD 类似,但它还会尝试在可能的情况下链接source。这允许将多输入运算符与多个源链接到一个任务中。HEAD_WITH_SOURCES;public static final ChainingStrategy DEFAULT_CHAINING_STRATEGY = ALWAYS;
}
相关文章:
Flink任务如何跑起来之 2.算子 StreamOperator
Flink任务如何跑起来之 2.算子 StreamOperator 前文介绍了Transformation创建过程,大多数情况下通过UDF完成DataStream转换中,生成的Transformation实例中,核心逻辑是封装了SimpleOperatorFactory实例。 UDF场景下,DataStream到…...
学习笔记——路由网络基础——路由优先级(preference)
1、路由优先级(preference) 路由优先级(preference)代表路由的优先程度。当路由器从多种不同的途径获知到达同一个目的网段的路由(这些路由的目的网络地址及网络掩码均相同)时,路由器会比较这些路由的优先级,优选优先级值最小的路由。 路由来源的优先…...
数据预处理——调整方差、标准化、归一化(Matlab、python)
对数据的预处理: (a)、调整数据的方差; (b)、标准化:将数据标准化为具有零均值和单位方差;(均值方差归一化(Standardization)) (c)、最值归一化,也称为离差标准化,是对原始数据的…...
opencv_特征检测和描述
理解特征 寻找独特的特定模式或特定特征,可以轻松跟踪和比较。 拼图:在图像中搜索这些特征,找到它们,在其他图像中查找相同的特征并对齐它们。而已。 基本上,角被认为是图像中的好特征。 在本单元中,我…...
CID引流电商下的3C产品选品策略深度解析
摘要:随着电商行业的迅猛发展和消费者需求的日益多样化,CID引流电商作为一种新兴的电商模式,逐渐受到了广泛关注。在这一模式下,3C产品作为高客单价、高技术含量的代表品类,其选品策略的制定显得尤为重要。本文将从多…...
DeepSORT(目标跟踪算法)中的状态向量与状态转移矩阵
DeepSORT(目标跟踪算法)中的状态向量与状态转移矩阵 flyfish 状态转移矩阵(State Transition Matrix)F的构造 这篇是一定要看的,拖到文章的最后部分,需要理解状态转移矩阵怎么来的,怎么是这个…...
李宏毅深度学习01——基本概念简介
视频链接 基本概念 Regression(回归): 类似于填空 Classification(分类): 类似于选择 Structure Learning(机器学习): ?? 机器学习找对应函数…...
TcpClient 服务器、客户端连接
TcpClient 服务器 TcpListener 搭建tcp服务器的类,基于socket套接字通信的 1 创建服务器对象 TcpListener server new TcpListener(IPAddress.Parse("127.0.0.1"), 3000); 2 开启服务器 设置最大连接数 server.Start(1000); 3 接收客户端的链接,只能…...
13大最佳工程项目管理系统软件盘点
国内外主流的13款工程项目管理系统软件:Worktile、中建软件、泛微建筑项目管理软件、LiquidPlanner、Wrike、建文软件、广联达、Microsoft Project、泛普软件、Procore、Buildertrend、Fieldwire、Autodesk Construction Cloud。 在快速变化的工程领域,有…...
SpringMVC:拦截器(Interceptor)
1. 简介 拦截器(Interceptor)类似于过滤器(Filter) Spring MVC的拦截器作用是在请求到达控制器之前或之后进行拦截,可以对请求和响应进行一些特定的处理。拦截器可以用于很多场景下: 1. 登录验证…...
【Python】selenium使用find_element时解决【NoSuchWindowException】问题的方法
NoSuchWindowException 是 Selenium WebDriver 中的一种异常,当尝试切换到一个不存在的窗口时,或者在尝试获取窗口句柄时窗口已经关闭或不存在,就会抛出这个异常。 以下是一些解决 NoSuchWindowException 的常见方法: 检查窗口是…...
PTA:7-188 水仙花数
作者 王秀秀 单位 山东交通学院 任务描述 本关任务:输出100到999之间的所有的“水仙花数”。所谓的“水仙花数”是指一个3位数,其各位数字立方和等于该数本身。 例如,153是一个水仙花数,因为 15313 53 33 提示 关键在于对一…...
HTML静态网页成品作业(HTML+CSS+JS)—— 美食企业曹氏鸭脖介绍网页(4个页面)
🎉不定期分享源码,关注不丢失哦 文章目录 一、作品介绍二、作品演示三、代码目录四、网站代码HTML部分代码 五、源码获取 一、作品介绍 🏷️本套采用HTMLCSS,使用Javacsript代码实现 图片轮播切换,共有4个页面。 二、…...
SCI二区|鲸鱼优化算法(WOA)原理及实现【附完整Matlab代码】
目录 1.背景2.算法原理2.1算法思想 3.结果展示4.参考文献5.代码获取 1.背景 2016年,S Mirjalili受到自然界座头鲸社会行为启发,提出了鲸鱼优化算法(Whale Optimization Algorithm, WOA)。 2.算法原理 WOA模拟了座头鲸的社会行为…...
人脸匹配——OpenCV
人脸匹配 导入所需的库加载dlib的人脸识别模型和面部检测器读取图片并转换为灰度图比较两张人脸选择图片并显示结果比较图片创建GUI界面运行GUI主循环运行显示全部代码 导入所需的库 cv2:OpenCV库,用于图像处理。 dlib:一个机器学习库&#x…...
韩顺平0基础学java——第22天
p441-459 异常exception 选中代码块,快捷键ctraltt6,即trt-catch 如果进行了异常处理,那么即使出现了异常,但是会继续执行 程序过程中发生的异常事件分为两大类: 异常体系图※ 常见的运行异常:类型转换…...
神经网络介绍及教程案例
神经网络介绍及教程&案例 神经网络(Neural Networks)是机器学习和人工智能中的一种关键技术,模仿了人类大脑的工作方式,能够处理复杂的数据和任务。以下是神经网络的一些基础介绍: 基本概念 神经元(N…...
16个不为人知的资源网站,强烈建议收藏!
整理了16个不为人知的资源网站,涵盖了课程学习、办公技能、娱乐休闲、小说音乐等多种资源,强烈建议收藏! #学习网站 1、中国大学MOOC icourse163.org/ 这是一个汇集了国内顶尖大学免费课程资源的平台,众多985工程院校如北京大…...
pandas获取某列最大值的所有数据
第一种方法: 按照某列进行由大到小的排序,然后再进去去重,保留第一个值,最终保留的结果就是最大值的数据 # 由大到小排序 data_frame data_frame.sort_values(bycolumn_a, ascendingFalse)# 按照column_b列去重保留第一条&#…...
App UI 风格展现非凡创意
App UI 风格展现非凡创意...
wordpress后台更新后 前端没变化的解决方法
使用siteground主机的wordpress网站,会出现更新了网站内容和修改了php模板文件、js文件、css文件、图片文件后,网站没有变化的情况。 不熟悉siteground主机的新手,遇到这个问题,就很抓狂,明明是哪都没操作错误&#x…...
mongodb源码分析session执行handleRequest命令find过程
mongo/transport/service_state_machine.cpp已经分析startSession创建ASIOSession过程,并且验证connection是否超过限制ASIOSession和connection是循环接受客户端命令,把数据流转换成Message,状态转变流程是:State::Created 》 St…...
java 实现excel文件转pdf | 无水印 | 无限制
文章目录 目录 文章目录 前言 1.项目远程仓库配置 2.pom文件引入相关依赖 3.代码破解 二、Excel转PDF 1.代码实现 2.Aspose.License.xml 授权文件 总结 前言 java处理excel转pdf一直没找到什么好用的免费jar包工具,自己手写的难度,恐怕高级程序员花费一年的事件,也…...
React Native在HarmonyOS 5.0阅读类应用开发中的实践
一、技术选型背景 随着HarmonyOS 5.0对Web兼容层的增强,React Native作为跨平台框架可通过重新编译ArkTS组件实现85%以上的代码复用率。阅读类应用具有UI复杂度低、数据流清晰的特点。 二、核心实现方案 1. 环境配置 (1)使用React Native…...
3-11单元格区域边界定位(End属性)学习笔记
返回一个Range 对象,只读。该对象代表包含源区域的区域上端下端左端右端的最后一个单元格。等同于按键 End 向上键(End(xlUp))、End向下键(End(xlDown))、End向左键(End(xlToLeft)End向右键(End(xlToRight)) 注意:它移动的位置必须是相连的有内容的单元格…...
蓝桥杯 冶炼金属
原题目链接 🔧 冶炼金属转换率推测题解 📜 原题描述 小蓝有一个神奇的炉子用于将普通金属 O O O 冶炼成为一种特殊金属 X X X。这个炉子有一个属性叫转换率 V V V,是一个正整数,表示每 V V V 个普通金属 O O O 可以冶炼出 …...
智能AI电话机器人系统的识别能力现状与发展水平
一、引言 随着人工智能技术的飞速发展,AI电话机器人系统已经从简单的自动应答工具演变为具备复杂交互能力的智能助手。这类系统结合了语音识别、自然语言处理、情感计算和机器学习等多项前沿技术,在客户服务、营销推广、信息查询等领域发挥着越来越重要…...
PAN/FPN
import torch import torch.nn as nn import torch.nn.functional as F import mathclass LowResQueryHighResKVAttention(nn.Module):"""方案 1: 低分辨率特征 (Query) 查询高分辨率特征 (Key, Value).输出分辨率与低分辨率输入相同。"""def __…...
FFmpeg:Windows系统小白安装及其使用
一、安装 1.访问官网 Download FFmpeg 2.点击版本目录 3.选择版本点击安装 注意这里选择的是【release buids】,注意左上角标题 例如我安装在目录 F:\FFmpeg 4.解压 5.添加环境变量 把你解压后的bin目录(即exe所在文件夹)加入系统变量…...
tomcat指定使用的jdk版本
说明 有时候需要对tomcat配置指定的jdk版本号,此时,我们可以通过以下方式进行配置 设置方式 找到tomcat的bin目录中的setclasspath.bat。如果是linux系统则是setclasspath.sh set JAVA_HOMEC:\Program Files\Java\jdk8 set JRE_HOMEC:\Program Files…...
