当前位置: 首页 > news >正文

一文弄明白KeyedProcessFunction函数

引言

KeyedProcessFunction是Flink用于处理KeyedStream的数据集合,它比ProcessFunction拥有更多特性,例如状态处理和定时器功能等。接下来就一起来了解下这个函数吧

正文

了解一个函数怎么用最权威的地方就是 官方文档 以及注解,KeyedProcessFunction的注解如下

/*** A keyed function that processes elements of a stream.** <p>For every element in the input stream {@link #processElement(Object, Context, Collector)} is* invoked. This can produce zero or more elements as output. Implementations can also query the* time and set timers through the provided {@link Context}. For firing timers {@link #onTimer(long,* OnTimerContext, Collector)} will be invoked. This can again produce zero or more elements as* output and register further timers.** <p><b>NOTE:</b> Access to keyed state and timers (which are also scoped to a key) is only* available if the {@code KeyedProcessFunction} is applied on a {@code KeyedStream}.** <p><b>NOTE:</b> A {@code KeyedProcessFunction} is always a {@link* org.apache.flink.api.common.functions.RichFunction}. Therefore, access to the {@link* org.apache.flink.api.common.functions.RuntimeContext} is always available and setup and teardown* methods can be implemented. See {@link* org.apache.flink.api.common.functions.RichFunction#open(org.apache.flink.configuration.Configuration)}* and {@link org.apache.flink.api.common.functions.RichFunction#close()}.*/

上面简单来说就是以下四点

  1. Flink中输入流中的每一条数据都会触发KeyedProcessFunction类的processElement方法调用
  2. 通过这个方法的Context参数可以设置定时器,在开启定时器后会程序会定时调用onTimer方法
  3. 由于KeyedProcessFunction实现了RichFunction接口,因此是可以通过RuntimeContext上下文对象管理状态state的开启和释放
  4. 需要注意的是,只有在KeyedStream里才能够访问state和定时器,通俗点来说就是这个函数要用在keyBy这个函数的后面

processElement方法解析

  1. Flink会调用processElement方法处理输入流中的每一条数据
  2. KeyedProcessFunction.Context参数可以用来读取以及更新内部状态state
  3. 这个KeyedProcessFunction跟其他function一样通过参数中的Collector对象以回写的方式返回数据

onTimer方法解析:在启用TimerService服务时会定时触发此方法,一般会在processElement方法中开启TimerService服务

以上就是这个函数的基本知识,接下来就通过实战来熟悉下它的使用

实战简介

本次实战的目标是学习KeyedProcessFunction,内容如下:

  1. 监听本机7777端口读取字符串
  2. 将每个字符串用空格分隔,转成Tuple2实例,f0是分隔后的单词,f1等于1
  3. 将Tuple2实例集合通过f0字段分区,得到KeyedStream
  4. KeyedSteam通过自定义KeyedProcessFunction处理
  5. 自定义KeyedProcessFunction的作用,是记录每个单词最新一次出现的时间,然后建一个十秒的定时器进行触发

使用代码例子

首先定义pojo类

public class CountWithTimestampNew {private String key;private long count;private long lastQuestTimestamp;public long getAndIncrementCount() {return ++count;}public String getKey() {return key;}public void setKey(String key) {this.key = key;}public long getCount() {return count;}public void setCount(long count) {this.count = count;}public long getLastQuestTimestamp() {return lastQuestTimestamp;}public void setLastQuestTimestamp(long lastQuestTimestamp) {this.lastQuestTimestamp = lastQuestTimestamp;}
}

接着实现KeyedProcessFunction类

