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 ...
随机推荐
- Node Sass could not find a binding for your current environment: OS X 64-bit with Node.js 10.x
运行Reac项目报: Node Sass could not find a binding for your current environment: OS X 64-bit with Node.js ...
- F#周报2019年第42期
新闻 TypeShape的性能 .NET Core 3.0包含.NET Framework API移植项目 宣告.NET Core 3.1预览版1 .NET Core 3.1预览版1中ASP.NET ...
- Jenkins部署(基于windows)
一.安装jdk,配置环境变量 二.安装tomcat和jenkins 1.检查电脑上8080端口是否被占用: 命令行中输入:netstat -ano 2.下载Tomcat Tomcat官方网站:http ...
- dll劫持破坏360
0x01 前言 说起DLL劫持技术,相信大家都不会陌生,因为这种技术的应用比较广泛,比如木马后门的启动.破解程序的内存补丁.外挂插件的注入以及加密狗的模拟等.之所以DLL劫持技术深受黑客们的喜爱,主要 ...
- JVM 中发生内存溢出的 8 种原因及解决办法
1. Java 堆空间 2. GC 开销超过限制 3. 请求的数组大小超过虚拟机限制 4. Perm gen 空间 5. Metaspace 6. 无法新建本机线程 7. 杀死进程或子进程 8. 发生 ...
- SpringBoot中神奇的@Enable*注解?
在SpringBoot开发过程,我们经常会遇到@Enable开始的好多注解,比如@EnableEurekaServer.@EnableAsync.@EnableScheduling等,今天我们就来分析 ...
- openssl生成密钥/证书
一.公钥/私钥/签名/验证签名/加密/解密/非对称加密 对称加密:用同一个密码 加密/解密 文件. 非对称加密:加密用的一个密码,解密用另外一组密码. 加密解密:公钥加密数据,然后私钥解密. 公钥 ...
- jquery mutilselect 插件添加中英文自动补全
jquery mutilselect默认只能根据设置的option来进行自动提示 $.each(availableTags, function(key, value) { $('#channels') ...
- javascript学习总结之Object.assign()方法详解
最近再写ES6的文章时候发现自己对Object.assign()方法不太了解,之前也没有接触过所以就就查阅了相关的资料,为了自己以后肯能会用到以及对知识进行巩固,所以在这里记录下自己学习的点点滴滴,毕 ...
- RabbitMQ通过DLX实现消息延迟接收
1. 创建队列WorkQueue,并把WorkQueue跟exchangeWork绑定:2. 创建队列DLXQueue,并把DLXQueue跟exchangeDLX绑定:a. 设置DLXQueue队列 ...