Apache Flink源码解析之stream-source

简介: 今天我们来解读一下Flink stream里的source模块。它是整个stream的入口,也是我们了解其流处理体系的入口。 SourceFunction SourceFunction是所有stream source的根接口。

今天我们来解读一下Flink stream里的source模块。它是整个stream的入口,也是我们了解其流处理体系的入口。

SourceFunction

SourceFunction是所有stream source的根接口。

它继承自一个标记接口(空接口)Function

SourceFunction定义了两个接口方法:

  • run : 启动一个source,即对接一个外部数据源然后emit元素形成stream(大部分情况下会通过在该方法里运行一个while循环的形式来产生stream)。
  • cancel : 取消一个source,也即将run中的循环emit元素的行为终止。

正常情况下,一个SourceFunction实现这两个接口方法就可以了。其实这两个接口方法也固化了一种实现模板

比如,实现一个XXXSourceFunction,那么大致的模板是这样的:

private volatile boolean isRunning = true;

    @Override
    public void run(SourceContext<T> ctx) throws Exception {
        while (isRunning && otherCondition == true) {
            ctx.collect(getElement());
        }
    }

    @Override
    public void cancel() {
        isRunning = false;
    }

SourceContext

Flink将Source的运行机制跟其如何emit元素进行了分离。具体如何emit元素,取决于另外一个独立的接口SourceContextSourceFunction以内部接口的方式定义了该上下文接口对象,将具体的实现抛给具体的sourceFunction。该接口中定义了emit元素的接口方法:

  • collect : 从source emit一个元素,该元素的时间戳被自动设置为本地时钟(System#currentTimeMillis()),这种由当前source自动追加的时间戳,在Flink里称之为Ingress Time(即摄入时间)。
  • collectWithTimestamp : 根据用户提供的自定义的时间戳emit一个元素,这种被称之为Event Time(即用户自行设置的事件时间)。
  • emitWatermark : 手动发射一个Watermark

这里有几个时间概念可参考我之前的文章:http://vinoyang.com/2016/05/02/flink-concepts/#时间

Watermark:Flink用Watermark来对上面的Event Time类型的事件进行窗口处理。所谓的Watermark是一个时间基准。WaterMark包含一个时间戳,Flink使用WaterMark标记所有小于该时间戳的消息都已流入,Flink的数据源在确认所有小于某个时间戳的消息都已输出到Flink流处理系统后,会生成一个包含该时间戳的WaterMark,插入到消息流中输出到Flink流处理系统中,Flink操作符按照时间窗口缓存所有流入的消息,当operator处理到WaterMark时,它对所有小于该WaterMark时间戳的时间窗口数据进行处理并发送到下一个operator节点,然后也将WaterMark发送到下一个operator节点。

内置的SourceFunction

source相关的完整类图如下:

flink-stream-source_class-diagram

RichSourceFunction

一个抽象类,继承自AbstractRichFunction。为实现一个Rich SourceFunction提供基础能力(其实所谓的Rich,主要是提供某种范式或者模板帮助你完成一部分基础实现)。该类的子类有两个,不过他们仍然是抽象类,只是在此基础上提供了更具体的实现:

  • MessageAcknowledgingSourceBase :它针对的是数据源是消息队列的场景并且提供了基于ID的应答机制。
  • MultipleIdsMessageAcknowledgingSourceBase : 在MessageAcknowledgingSourceBase的基础上针对ID应答机制进行了更为细分的处理,支持两种ID应答模型:session idunique message id

ParallelSourceFunction

该接口只是个标记接口,用于标识继承该接口的Source都是并行执行的。其直接实现类是RichParallelSourceFunction,它是一个抽象类并继承自AbstractRichFunction(从名称可以看出,它应该兼具richparallel两个特性,这里的rich体现在它定义了openclose这两个方法)。

继承RichParallelSourceFunction的那些SourceFunction意味着它们都是并行执行的并且可能有一些资源需要open/close,Flink提供了这么几个实现:

  • FileSourceFunction : 以文件为数据源的Source,它根据给定的InputFormat作为数据源记录的生产器(它可以接收一个file path来基于文件生产记录),根据给定的TypeInformation来产生序列化器,再结合内部创建的splitIterator实现了一个基于文件的sourceFunction。
  • ConnectorSource : 抽象类,没有具体的实现。通过其构造器注入了一个属性DeserializationSchema,该属性是一个协议接口,用于定义如何将二进制数据反序列化为Java/Scala对象。
  • StatefulSequenceSource :有状态的序列Source。它接收startend作为一个发射序列的区间,然后根据一定的算法算得需要发射的时间间隔,并保证区间内的元素送达具有exactly once的强一致性,具体的计算方式需要结合当前task的subtask的数量以及当前subtask在集合中的索引计算得出。
  • FromSplittableIteratorFunction :根据给定的SplittableIterator(它是一个全局的iterator)结合当前task运行时subtask的数量,以及该subtask在所有subtask中的序号计算出分区(partition)从而产生一个细分的Iterator。通过Iterator迭代来发射元素。

FileMonitoringFunction

该Source是以监控给定path位置的文件为手段,根据给定的interval作为时间间隔,emit的内容依赖监控文件的变。Flink为这种形式的Source提供了三种watchtype :

    public enum WatchType {
        ONLY_NEW_FILES,                 //仅关注新文件产生
        REPROCESS_WITH_APPENDED,    //当有文件产生变更,该文件的所有内容都需要被重新处理
        PROCESS_ONLY_APPENDED       //当有文件产生变更,只有变更的内容需要被处理
    }

该类型的Source始终发射的是一个三元组(Tuple3),它包含三个元素:

  • filePath : 标识文件路径
  • offset : 偏移量
  • fileSize : 文件大小

watchtype的不同主要影响发射元素的内容。当WatchType的类型为ONLY_NEW_FILESREPROCESS_WITH_APPENDED类型时,offset会被设置为0,fileSize被设置为-1。而WatchType类型为PROCESS_ONLY_APPENDED,则三个值都为其对应的真实值。

SocketTextStreamFunction

根据给定的hostnameport,以socket的方式进行通信并获取数据,以delimiter参数给定的字符作为终止标识符。

FromIteratorFunction

该Source接收一个迭代器,然后在发射循环体中,依次迭代发射数据。

FromElementsFunction

该Source接收一个元素迭代器(一组元素的集合),以Flink的类型序列化机制将其序列化为二进制数据,然后在发射元素的循环体中,进行反序列化为初始类型,再发射数据。

这里先序列化为二进制,再从二进制反序列化为最初的对象类型。不是特别容易理解,乍一看多此一举,让人匪夷所思。其实,这么做是有原因的,是因为Flink的序列化机制是其自定义的,并且跟其自主管理内存紧密联系在一起(想了解其自主内存管理的可参看我之前的系列文章)。而自主内存管理又涉及到二进制数据的存储。FromElementsFunction支持从某个check point部分恢复,所以必须先还原其原先的存储位置(通过序列化),然后跳过不需要emit的元素,然后再发射需要发射的元素(将这些元素反序列化)。

常见连接器中的Source

Flink自身提供了一些针对第三方主流开源系统的连接器支持,它们有:

  • elasticsearch
  • flume
  • kafka(0.8/0.9版本)
  • nifi
  • rabbitmq
  • twitter

这些连接器有些可以同时作为sourcesink。因为我们今天的主题是source,所以我们先来看看以上这些被支持的连接器它们的source都是继承自刚刚我们谈到的哪些接口或者类。

  • kafka : RichParallelSourceFunction
  • nifi : RichParallelSourceFunction
  • rabbitmq : MultipleIdsMessageAcknowledgingSourceBase(因为rabbitmq具备非常成熟的ack机制,所以继承这个类是顺其自然的)

小结

这篇文章我们主要谈及了Flink的stream source相关的设计、实现。当然这个主题还没有完全谈完,还会有后续篇幅继续解读。




原文发布时间为:2016-05-05


本文作者:vinoYang


本文来自云栖社区合作伙伴CSDN博客,了解相关信息可以关注CSDN博客。

相关实践学习
基于Hologres+Flink搭建GitHub实时数据大屏
通过使用Flink、Hologres构建实时数仓,并通过Hologres对接BI分析工具(以DataV为例),实现海量数据实时分析.
实时计算 Flink 实战课程
如何使用实时计算 Flink 搞定数据处理难题?实时计算 Flink 极客训练营产品、技术专家齐上阵,从开源 Flink功能介绍到实时计算 Flink 优势详解,现场实操,5天即可上手! 欢迎开通实时计算 Flink 版: https://cn.aliyun.com/product/bigdata/sc Flink Forward Asia 介绍: Flink Forward 是由 Apache 官方授权,Apache Flink Community China 支持的会议,通过参会不仅可以了解到 Flink 社区的最新动态和发展计划,还可以了解到国内外一线大厂围绕 Flink 生态的生产实践经验,是 Flink 开发者和使用者不可错过的盛会。 去年经过品牌升级后的 Flink Forward Asia 吸引了超过2000人线下参与,一举成为国内最大的 Apache 顶级项目会议。结合2020年的特殊情况,Flink Forward Asia 2020 将在12月26日以线上峰会的形式与大家见面。
目录
相关文章
|
存储 缓存 算法
分布式锁服务深度解析:以Apache Flink的Checkpointing机制为例
【10月更文挑战第7天】在分布式系统中,多个进程或节点可能需要同时访问和操作共享资源。为了确保数据的一致性和系统的稳定性,我们需要一种机制来协调这些进程或节点的访问,避免并发冲突和竞态条件。分布式锁服务正是为此而生的一种解决方案。它通过在网络环境中实现锁机制,确保同一时间只有一个进程或节点能够访问和操作共享资源。
502 3
|
安全 网络协议 应用服务中间件
AJP Connector:深入解析及在Apache HTTP Server中的应用
【9月更文挑战第6天】在Java Web应用开发中,Tomcat作为广泛使用的Servlet容器,经常与Apache HTTP Server结合使用,以提供高效、稳定的Web服务。而AJP Connector(Apache JServ Protocol Connector)作为连接Tomcat和Apache HTTP Server的重要桥梁,扮演着至关重要的角色
565 2
|
存储 物联网 大数据
探索阿里云 Flink 物化表:原理、优势与应用场景全解析
阿里云Flink的物化表是流批一体化平台中的关键特性,支持低延迟实时更新、灵活查询性能、无缝流批处理和高容错性。它广泛应用于电商、物联网和金融等领域,助力企业高效处理实时数据,提升业务决策能力。实践案例表明,物化表显著提高了交易欺诈损失率的控制和信贷审批效率,推动企业在数字化转型中取得竞争优势。
505 16
|
消息中间件 存储 负载均衡
Apache Kafka核心概念解析:生产者、消费者与Broker
【10月更文挑战第24天】在数字化转型的大潮中,数据的实时处理能力成为了企业竞争力的重要组成部分。Apache Kafka 作为一款高性能的消息队列系统,在这一领域占据了重要地位。通过使用 Kafka,企业可以构建出高效的数据管道,实现数据的快速传输和处理。今天,我将从个人的角度出发,深入解析 Kafka 的三大核心组件——生产者、消费者与 Broker,希望能够帮助大家建立起对 Kafka 内部机制的基本理解。
536 2
|
消息中间件 Kubernetes 监控
实时计算 Flink版操作报错合集之在编译源码时遇到报错:无法访问,该如何处理
在使用实时计算Flink版过程中,可能会遇到各种错误,了解这些错误的原因及解决方法对于高效排错至关重要。针对具体问题,查看Flink的日志是关键,它们通常会提供更详细的错误信息和堆栈跟踪,有助于定位问题。此外,Flink社区文档和官方论坛也是寻求帮助的好去处。以下是一些常见的操作报错及其可能的原因与解决策略。
|
分布式计算 Java Apache
Apache Spark Streaming技术深度解析
【9月更文挑战第4天】Apache Spark Streaming是Apache Spark生态系统中用于处理实时数据流的一个重要组件。它将输入数据分成小批次(micro-batch),然后利用Spark的批处理引擎进行处理,从而结合了批处理和流处理的优点。这种处理方式使得Spark Streaming既能够保持高吞吐量,又能够处理实时数据流。
340 0
|
安全 搜索推荐 数据挖掘
文件解析的终极工具:Apache Tika
文件解析的终极工具:Apache Tika
2436 0
|
JSON 资源调度 Kubernetes
实时计算 Flink版操作报错合集之解析JSON数组时,遇到报错,该怎么解决
在使用实时计算Flink版过程中,可能会遇到各种错误,了解这些错误的原因及解决方法对于高效排错至关重要。针对具体问题,查看Flink的日志是关键,它们通常会提供更详细的错误信息和堆栈跟踪,有助于定位问题。此外,Flink社区文档和官方论坛也是寻求帮助的好去处。以下是一些常见的操作报错及其可能的原因与解决策略。
320 0
|
10月前
|
算法 测试技术 C语言
深入理解HTTP/2:nghttp2库源码解析及客户端实现示例
通过解析nghttp2库的源码和实现一个简单的HTTP/2客户端示例,本文详细介绍了HTTP/2的关键特性和nghttp2的核心实现。了解这些内容可以帮助开发者更好地理解HTTP/2协议,提高Web应用的性能和用户体验。对于实际开发中的应用,可以根据需要进一步优化和扩展代码,以满足具体需求。
1029 29

推荐镜像

更多