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

流程总结

相关推荐
Jackeyzhe21 分钟前
Flink学习笔记:状态类型和应用
flink
九河云1 小时前
华为云 ECS 弹性伸缩技术:应对业务峰值的算力动态调度策略
大数据·服务器·人工智能·物联网·华为云
AI营销资讯站2 小时前
AI营销内容生产:哪些平台支持全球多语言内容同步生产?
大数据·人工智能
桃花键神3 小时前
openFuyao在AI推理与大数据场景中的加速方案:技术特性与实践探索
大数据·人工智能
天远数科5 小时前
前端全栈进阶:使用 Node.js Crypto 模块处理 AES 加密与天远API数据聚合
大数据·api
天远API5 小时前
后端进阶:使用 Go 处理天远API的 KV 数组结构与并发风控
大数据·api
千匠网络5 小时前
S2B供应链平台:优化资源配置,推动产业升级
大数据·人工智能·产品运营·供应链·s2b
WX-bisheyuange5 小时前
基于Spring Boot的智慧校园管理系统设计与实现
java·大数据·数据库·毕业设计
AI营销快线6 小时前
AI如何每日自动生成大量高质量营销素材?
大数据·人工智能
KKKlucifer6 小时前
从 “人工标注” 到 “AI 驱动”:数据分类分级技术的效率革命
大数据·人工智能·分类