Flink中异步AsyncIO的实现 (源码分析)
先上张图整体了解Flink中的异步io

阿里贡献给flink的,优点就不说了嘛,官网上都有,就是写库不会柱塞性能更好
然后来看一下, Flink 中异步io主要分为两种
一种是有序Ordered
一种是无序UNordered
主要区别是往下游output的顺序(注意这里顺序不是写库的顺序既然都异步了写库的顺序自然是无法保证的),有序的会按接收的顺序继续往下游output发送,无序就是谁先处理完谁就先往下游发送
两张图了解这两种模式的实现

有序:record数据会通过异步线程写库,Emitter是一个守护进程,会不停的拉取queue头部的数据,如果头部的数据异步写库完成,Emitter将头数据往下游发送,如果头元素还没有异步写库完成,柱塞 
无序:record数据会通过异步线程写库,这里有两个queue,一开始放在uncompleteedQueue,当哪个record异步写库成功后就直接放到completedQueue中,Emitter是一个守护进程,completedQueue只要有数据,会不停的拉取queue数据往下游发送
可以看到原理还是很简单的,两句话就总结完了,就是利用queue和java的异步线程,现在来看下源码
这里AsyncIO在Flink中被设计成operator中的一种,自然去OneInputStreamOperator的实现类中去找
于是来看一下AsyncWaitOperator.java

看到它的open方法(open方法会在taskmanager启动job的时候全部统一调用,可以翻一下以前的文章)
这里启动了一个守护线程Emitter,来看下线程具体做了什么

1处拉取数据,2处就是常规的将拉取到的数据往下游emit,Emitter拉取数据,这里先不讲因为分为有序的和无序的
这里已经知道了这个Emitter的作用是循环的拉取数据往下游发送
回到AsyncWaitOperator.java在它的open方法初始化了Emitter,那它是如何处理接收到的数据的呢,看它的ProcessElement()方法



其实主要就是三个个方法
先是!!!将record封装成了一个包装类StreamRecordQueueEntry,主要是这个包装类的构造方法中,创建了一个CompleteableFuture(这个的complete方法其实会等到用户代码执行的时候用户自己决定什么时候完成)
1处主要就是讲元素加入到了对应的queue,这里也分为两种有序和无序的

这里也先不讲这两种模式加入数据的区别
接着2处就是调用用户的代码了,来看看官网的异步io的例子

给了一个Future作为参数,用户自己起了一个线程(这里思考一下就知道了为什么要新起一个异步线程去执行,因为如果不起线程的话,那processElement方法就柱塞了,无法异步了)去写库读库等,然后调用了这个参数的complete方法(也就是前面那个包装类中的CompleteableFuture)并且传入了一个结果
看下complete方法源码

这个resultFuture是每个record的包装类StreamRecordQueueEntry的其中一个属性是一个CompletableFuture
那现在就清楚了,用户代码在自己新起的线程中当自己的逻辑执行完以后会使这个异步线程结束,并输入一个结果
那这个干嘛用的呢
最开始的图中看到有序和无序实现原理,有序用一个queue,无序用两个queue分别就对应了
OrderedStreamElementQueue类中

UnorderedStreamElementQueue类中

回到前面有两个地方没有细讲,一是两种模式的Emitter是如何拉取数据的,二是两种模式下数据是如何加入OrderedStreamElementQueue的
有序模式:
1.先来看一下有序模式的,Emitter的数据拉取,和数据的加入
其tryPut()方法


onComplete方法

onCompleteHandler方法
这里比较绕,先将接收的数据加入queue中,然后onComplete()中当上一个异步线程getFuture() 其实就是每个元素包装类里面的那个CompletableFuture,当他结束时(会在用户方法用户调用complete时结束)异步调用传入的对象的 accept方法,accept方法中调用了onCompleteHandler()方法,onCompleteHandler方法中会判断queue是否为空,以及queue的头元素是否完成了用户的异步方法,当完成的时候,就会将headIsCompleted这个对象signalAll()唤醒
2.接着看有序模式Emitter的拉取数据

