Flink异步I/O

1 概述html

流计算系统中常常须要与外部系统进行交互,咱们一般的作法如向数据库发送用户a的查询请求,而后等待结果返回,在这以前,咱们的程序没法发送用户b的查询请求。这是一种同步访问方式,以下图所示。数据库

imageapache

图中棕色的长条表示等待时间,能够发现网络等待时间极大地阻碍了吞吐和延迟。为了解决同步访问的问题,异步模式能够并发地处理多个请求和回复。也就是说,你能够连续地向数据库发送用户a、b、c等的请求,与此同时,哪一个请求的回复先返回了就处理哪一个回复,从而连续的请求之间不须要阻塞等待,如上图右边所示。这也正是 Async I/O 的实现原理。网络

2 Async I/O原理实现并发

以下官方示例代码:框架

image异步

AsyncDataStream.(un)orderedWait 的主要工做就是建立了一个 AsyncWaitOperator。AsyncWaitOperator 是支持异步 IO 访问的算子实现,该算子会运行 AsyncFunction 并处理异步返回的结果,其内部原理以下图所示。async

image线程

如图所示,AsyncWaitOperator 主要由两部分组成:StreamElementQueue 和 Emitter。StreamElementQueue 是一个 Promise 队列,所谓 Promise 是一种异步抽象表示未来会有一个值,这个队列是未完成的 Promise 队列,也就是进行中的请求队列。Emitter 是一个单独的线程,负责发送消息(收到的异步回复)给下游。htm

图中E5表示进入该算子的第五个元素(”Element-5”),在执行过程当中首先会将其包装成一个 “Promise” P5,而后将P5放入队列。最后调用 AsyncFunction 的 ayncInvoke 方法,该方法会向外部服务发起一个异步的请求,并注册回调。该回调会在异步请求成功返回时调用 AsyncCollector.collect 方法将返回的结果交给框架处理。实际上 AsyncCollector 是一个 Promise ,也就是 P5,在调用 collect 的时候会标记 Promise 为完成状态,并通知 Emitter 线程有完成的消息能够发送了。Emitter 就会从队列中拉取完成的 Promise ,并从 Promise 中取出消息发送给下游。

3 消息顺序性

3.1 有序

有序比较简单,使用一个队列就能实现。全部新进入该算子的元素(包括 watermark),都会包装成 Promise 并按到达顺序放入该队列。以下图所示,尽管P4的结果先返回,但并不会发送,只有 P1 (队首)的结果返回了才会触发 Emitter 拉取队首元素进行发送。

image

3.2 无序

使用两个队列就能实现,一个 uncompletedQueue 一个 completedQueue。全部新进入该算子的元素,一样的包装成 Promise 并放入 uncompletedQueue 队列,当uncompletedQueue队列中任意的Promise返回了数据,则将该 Promise 移到 completedQueue 队列中,并通知 Emitter 消费。以下图所示:

image

References

1.https://ci.apache.org/projects/flink/flink-docs-release-1.6/dev/stream/operators/asyncio.html

相关文章
相关标签/搜索