先上张图整体了解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的实现 (源码分析)的更多相关文章

  1. Flink中Idle停滞流机制(源码分析)

    前几天在社区群上,有人问了一个问题 既然上游最小水印会决定窗口触发,那如果我上游其中一条流突然没有了数据,我的窗口还会继续触发吗? 看到这个问题,我蒙了???? 对哈,因为我是选择上游所有流中水印最小 ...

  2. Flink中的CEP复杂事件处理 (源码分析)

    其实CEP复杂事件处理,简单来说你可以用通过类似正则表达式的方式去表示你的逻辑,表现能力非常的强,用过的人都知道 开篇先偷一张图,整体了解Flink中的CEP中的  一种重要的图  NFA非确定有限状 ...

  3. Flink 中LatencyMarks延迟监控(源码分析)

    流式计算中处理延迟是一个非常重要的监控metric flink中通过开启配置   metrics.latency.interval  来开启latency后就可以在metric中看到askManage ...

  4. 异步编程之co——源码分析

    异步编程系列教程: (翻译)异步编程之Promise(1)--初见魅力 异步编程之Promise(2):探究原理 异步编程之Promise(3):拓展进阶 异步编程之Generator(1)--领略魅 ...

  5. RocketMQ中Broker的HA策略源码分析

    Broker的HA策略分为两部分①同步元数据②同步消息数据 同步元数据 在Slave启动时,会启动一个定时任务用来从master同步元数据 if (role == BrokerRole.SLAVE) ...

  6. Flink的Job启动TaskManager端(源码分析)

    前面说到了  Flink的JobManager启动(源码分析)  启动了TaskManager 然后  Flink的Job启动JobManager端(源码分析)  说到JobManager会将转化得到 ...

  7. RocketMQ中Broker的刷盘源码分析

    上一篇博客的最后简单提了下CommitLog的刷盘  [RocketMQ中Broker的消息存储源码分析] (这篇博客和上一篇有很大的联系) Broker的CommitLog刷盘会启动一个线程,不停地 ...

  8. 【Java】NIO中Selector的select方法源码分析

    该篇博客的有些内容和在之前介绍过了,在这里再次涉及到的就不详细说了,如果有不理解请看[Java]NIO中Channel的注册源码分析, [Java]NIO中Selector的创建源码分析 Select ...

  9. List中的ArrayList和LinkedList源码分析

    ​ List是在面试中经常会问的一点,在我们面试中知道的仅仅是List是单列集合Collection下的一个实现类, List的实现接口又有几个,一个是ArrayList,还有一个是LinkedLis ...

随机推荐

  1. kali系统

    打开终端分别输入下面两条命令: update-alternatives --install /usr/bin/python python /usr/bin/python2 100 update-alt ...

  2. Java源码解析|HashMap的前世今生

    HashMap的前世今生 Java8在Java7的基础上,做了一些改进和优化. 底层数据结构和实现方法上,HashMap几乎重写了一套 所有的集合都新增了函数式的方法,比如说forEach,也新增了很 ...

  3. 配置code::blocks的glut环境

    code::blocks很小,特别适合小型项目及家用旧电脑上MingW下编程,当然windows还是安装的Visual Studio办公用的,现把配置过程记录一遍. 1.在百度搜code::block ...

  4. Tomcat基本知识(一)

    顶层架构先上一张Tomcat的顶层结构图(图A),如下: Tomcat中最顶层的容器是Server,代表着整个服务器,从上图中可以看出,一个Server可以包含至少一个Service,用于具体提供服务 ...

  5. Java表达式计算转型规则

    本题答案应为:B.C.D ------------知识点------------ Java表达式转型规则由低到高转换(例如int 到 double): 1.所有的byte,short,char型的值将 ...

  6. Spring Cloud Alibaba学习笔记(3) - Ribbon

    1.手写一个客户端负载均衡器 在了解什么是Ribbon之前,首先通过代码的方式手写一个负载均衡器 RestTemplate restTemplate = new RestTemplate(); // ...

  7. jquery的返回顶端的功能实现

    页面很长的时候,读到最下面,需要返回顶端,则在页面最下面布局一个返回顶部的图标很有用. 具体功能是,jquey控制,向下滚动出现返回顶部图片,若滚动返回顶部或点回顶部,则图标消失. 实现效果如下图:

  8. python的递归函数怎么用

    在函数内部,可以调用其他函数.如果一个函数在内部调用自身本身,这个函数就是递归函数 理论上,所有的递归函数都可以写成循环的方式,但循环的逻辑不如递归清晰 使用递归函数需要注意防止栈溢出.由于栈的大小不 ...

  9. Fiddler抓包工具的基本操作

    Fiddler ——位于客户端和服务器端的HTTP代理 代理:客户端所有请求都先经过fiddler,然后转发到相应服务器 服务器端所有相应都先经过fiddler,然后发送到客户端 1. 常用的HTTP ...

  10. Ubuntu 14.04风扇不停转,风扇狂转 的解决办法,亲测有效。

    Ubuntu 14.04风扇不停转,风扇狂转 的解决办法,亲测有效. 原文  http://ubuntuforums.org/showthread.php?t=2218367 楼主说:ubuntu 1 ...