public class CountWithTimeoutKeyProcessFunctionNew extends KeyedProcessFunction<Tuple, Tuple2<String, Integer>, Tuple2<String, Long>> {private ValueState<CountWithTimestampNew> state;@Overridepublic void open(Configuration parameters) throws Exception {state = getRuntimeContext().getState(new ValueStateDescriptor<CountWithTimestampNew>("sherlock-state", CountWithTimestampNew.class));}// 实现数据处理逻辑的地方@Overridepublic void processElement(Tuple2<String, Integer> value, Context ctx, Collector<Tuple2<String, Long>> out) throws Exception {Tuple currentKey = ctx.getCurrentKey();CountWithTimestampNew countWithTimestampNew = state.value();if (countWithTimestampNew == null) {countWithTimestampNew = new CountWithTimestampNew();countWithTimestampNew.setKey(value.f0);}countWithTimestampNew.getAndIncrementCount();//更新这个单词最后一次出现的时间countWithTimestampNew.setLastQuestTimestamp(ctx.timestamp());//单词之间不会互相覆盖吗?推测state对象是跟key绑定,针对每一个不同的key KeyedProcessFunction会创建其对应的state对象state.update(countWithTimestampNew);//给当前单词创建定时器,十秒后触发long timer = countWithTimestampNew.getLastQuestTimestamp()+10000;//尝试注释掉看看是否还会触发onTimer方法ctx.timerService().registerProcessingTimeTimer(timer);//打印所有信息,用于确保数据准确性System.out.println(String.format(" 触发processElement方法,当前的key是 %s, 这个单词累加次数是 %d, 上次请求的时间是:%s, timer的时间是: %s",currentKey.getField(0),countWithTimestampNew.getCount(),time(countWithTimestampNew.getLastQuestTimestamp()),time(timer)));}@Overridepublic void onTimer(long timestamp, OnTimerContext ctx, Collector<Tuple2<String, Long>> out) throws Exception {Tuple currentKey = ctx.getCurrentKey();CountWithTimestampNew countWithTimestampNew = state.value();//标记当前元素是否已经连续10s未出现boolean isTimeout = false;if (timestamp >= countWithTimestampNew.getLastQuestTimestamp()+10000 ) {//out.collect(new Tuple2<>(countWithTimestampNew.getKey(), countWithTimestampNew.getCount()));isTimeout = true;}//打印所有信息,用于确保数据准确性System.out.println(String.format(" 触发onTimer方法,当前的key是 %s, 这个单词累加次数是 %d, 上次请求的时间是:%s, timer的时间是: %s, 当前单词是否已超过10秒没有再请求: %s",currentKey.getField(0),countWithTimestampNew.getCount(),time(countWithTimestampNew.getLastQuestTimestamp()),time(timestamp),String.valueOf(isTimeout)));}public static String time(long timeStamp) {return new SimpleDateFormat("yyyy-MM-dd hh:mm:ss").format(new Date(timeStamp));}
}

最后是启动类

public class KeyedProcessFunctionDemo2 {public static void main(String[] args) throws Exception {final StreamExecutionEnvironment env = StreamExecutionEnvironment.getExecutionEnvironment();// 并行度1env.setParallelism(1);// 处理时间env.setStreamTimeCharacteristic(TimeCharacteristic.ProcessingTime);// 监听本地9999端口,读取字符串DataStream<String> socketDataStream = env.socketTextStream("localhost", 7777);// 所有输入的单词,如果超过10秒没有再次出现,都可以通过CountWithTimeoutFunction得到DataStream<Tuple2<String, Long>> timeOutWord = socketDataStream// 对收到的字符串用空格做分割,得到多个单词.flatMap(new SplitterFlatMapFunction())// 设置时间戳分配器,用当前时间作为时间戳.assignTimestampsAndWatermarks(new AssignerWithPeriodicWatermarks<Tuple2<String, Integer>>() {@Overridepublic long extractTimestamp(Tuple2<String, Integer> element, long previousElementTimestamp) {// 使用当前系统时间作为时间戳return System.currentTimeMillis();}@Overridepublic Watermark getCurrentWatermark() {// 本例不需要watermark,返回nullreturn null;}})// 将单词作为key分区.keyBy(0)// 按单词分区后的数据,交给自定义KeyedProcessFunction处理.process(new CountWithTimeoutKeyProcessFunctionNew());// 所有输入的单词,如果超过10秒没有再次出现,就在此打印出来timeOutWord.print();env.execute("ProcessFunction demo : KeyedProcessFunction");}
}

演示

在启动服务前,先通过linux指令监听端口 nc -lk 7777

  1. 启动Flink服务后,往7777端口里面发送数据
    在这里插入图片描述

  2. 通过IDEA的终端可以看到有日志输出,可以看到在发送消息的时候第一条日志立马打印出来并在10秒后输出第二条日志
    在这里插入图片描述