这里有序方式拉取数据的逻辑很清晰,如果为空或者头元素没有完成用户的异步方法,headIsCompleted这个对象会wait住(上面可以知道,当加入元素的到queue且头元素完成异步方法的时候会signalAll())然后将头数据返回,往下游发送
这样就实现了有序发送,因为Emitter只拉取头元素且已经完成用户异步方法的头元素
无序模式:
这里和有序模式就大同小异了,只是变成了,接收数据后直接加入uncompletedQueue,当数据完成异步方法的时候就,放到completedQueue里面去并signalAll(),只要completedqueue里面有数据,Emitter就拉取往下发
这样就实现了无序模式,也就是异步写入谁先处理完就直接放到完成队列里面去,然后往下发,不用管接收数据的顺序
Flink中异步AsyncIO的实现 (源码分析)的更多相关文章
- Flink中Idle停滞流机制(源码分析)
前几天在社区群上,有人问了一个问题 既然上游最小水印会决定窗口触发,那如果我上游其中一条流突然没有了数据,我的窗口还会继续触发吗? 看到这个问题,我蒙了???? 对哈,因为我是选择上游所有流中水印最小 ...
- Flink中的CEP复杂事件处理 (源码分析)
其实CEP复杂事件处理,简单来说你可以用通过类似正则表达式的方式去表示你的逻辑,表现能力非常的强,用过的人都知道 开篇先偷一张图,整体了解Flink中的CEP中的 一种重要的图 NFA非确定有限状 ...
- Flink 中LatencyMarks延迟监控(源码分析)
流式计算中处理延迟是一个非常重要的监控metric flink中通过开启配置 metrics.latency.interval 来开启latency后就可以在metric中看到askManage ...
- 异步编程之co——源码分析
异步编程系列教程: (翻译)异步编程之Promise(1)--初见魅力 异步编程之Promise(2):探究原理 异步编程之Promise(3):拓展进阶 异步编程之Generator(1)--领略魅 ...
- RocketMQ中Broker的HA策略源码分析
Broker的HA策略分为两部分①同步元数据②同步消息数据 同步元数据 在Slave启动时,会启动一个定时任务用来从master同步元数据 if (role == BrokerRole.SLAVE) ...
- Flink的Job启动TaskManager端(源码分析)
前面说到了 Flink的JobManager启动(源码分析) 启动了TaskManager 然后 Flink的Job启动JobManager端(源码分析) 说到JobManager会将转化得到 ...
- RocketMQ中Broker的刷盘源码分析
上一篇博客的最后简单提了下CommitLog的刷盘 [RocketMQ中Broker的消息存储源码分析] (这篇博客和上一篇有很大的联系) Broker的CommitLog刷盘会启动一个线程,不停地 ...
- 【Java】NIO中Selector的select方法源码分析
该篇博客的有些内容和在之前介绍过了,在这里再次涉及到的就不详细说了,如果有不理解请看[Java]NIO中Channel的注册源码分析, [Java]NIO中Selector的创建源码分析 Select ...
- List中的ArrayList和LinkedList源码分析
List是在面试中经常会问的一点,在我们面试中知道的仅仅是List是单列集合Collection下的一个实现类, List的实现接口又有几个,一个是ArrayList,还有一个是LinkedLis ...
随机推荐
- LeetCode_225-Implement Stack using Queues
使用队列实现栈的操作 class MyStack { public: /** Initialize your data structure here. */ MyStack() { } /** Pus ...
- 并发新构件之DelayQueue:延时队列
DelayQueue:延时队列,首先是一个队列,所以可以持有对象,但是仅限于实现了Delayed接口的对象.重写getDelay()和compareTo()(因为要比较)方法: 通俗来讲:延时队列的就 ...
- MySQL学习(一)索引的基本认识
MySQL中,所有的数据类型都可以被索引,包括普通索引,唯一性索引,全文索引,单列索引,多列索引和空间索引等. 额外的:我已知的自动创建索引的时机:创建主键,唯一,外键约束的时候 一.索引简介 1.1 ...
- sql 外键 on update cascade 和 on delete cascade 作用区别?
这是数据库外键定义的一个可选项,用来设置当主键表中的被参考列的数据发生变化时,外键表中响应字段的变换规则的.update 则是主键表中被参考字段的值更新,delete是指在主键表中删除一条记录:on ...
- vue中百度地图API的调用
1.使用百度地图api需要使用jsonp,来获取百度api的返回,因为vue不自带jsonp所以需要下载 安装jsonp npm i vue-jsonp -S 引入jsop import Vue fr ...
- unittest中HTMLTestRunner模块生成
unittest里面是不能生成html格式报告的,需要导入一个第三方的模块:HTMLTestRunner 一.导入HTMLTestRunner 方法1.这个模块下载不能通过pip安装了,只能下载后手动 ...
- oracle 分区表(子分区)收缩笔记
思路1.首先移动子分区到别的表空间.2.收缩数据文件.3.再把子分区移回原表空间. ---------------------------------------------生成发送报告移动子分区语句 ...
- windows进程中的内存结构(缓冲溢出原理)
接触过编程的人都知道,高级语言都能通过变量名来访问内存中的数据.那么这些变量在内存中是如何存放的呢?程序又是如何使用这些变量的呢?下面就会对此进行深入的讨论.下文中的C语言代码如没有特别声明,默认都使 ...
- PHP ksort
1.例子一: <?php /** * 根据 c1 对元素排序 */ $arrays = [ 'b' => [ 'c1' => 10, 'c2' => 5, ], 'a' =&g ...
- [专题练习] Part1 搜索
本文中的链接有的是题解有的是题目链接,已经搞混了... 一.DFS(深度优先搜索) 过于水略过. 二.BFS(广度优先搜索) 同上. 三.记忆化 记忆化搜索,就是我们的状态会重复利用,为了防止状态的重 ...