聊聊Flink异步I/O机制的原理


异步I/O专门用来解决Flink计算过程中与外部系统的交互问题。在默认情况下,算子向外部系统发出请求后即阻塞,等待结果返回才能发送下一个请求,可能会造成较大的延迟,吞吐量下降。有了异步I/O之后,就可以并发地发出请求和接收响应,延迟大大降低。下图来自官方文档,一看便知。

聊聊Flink异步I/O机制的原理

image

要享受异步I/O带来的便利,前提就是我们有一个能异步请求外部系统的客户端。如果原生没有提供,就得自己创建有限大小的线程池,将客户端放到线程池里调用。

异步I/O的原始设计文档见FLIP-12。但是随着时间的推移,它里面的内容与目前最新的Flink 1.9版本的实现有了一定出入,所以就不参考它了,直接讲讲笔者读过1.9版本的相关源码之后总结出的东西吧。

在调用AsyncDataStream.orderedWait()/unorderedWait()方法时,本质上是产生了一个AsyncWaitOperator算子,它是异步I/O的核心。每个AsyncWaitOperator都由三个主要的部分组成。

所谓StreamElementQueueEntry就是StreamElement(Flink基础概念,可以是流中的一条数据,或是一个水印等)的简单封装,通过j.u.c.CompletableFuture实现异步返回。CompletableFuture是JDK 8提供的新特性,可以认为是非常好用的Future改进版,这里就不再展开讲了。

以下是以StreamElementQueueEntry为中心展开的类图。看官会注意到它有两种实现:代表数据的StreamRecordQueueEntry,和代表水印的WatermarkQueueEntry。它们都持有CompletableFuture。

聊聊Flink异步I/O机制的原理

image

AsyncWaitOperator的机制可以用下面的简图来表示。

聊聊Flink异步I/O机制的原理

image

  1. 来自上游的StreamElement进入AsyncWaitOperator的StreamElementQueue,并被封装成StreamElementQueueEntry。
  2. AsyncWaitOperator调用传入的AsyncFunction的asyncInvoke()方法,该方法异步地与外部系统交互。
  3. 异步操作完成后,由asyncInvoke()方法显式地调用ResultFuture.complete()方法,将结果返回;或者调用completeExceptionally()方法表示出现了异常。ResultFuture就是CompletableFuture的代理接口。
  4. Emitter线程从StreamElementQueue中拉取那些已经完成了的StreamElementQueueEntry,并输出到下游算子。

以上的分析说明了AsyncWaitOperator的工作流程,但是没有考虑输出流的顺序性。实际上会有以下两种情况:

聊聊Flink异步I/O机制的原理

image

简单讨论一下。

聊聊Flink异步I/O机制的原理

image

聊聊Flink异步I/O机制的原理

异步I/O的检查点做起来很容易。由上面的分析可以知道,StreamElementQueue保存的就是尚未完成异步请求的元素,以及已完成异步请求但还没有送到Emitter发送的元素,只要遍历该队列,并将它们都放入状态后端就OK。

展开阅读全文

页面更新:2024-05-16

标签:检查点   算子   水印   队列   线程   下游   顺序   客户端   放入   元素   原理   机制   情况   操作   时间   方法   系统   科技

1 2 3 4 5

上滑加载更多 ↓
推荐阅读:
友情链接:
更多:

本站资料均由网友自行发布提供,仅用于学习交流。如有版权问题,请与我联系,QQ:4156828  

© CopyRight 2020-2024 All Rights Reserved. Powered By 71396.com 闽ICP备11008920号-4
闽公网安备35020302034903号

Top