  3. 那么咱们尝试连续发送两条Hello呢,可以看到累加器会持续累加,并且会触发两次onTimer方法,也就是每一条消息都会触发一次。由于连续发送两条,因此可以看得到第三行日志的末尾是false,说明收到第一条后的10秒内又有相同的消息进来。第二条是ture说明在收到第二条消息后的10秒内没有消息进来
    在这里插入图片描述

  4. 再输入点其他的试试
    在这里插入图片描述

  5. 通过输出可以看到这些单词的计数器又从0开始,说明每一个Key都对应一个状态
    在这里插入图片描述

思考题

  1. open方法会在哪里进行调用,KeyedProcessFunction整个类的完整调用逻辑是怎么样的
  2. registerProcessingTimeTimer和registerEventTimeTimer的差异是什么

参考资料

  1. https://blog.csdn.net/boling_cavalry/article/details/106299167
  2. https://blog.csdn.net/lujisen/article/details/105510532
  3. https://blog.csdn.net/qq_31866793/article/details/102831731

相关文章:

一文弄明白KeyedProcessFunction函数

引言 KeyedProcessFunction是Flink用于处理KeyedStream的数据集合&#xff0c;它比ProcessFunction拥有更多特性&#xff0c;例如状态处理和定时器功能等。接下来就一起来了解下这个函数吧 正文 了解一个函数怎么用最权威的地方就是 官方文档 以及注解&#xff0c;KeyedProc…...

alibabacloud学习笔记06(小滴课堂)

讲Sentinel流量控制详细操作 基于并发线程进行限流配置实操 在浏览器打开快速刷新会报错 基于并发线程进行限流配置实操 讲解 微服务高可用利器Sentinel熔断降级规则 讲解服务调用常见的熔断状态和恢复 讲解服务调用熔断例子 我们写一个带异常的接口&#xff1a;...

Code Composer Studio (CCS) - Licensing Information

Code Composer Studio [CCS] - Licensing Information 1. Help -> Code Composer Studio Licensing Information2. Upgrade3. Specify a license fileReferences 1. Help -> Code Composer Studio Licensing Information 2. Upgrade ​​​ 3. Specify a license file …...

uniapp引入微信小程序直播组件

方法1.小程序跳转视频号直播 微信小程序跳转到视频号 1.1微信开放平台注册 https://open.weixin.qq.com/ 2.2 方法2.使用小程序提供的直播组件 参考 微信小程序跳转视频号直播 小程序直播官方文档 https://developers.weixin.qq.com/miniprogram/dev/component/live-play…...

五个简单的C#编程案例

案例一&#xff1a;Hello, World! csharp using System; class Program { static void Main() { Console.WriteLine("Hello, World!"); } } 这个案例是最基础的C#程序&#xff0c;它打印出“Hello, World!”到控制台。每个C#程…...

Zlibrary低调官宣2024年最新网址,国内可直接访问,免费下载海量电子书籍

最近过节&#xff0c;文章也没怎么写&#xff0c;明天要上班了&#xff0c;今天写篇文章做个预热。 春节期间&#xff0c;“知识大航海”群里&#xff0c;有位群友分享了一个Zlibrary的最新地址&#xff0c;感谢这位群友妹妹的热心分享&#xff0c;这个地址国内可以直接访问。 …...

Android 开机启动

一、添加权限 <uses-permission android:name"android.permission.RECEIVE_BOOT_COMPLETED"/> 二、写一个广播接收器 public class BootReceiver extends BroadcastReceiver {Overridepublic void onReceive(Context context, Intent intent) {if(Intent.ACT…...

二叉树相关算法需了解汇总-基础算法操作

文章目录 144.二叉树的前序遍历145.二叉树的后序遍历94.二叉树的中序遍历102.二叉树的层序遍历107.二叉树的层次遍历倒序199.二叉树的右视图637.二叉树的层平均值429.N叉树的层序遍历515.在每个树行中找最大值116.填充每个节点的下一个右侧节点指针104.二叉树的最大深度111.二叉…...

万字干货-京东零售数据资产能力升级与实践

开篇 京东自营和商家自运营模式&#xff0c;以及伴随的多种运营视角、多种组合计算、多种销售属性等数据维度&#xff0c;相较于行业同等量级&#xff0c;数据处理的难度与复杂度都显著增加。如何从海量的数据模型与数据指标中提升检索数据的效率&#xff0c;降低数据存算的成…...

探索前端框架的世界:一场前端之旅

在网络世界中&#xff0c;网页开发领域的一颗明星是前端框架。这些框架为开发者提供了丰富的工具和技术&#xff0c;帮助他们构建出漂亮、高效的网页应用。现在&#xff0c;让我们随着小明的故事一起来探索一下吧。 小明的梦想 小明是一位年轻有为的前端开发者&#xff0c;他…...

class complex

class complex from C_OOP_base1_houjie complex.h #ifndef __COMPLEX__ // 防卫式声明 guard; 名称自定义 #define __COMPLEX__// 0. forward declarations class complex;complex& __doapl (complex* ths, const complex& r);// 1. class declarations class compl…...

数据库系统概论整理与总结

数据库系统概论 第一章&#xff1a;绪论 四个基本概念 四个概念 数据&#xff1a;Data 数据库&#xff1a;DataBase 数据库管理系统:DBMS 数据库系统:DBS 打个比喻&#xff0c;比如说菜鸟物流&#xff1a; Data&#xff1a;快递 DB&#xff1a;物流厂库 DBMS&#xff1a;对…...

打通新势力NAS权限壁垒,绿联私有云安装Portainer,实现更强大的Docker功能

打通新势力NAS权限壁垒&#xff0c;绿联私有云安装Portainer&#xff0c;实现更强大的Docker功能 对于国产新势力NAS来说&#xff0c;因为安全问题并没有完全开放SSH权限&#xff0c;所以还不能和传统NAS那样直接通过Docker run命令来部署容器&#xff0c;同时&#xff0c;对于…...

前端基础自学整理|DOM树

DOM&#xff0c;文档对象模型&#xff08;Document Object Model&#xff09;&#xff0c;简单的说&#xff0c;DOM是一种理念&#xff0c;一种思想&#xff0c;一个与系统平台和编程语言无关的接口&#xff0c;一种方法, 使 Web开发人员可以访问HTML元素&#xff01;不是具体方…...

RedisDesktopManager无法远程连接到Linux虚拟机中Redis的docker容器的一种解决方案

1.问题描述 除了RedisDesktopManager以外&#xff0c;使用java代码也无法连接到centos7虚拟机中的docker容器中的Redis &#xff0c;按照网上其他博主的解决方案&#xff0c;在排除Linux防火墙问题&#xff0c;端口映射问题&#xff0c;redis.conf配置文件问题以后&#xff0c…...

HarmonyOS 权限 介绍

权限说明 权限等级 根据权限对于不同等级应用有不同的开放范围&#xff0c;权限类型对应分为以下三种&#xff0c;等级依次提高。 normal权限 normal 权限允许应用访问超出默认规则外的普通系统资源。 这些系统资源的开放&#xff08;包括数据和功能&#xff09;对用户隐私以及…...

算法训练营day33(补),复习二叉树1

// 889. 根据前序和后序遍历构造二叉树 // 前序中左右 后序遍历左右中 func constructFromPrePost(preorder []int, postorder []int) *TreeNode { if len(preorder) 0 { return nil } root : &TreeNode{} root.Val preorder[0] //前序数组去掉root节点 preorder pre…...

k8s-权限管理

1. 身份认证 我们在目前的k8s集群环境里面&#xff0c;只能在master节点上执行kubectl的一些命令&#xff0c;在其他节点上执行就会报错 # 看一下是不是 [rootnode1 ~]# kubectl get nodes E0220 12:50:15.695133 6091 memcache.go:238] couldnt get current server API gro…...

四.QT5工具安装和环境变量的配置

1.以管理员身份运行安装包 2.登录qt账号&#xff0c;点击【next】 3.选中同意 4.选择安装目录&#xff0c;注意不能有中文和空格 5.勾选 64位 mingw。点击【next】&#xff0c;等待安装完成 6.配置环境变量...

为什么需要MDL锁

点击上方蓝字关注我 在数据库管理中&#xff0c;元数据&#xff08;metadata&#xff09;的保护至关重要&#xff0c;而MySQL中的"元数据锁"&#xff08;MDL锁&#xff09;就是它的守护者。 1. 什么是MDL锁MDL锁&#xff0c;全名Metadata Lock&#xff0c;是MySQL中…...

<6>-MySQL表的增删查改

目录 一&#xff0c;create&#xff08;创建表&#xff09; 二&#xff0c;retrieve&#xff08;查询表&#xff09; 1&#xff0c;select列 2&#xff0c;where条件 三&#xff0c;update&#xff08;更新表&#xff09; 四&#xff0c;delete&#xff08;删除表&#xf…...

rknn优化教程(二)

文章目录 1. 前述2. 三方库的封装2.1 xrepo中的库2.2 xrepo之外的库2.2.1 opencv2.2.2 rknnrt2.2.3 spdlog 3. rknn_engine库 1. 前述 OK&#xff0c;开始写第二篇的内容了。这篇博客主要能写一下&#xff1a; 如何给一些三方库按照xmake方式进行封装&#xff0c;供调用如何按…...

循环冗余码校验CRC码 算法步骤+详细实例计算

通信过程&#xff1a;&#xff08;白话解释&#xff09; 我们将原始待发送的消息称为 M M M&#xff0c;依据发送接收消息双方约定的生成多项式 G ( x ) G(x) G(x)&#xff08;意思就是 G &#xff08; x ) G&#xff08;x) G&#xff08;x) 是已知的&#xff09;&#xff0…...

学校招生小程序源码介绍

基于ThinkPHPFastAdminUniApp开发的学校招生小程序源码&#xff0c;专为学校招生场景量身打造&#xff0c;功能实用且操作便捷。 从技术架构来看&#xff0c;ThinkPHP提供稳定可靠的后台服务&#xff0c;FastAdmin加速开发流程&#xff0c;UniApp则保障小程序在多端有良好的兼…...

江苏艾立泰跨国资源接力:废料变黄金的绿色供应链革命

在华东塑料包装行业面临限塑令深度调整的背景下&#xff0c;江苏艾立泰以一场跨国资源接力的创新实践&#xff0c;重新定义了绿色供应链的边界。 跨国回收网络&#xff1a;废料变黄金的全球棋局 艾立泰在欧洲、东南亚建立再生塑料回收点&#xff0c;将海外废弃包装箱通过标准…...

ffmpeg(四):滤镜命令

FFmpeg 的滤镜命令是用于音视频处理中的强大工具&#xff0c;可以完成剪裁、缩放、加水印、调色、合成、旋转、模糊、叠加字幕等复杂的操作。其核心语法格式一般如下&#xff1a; ffmpeg -i input.mp4 -vf "滤镜参数" output.mp4或者带音频滤镜&#xff1a; ffmpeg…...

Python爬虫(一):爬虫伪装

一、网站防爬机制概述 在当今互联网环境中&#xff0c;具有一定规模或盈利性质的网站几乎都实施了各种防爬措施。这些措施主要分为两大类&#xff1a; 身份验证机制&#xff1a;直接将未经授权的爬虫阻挡在外反爬技术体系&#xff1a;通过各种技术手段增加爬虫获取数据的难度…...

从零实现STL哈希容器:unordered_map/unordered_set封装详解

本篇文章是对C学习的STL哈希容器自主实现部分的学习分享 希望也能为你带来些帮助~ 那咱们废话不多说&#xff0c;直接开始吧&#xff01; 一、源码结构分析 1. SGISTL30实现剖析 // hash_set核心结构 template <class Value, class HashFcn, ...> class hash_set {ty…...

Matlab | matlab常用命令总结

常用命令 一、 基础操作与环境二、 矩阵与数组操作(核心)三、 绘图与可视化四、 编程与控制流五、 符号计算 (Symbolic Math Toolbox)六、 文件与数据 I/O七、 常用函数类别重要提示这是一份 MATLAB 常用命令和功能的总结,涵盖了基础操作、矩阵运算、绘图、编程和文件处理等…...

多模态大语言模型arxiv论文略读(108)

CROME: Cross-Modal Adapters for Efficient Multimodal LLM ➡️ 论文标题&#xff1a;CROME: Cross-Modal Adapters for Efficient Multimodal LLM ➡️ 论文作者&#xff1a;Sayna Ebrahimi, Sercan O. Arik, Tejas Nama, Tomas Pfister ➡️ 研究机构: Google Cloud AI Re…...