flink异步流(async stream)解析

异步流都在 org.apache.flink.streaming.api.operators.async 包下面

AsyncResult

AsyncResult是存放在queue的中间结果,可以是watermark(AsyncCollectionResult),也可以是用户record(AsyncCollectionResult)。

方法有四个,分别是判断watermark、判断result、获取watermark、获取result

StreamElementQueueEntry是一个抽象类,实现了大部分逻辑,剩下主要业务逻辑是getFuture和onComplete。

它有两个实现类WatermarkQueueEntry和StreamRecordQueueEntry

watermark不是异步的,所以WatermarkQueueEntry中的future是_CompletableFuture.completedFuture(watermark);表示已经完成的future。_

StreamRecordQueueEntry 用户record是异步的。只有调用complete的时候才会赋值result,表示完成。赋值result在用户自定义异步函数中进行的。

AsyncWaitOperator

将进入的element包装成StreamRecordQueueEntry

处理的时候,首先会根据超时时间timeout,来注册定时器,超时的话会调用户自定义的timeout方法,按时完成会取消对应定时器。

添加到buffer中,这个buffer是有界的,可以控制异步的数量。

调用用户的asyncInvoke方法

addAsyncBufferEntry在添加的时候使用tryPut方法,没有空间的话就会wait。

queue中消息处理是在Emitter类中。

Emitter是在open方法中初始化的,放在emitterThread线程中单独处理。

Emitter的run方法中,取出一个element,这个element是异步已经完成的结果。调用output方法,将结果发送到下游。

output中针对watermark和element分别处理,watermark比较简单。主要看element。

首先是获取result,并发送到下游,再从队列中移除这个result,最后队列腾出一个空间,唤醒可能阻塞的主线程,主线程可以继续放入队列。

可以看到缓存队列StreamElementQueue是异步的关键,正常情况下是来一条数据处理一条数据,它是同步的,现在使用StreamElementQueue将消息先缓存起来,从StreamElementQueue中出去的消息都是已经经过处理的,消息处理耗时整体缩短。

举例现在有10条消息,每条消息处理时间是1s,那么不使用异步,同步处理,处理总时间就是10s。使用异步流的话,就是10条消息会先进入StreamElementQueue中,在StreamElementQueue中同时已经处理,最快处理总时间达到1s。

StreamElementQueue

主要是三个方法,

tryPut添加element,没空间就是false,添加成功就是true

peekBlockingly、poll 两个方法都是获取第一个完成element,区别是是否移除。

它有两个实现类OrderedStreamElementQueue和UnorderedStreamElementQueue,对应有序和无序。

顺序是指的队列弹出element顺序是不是element放入的顺序,即在获取第一个完成的element是不是第一个放入的element。

OrderedStreamElementQueue

比较简单。

capacity是容量大小,queue是实际存放的队列。

tryPut,空间有剩余调用addEntry放入元素。addEntry将元素放入尾部,并注册onCompleteHandler,通知headIsCompleted。

peekBlockingly和poll类似。

在poll中,首先队列是空的或者队列头部没有完成,headIsCompleted阻塞。headIsCompleted在头部完成的时候会回调onCompleteHandler释放。队列poll移除头部。

UnorderedStreamElementQueue

无序,这个效率更高。但是这个无序并不是完全无序,是在watermark之间无序。

  • uncompletedQueue中存放是按照watermark划分成的几个批次的没有完成的element
  • completedQueue是已经完成的单个element
  • firstSet是存放时间最久批次的element
  • lastSet是当前进入的element需要存放的批次

基本思路是新的element进入后放到lastSet中,如果是watermark进入的话就新开一个批次。获取第一个完成的element的时候从firstSet中获取。

tryPut还是调用addEntry方法。如果是element,就直接加入lastSet中。是watermark就要新开批次,创建新的lastSet,将新的空的lastSet加入到uncompletedQueue。要是firstSet为空,表示没有未完成的element,将watermark加入firstSet中,firstSet不为空,有没完成的element,这个watermark插入uncompletedQueue中起隔断作用。最后注册回调函数onCompleteHandler,在element完成的时候触发。

onCompleteHandler是在element完成的时候触发。每个element的耗时都是随机的。这里首先要求firstSet中都完成,再处理下一批次。完成的element放入到completedQueue中。

peekBlockingly和poll比较简单,从completedQueue中直接获取即可。

AsyncFunction

最后就是api的使用了。org.apache.flink.streaming.api.functions.async.AsyncFunction

流程总结

相关推荐
武子康6 小时前
大数据-237 离线数仓 - Hive 广告业务实战:ODS→DWD 事件解析、广告明细与转化分析落地
大数据·后端·apache hive
大大大大晴天8 小时前
Flink生产问题排障-Kryo serializer scala extensions are not available
大数据·flink
武子康2 天前
大数据-236 离线数仓 - 会员指标验证、DataX 导出与广告业务 ODS/DWD/ADS 全流程
大数据·后端·apache hive
武子康3 天前
大数据-235 离线数仓 - 实战:Flume+HDFS+Hive 搭建 ODS/DWD/DWS/ADS 会员分析链路
大数据·后端·apache hive
DianSan_ERP4 天前
电商API接口全链路监控:构建坚不可摧的线上运维防线
大数据·运维·网络·人工智能·git·servlet
够快云库4 天前
能源行业非结构化数据治理实战:从数据沼泽到智能资产
大数据·人工智能·机器学习·企业文件安全
AI周红伟4 天前
周红伟:智能体全栈构建实操:OpenClaw部署+Agent Skills+Seedance+RAG从入门到实战
大数据·人工智能·大模型·智能体
B站计算机毕业设计超人4 天前
计算机毕业设计Django+Vue.js高考推荐系统 高考可视化 大数据毕业设计(源码+LW文档+PPT+详细讲解)
大数据·vue.js·hadoop·django·毕业设计·课程设计·推荐算法
计算机程序猿学长4 天前
大数据毕业设计-基于django的音乐网站数据分析管理系统的设计与实现(源码+LW+部署文档+全bao+远程调试+代码讲解等)
大数据·django·课程设计
B站计算机毕业设计超人4 天前
计算机毕业设计Django+Vue.js音乐推荐系统 音乐可视化 大数据毕业设计 (源码+文档+PPT+讲解)
大数据·vue.js·hadoop·python·spark·django·课程设计