blob: 1f9f4fbcdfdb22d07ebb9b7a34576c4c0306bcb1 [file] [log] [blame]
"use strict";(function(){const t={encode:!1,tokenize:function(e){return e.replace(/[\x00-\x7F]/g,"").split("")}};t.doc={id:"id",field:["title","content"],store:["title","href","section"]};const e=FlexSearch.create("balance",t);window.bookSearchIndex=e,e.add({id:0,href:"/zh/documentation/flink-stable/",title:"Flink $FlinkStableShortVersion (stable)",section:"Documentation",content:" Flink documentation (latest stable release) # You can find the Flink documentation for the latest stable release here. "}),e.add({id:1,href:"/zh/getting-started/with-flink/",title:"With Flink",section:"教程",content:" Getting Started with Flink # Read how you can get started with Flink here. "}),e.add({id:2,href:"/zh/what-is-flink/flink-architecture/",title:"架构",section:"About",content:` Apache Flink 是什么? # Apache Flink 是一个框架和分布式处理引擎,用于在无边界和有边界数据流上进行有状态的计算。Flink 能在所有常见集群环境中运行,并能以内存速度和任意规模进行计算。
接下来,我们来介绍一下 Flink 架构中的重要方面。
处理无界和有界数据 # 任何类型的数据都可以形成一种事件流。信用卡交易、传感器测量、机器日志、网站或移动应用程序上的用户交互记录,所有这些数据都形成一种流。
数据可以被作为 无界 或者 有界 流来处理。
无界流 有定义流的开始,但没有定义流的结束。它们会无休止地产生数据。无界流的数据必须持续处理,即数据被摄取后需要立刻处理。我们不能等到所有数据都到达再处理,因为输入是无限的,在任何时候输入都不会完成。处理无界数据通常要求以特定顺序摄取事件,例如事件发生的顺序,以便能够推断结果的完整性。
有界流 有定义流的开始,也有定义流的结束。有界流可以在摄取所有数据后再进行计算。有界流所有数据可以被排序,所以并不需要有序摄取。有界流处理通常被称为批处理
Apache Flink 擅长处理无界和有界数据集 精确的时间控制和状态化使得 Flink 的运行时(runtime)能够运行任何处理无界流的应用。有界流则由一些专为固定大小数据集特殊设计的算法和数据结构进行内部处理,产生了出色的性能。
通过探索 Flink 之上构建的 用例 来加深理解。
部署应用到任意地方 # Apache Flink 是一个分布式系统,它需要计算资源来执行应用程序。Flink 集成了所有常见的集群资源管理器,例如 Hadoop YARN Apache Mesos Kubernetes,但同时也可以作为独立集群运行。
Flink 被设计为能够很好地工作在上述每个资源管理器中,这是通过资源管理器特定(resource-manager-specific)的部署模式实现的。Flink 可以采用与当前资源管理器相适应的方式进行交互。
部署 Flink 应用程序时,Flink 会根据应用程序配置的并行性自动标识所需的资源,并从资源管理器请求这些资源。在发生故障的情况下,Flink 通过请求新资源来替换发生故障的容器。提交或控制应用程序的所有通信都是通过 REST 调用进行的,这可以简化 Flink 与各种环境中的集成。
运行任意规模应用 # Flink 旨在任意规模上运行有状态流式应用。因此,应用程序被并行化为可能数千个任务,这些任务分布在集群中并发执行。所以应用程序能够充分利用无尽的 CPU、内存、磁盘和网络 IO。而且 Flink 很容易维护非常大的应用程序状态。其异步和增量的检查点算法对处理延迟产生最小的影响,同时保证精确一次状态的一致性。
Flink 用户报告了其生产环境中一些令人印象深刻的扩展性数字
处理每天处理数万亿的事件, 应用维护几TB大小的状态, 应用在数千个内核上运行。 利用内存性能 # 有状态的 Flink 程序针对本地状态访问进行了优化。任务的状态始终保留在内存中,如果状态大小超过可用内存,则会保存在能高效访问的磁盘数据结构中。任务通过访问本地(通常在内存中)状态来进行所有的计算,从而产生非常低的处理延迟。Flink 通过定期和异步地对本地状态进行持久化存储来保证故障场景下精确一次的状态一致性。
`}),e.add({id:3,href:"/zh/documentation/flink-master/",title:"Flink Master (snapshot)",section:"Documentation",content:" Flink documentation (latest snapshot) # You can find the Flink documentation for the latest snapshot here. "}),e.add({id:4,href:"/zh/getting-started/with-flink-kubernetes-operator/",title:"With Flink Kubernetes Operator",section:"教程",content:" Getting Started with Flink Kubernetes Operator # Read how you can get started with Flink Kubernetes Operator here. "}),e.add({id:5,href:"/zh/what-is-flink/flink-applications/",title:"应用",section:"About",content:` Apache Flink 是什么? # Apache Flink 是一个针对无界和有界数据流进行有状态计算的框架。Flink 自底向上在不同的抽象级别提供了多种 API,并且针对常见的使用场景开发了专用的扩展库。
在本章中,我们将介绍 Flink 所提供的这些简单易用、易于表达的 API 和库。
流处理应用的基本组件 # 可以由流处理框架构建和执行的应用程序类型是由框架对 流、状态、时间 的支持程度来决定的。在下文中,我们将对上述这些流处理应用的基本组件逐一进行描述,并对 Flink 处理它们的方法进行细致剖析。
# 显而易见,(数据)流是流处理的基本要素。然而,流也拥有着多种特征。这些特征决定了流如何以及何时被处理。Flink 是一个能够处理任何类型数据流的强大处理框架。
有界 无界 的数据流:流可以是无界的;也可以是有界的,例如固定大小的数据集。Flink 在无界的数据流处理上拥有诸多功能强大的特性,同时也针对有界的数据流开发了专用的高效算子。 实时 历史记录 的数据流:所有的数据都是以流的方式产生,但用户通常会使用两种截然不同的方法处理数据。或是在数据生成时进行实时的处理;亦或是先将数据流持久化到存储系统中——例如文件系统或对象存储,然后再进行批处理。Flink 的应用能够同时支持处理实时以及历史记录数据流。 状态 # 只有在每一个单独的事件上进行转换操作的应用才不需要状态,换言之,每一个具有一定复杂度的流处理应用都是有状态的。任何运行基本业务逻辑的流处理应用都需要在一定时间内存储所接收的事件或中间结果,以供后续的某个时间点(例如收到下一个事件或者经过一段特定时间)进行访问并进行后续处理。
应用状态是 Flink 中的一等公民,Flink 提供了许多状态管理相关的特性支持,其中包括:
多种状态基础类型:Flink 为多种不同的数据结构提供了相对应的状态基础类型,例如原子值(value),列表(list)以及映射(map)。开发者可以基于处理函数对状态的访问方式,选择最高效、最适合的状态基础类型。 插件化的State BackendState Backend 负责管理应用程序状态,并在需要的时候进行 checkpointFlink 支持多种 state backend,可以将状态存在内存或者 RocksDBRocksDB 是一种高效的嵌入式、持久化键值存储引擎。Flink 也支持插件式的自定义 state backend 进行状态存储。 精确一次语义:Flink checkpoint 和故障恢复算法保证了故障发生后应用状态的一致性。因此,Flink 能够在应用程序发生故障时,对应用程序透明,不造成正确性的影响。 超大数据量状态:Flink 能够利用其异步以及增量式的 checkpoint 算法,存储数 TB 级别的应用状态。 可弹性伸缩的应用:Flink 能够通过在更多或更少的工作节点上对状态进行重新分布,支持有状态应用的分布式的横向伸缩。 时间 # 时间是流处理应用另一个重要的组成部分。因为事件总是在特定时间点发生,所以大多数的事件流都拥有事件本身所固有的时间语义。进一步而言,许多常见的流计算都基于时间语义,例如窗口聚合、会话计算、模式检测和基于时间的 join。流处理的一个重要方面是应用程序如何衡量时间,即区分事件时间(event-time)和处理时间(processing-time)。
Flink 提供了丰富的时间语义支持。
事件时间模式:使用事件时间语义的流处理应用根据事件本身自带的时间戳进行结果的计算。因此,无论处理的是历史记录的事件还是实时的事件,事件时间模式的处理总能保证结果的准确性和一致性。 Watermark 支持:Flink 引入了 watermark 的概念,用以衡量事件时间进展。Watermark 也是一种平衡处理延时和完整性的灵活机制。 迟到数据处理:当以带有 watermark 的事件时间模式处理数据流时,在计算完成之后仍会有相关数据到达。这样的事件被称为迟到事件。Flink 提供了多种处理迟到数据的选项,例如将这些数据重定向到旁路输出(side output)或者更新之前完成计算的结果。 处理时间模式:除了事件时间模式,Flink 还支持处理时间语义。处理时间模式根据处理引擎的机器时钟触发计算,一般适用于有着严格的低延迟需求,并且能够容忍近似结果的流处理应用。 分层 API # Flink 根据抽象程度分层,提供了三种不同的 API。每一种 API 在简洁性和表达力上有着不同的侧重,并且针对不同的应用场景。
下文中,我们将简要描述每一种 API 及其应用,并提供相关的代码示例。
ProcessFunction # ProcessFunction Flink 所提供的最具表达力的接口。ProcessFunction 可以处理一或两条输入数据流中的单个事件或者归入一个特定窗口内的多个事件。它提供了对于时间和状态的细粒度控制。开发者可以在其中任意地修改状态,也能够注册定时器用以在未来的某一时刻触发回调函数。因此,你可以利用 ProcessFunction 实现许多有状态的事件驱动应用所需要的基于单个事件的复杂业务逻辑。
下面的代码示例展示了如何在 KeyedStream 上利用 KeyedProcessFunction 对标记为 START END 的事件进行处理。当收到 START 事件时,处理函数会记录其时间戳,并且注册一个时长4小时的计时器。如果在计时器结束之前收到 END 事件,处理函数会计算其与上一个 START 事件的时间间隔,清空状态并将计算结果返回。否则,计时器结束,并清空状态。
/** * Matches keyed START and END events and computes the difference between * both elements' timestamps. The first String field is the key attribute, * the second String attribute marks START and END events. */ public static class StartEndDuration extends KeyedProcessFunction<String, Tuple2<String, String>, Tuple2<String, Long>> { private ValueState<Long> startTime; @Override public void open(Configuration conf) { // obtain state handle startTime = getRuntimeContext() .getState(new ValueStateDescriptor<Long>("startTime", Long.class)); } /** Called for each processed event. */ @Override public void processElement( Tuple2<String, String> in, Context ctx, Collector<Tuple2<String, Long>> out) throws Exception { switch (in.f1) { case "START": // set the start time if we receive a start event. startTime.update(ctx.timestamp()); // register a timer in four hours from the start event. ctx.timerService() .registerEventTimeTimer(ctx.timestamp() + 4 * 60 * 60 * 1000); break; case "END": // emit the duration between start and end event Long sTime = startTime.value(); if (sTime != null) { out.collect(Tuple2.of(in.f0, ctx.timestamp() - sTime)); // clear the state startTime.clear(); } default: // do nothing } } /** Called when a timer fires. */ @Override public void onTimer( long timestamp, OnTimerContext ctx, Collector<Tuple2<String, Long>> out) { // Timeout interval exceeded. Cleaning up the state. startTime.clear(); } } 这个例子充分展现了 KeyedProcessFunction 强大的表达力,也因此是一个实现相当复杂的接口。
DataStream API # DataStream API 为许多通用的流处理操作提供了处理原语。这些操作包括窗口、逐条记录的转换操作,在处理事件时进行外部数据库查询等。DataStream API 支持 Java Scala 语言,预先定义了例如map()、reduce()、aggregate() 等函数。你可以通过扩展实现预定义接口或使用 JavaScala lambda 表达式实现自定义的函数。
下面的代码示例展示了如何捕获会话时间范围内所有的点击流事件,并对每一次会话的点击量进行计数。
// a stream of website clicks DataStream<Click> clicks = ... DataStream<Tuple2<String, Long>> result = clicks // project clicks to userId and add a 1 for counting .map( // define function by implementing the MapFunction interface. new MapFunction<Click, Tuple2<String, Long>>() { @Override public Tuple2<String, Long> map(Click click) { return Tuple2.of(click.userId, 1L); } }) // key by userId (field 0) .keyBy(0) // define session window with 30 minute gap .window(EventTimeSessionWindows.withGap(Time.minutes(30L))) // count clicks per session. Define function as lambda function. .reduce((a, b) -> Tuple2.of(a.f0, a.f1 + b.f1)); SQL & Table API # Flink 支持两种关系型的 API, Table API 和 SQL 。这两个 API 都是批处理和流处理统一的 API,这意味着在无边界的实时数据流和有边界的历史记录数据流上,关系型 API 会以相同的语义执行查询,并产生相同的结果。Table API 和 SQL 借助了 Apache Calcite 来进行查询的解析,校验以及优化。它们可以与 DataStream 和 DataSet API 无缝集成,并支持用户自定义的标量函数,聚合函数以及表值函数。
Flink 的关系型 API 旨在简化数据分析、数据流水线和 ETL 应用的定义。
下面的代码示例展示了如何使用 SQL 语句查询捕获会话时间范围内所有的点击流事件,并对每一次会话的点击量进行计数。此示例与上述 DataStream API 中的示例有着相同的逻辑。
SELECT userId, COUNT(*) FROM clicks GROUP BY SESSION(clicktime, INTERVAL '30' MINUTE), userId # Flink 具有数个适用于常见数据处理应用场景的扩展库。这些库通常嵌入在 API 中,且并不完全独立于其它 API。它们也因此可以受益于 API 的所有特性,并与其他库集成。
复杂事件处理(CEP) :模式检测是事件流处理中的一个非常常见的用例。Flink CEP 库提供了 API,使用户能够以例如正则表达式或状态机的方式指定事件模式。CEP 库与 Flink DataStream API 集成,以便在 DataStream 上评估模式。CEP 库的应用包括网络入侵检测,业务流程监控和欺诈检测。
DataSet API DataSet API Flink 用于批处理应用程序的核心 APIDataSet API 所提供的基础算子包括mapreduce、(outer) joinco-groupiterate等。所有算子都有相应的算法和数据结构支持,对内存中的序列化数据进行操作。如果数据大小超过预留内存,则过量数据将存储到磁盘。Flink DataSet API 的数据处理算法借鉴了传统数据库算法的实现,例如混合散列连接(hybrid hash-join)和外部归并排序(external merge-sort)。
Gelly : Gelly 是一个可扩展的图形处理和分析库。Gelly 是在 DataSet API 之上实现的,并与 DataSet API 集成。因此,它能够受益于其可扩展且健壮的操作符。Gelly 提供了 内置算法 ,如 label propagationtriangle enumeration page rank 算法,也提供了一个简化自定义图算法实现的 Graph API
`}),e.add({id:6,href:"/zh/documentation/flink-kubernetes-operator-stable/",title:"Kubernetes Operator $FlinkKubernetesOperatorStableShortVersion (latest)",section:"Documentation",content:" Flink Kubernetes Operator documentation (latest stable release) # You can find the Flink Kubernetes Operator documentation for the latest stable release here. "}),e.add({id:7,href:"/zh/getting-started/with-flink-cdc/",title:"With Flink CDC",section:"教程",content:" Getting Started with Flink CDC # Read how you can get started with Flink CDC here. "}),e.add({id:8,href:"/zh/what-is-flink/flink-operations/",title:"运维",section:"About",content:` Apache Flink 是什么? # Apache Flink 是一个针对无界和有界数据流进行有状态计算的框架。由于许多流应用程序旨在以最短的停机时间连续运行,因此流处理器必须提供出色的故障恢复能力,以及在应用程序运行期间进行监控和维护的工具。
Apache Flink 非常注重流数据处理的可运维性。因此在这一小节中,我们将详细介绍 Flink 的故障恢复机制,并介绍其管理和监控应用的功能。
7 * 24小时稳定运行 # 在分布式系统中,服务故障是常有的事,为了保证服务能够7*24小时稳定运行,像Flink这样的流处理器故障恢复机制是必须要有的。显然这就意味着,它(这类流处理器)不仅要能在服务出现故障时候能够重启服务,而且还要当故障发生时,保证能够持久化服务内部各个组件的当前状态,只有这样才能保证在故障恢复时候,服务能够继续正常运行,好像故障就没有发生过一样。
Flink通过几下多种机制维护应用可持续运行及其一致性:
检查点的一致性: Flink的故障恢复机制是通过建立分布式应用服务状态一致性检查点实现的,当有故障产生时,应用服务会重启后,再重新加载上一次成功备份的状态检查点信息。结合可重放的数据源,该特性可保证*精确一次(exactly-once)*的状态一致性。 高效的检查点: 如果一个应用要维护一个TB级的状态信息,对此应用的状态建立检查点服务的资源开销是很高的,为了减小因检查点服务对应用的延迟性(SLAs服务等级协议)的影响,Flink采用异步及增量的方式构建检查点服务。 端到端的精确一次: Flink 为某些特定的存储支持了事务型输出的功能,及时在发生故障的情况下,也能够保证精确一次的输出。 集成多种集群管理服务: Flink已与多种集群管理服务紧密集成,如 Hadoop YARN, Mesos, 以及 Kubernetes。当集群中某个流程任务失败后,一个新的流程服务会自动启动并替代它继续执行。 内置高可用服务: Flink内置了为解决单点故障问题的高可用性服务模块,此模块是基于Apache ZooKeeper 技术实现的,Apache ZooKeeper是一种可靠的、交互式的、分布式协调服务组件。 Flink能够更方便地升级、迁移、暂停、恢复应用服务 # 驱动关键业务服务的流应用是经常需要维护的。比如需要修复系统漏洞,改进功能,或开发新功能。然而升级一个有状态的流应用并不是简单的事情,因为在我们为了升级一个改进后版本而简单停止当前流应用并重启时,我们还不能丢失掉当前流应用的所处于的状态信息。
Flink Savepoint 服务就是为解决升级服务过程中记录流应用状态信息及其相关难题而产生的一种唯一的、强大的组件。一个 Savepoint,就是一个应用服务状态的一致性快照,因此其与checkpoint组件的很相似,但是与checkpoint相比,Savepoint 需要手动触发启动,而且当流应用服务停止时,它并不会自动删除。Savepoint 常被应用于启动一个已含有状态的流服务,并初始化其(备份时)状态。Savepoint 有以下特点:
便于升级应用服务版本: Savepoint 常在应用版本升级时使用,当前应用的新版本更新升级时,可以根据上一个版本程序记录的 Savepoint 内的服务状态信息来重启服务。它也可能会使用更早的 Savepoint 还原点来重启服务,以便于修复由于有缺陷的程序版本导致的不正确的程序运行结果。 方便集群服务移植: 通过使用 Savepoint,流服务应用可以自由的在不同集群中迁移部署。 方便Flink版本升级: 通过使用 Savepoint,可以使应用服务在升级Flink时,更加安全便捷。 增加应用并行服务的扩展性: Savepoint 也常在增加或减少应用服务集群的并行度时使用。 便于A/B测试及假设分析场景对比结果: 通过把同一应用在使用不同版本的应用程序,基于同一个 Savepoint 还原点启动服务时,可以测试对比2个或多个版本程序的性能及服务质量。 暂停和恢复服务: 一个应用服务可以在新建一个 Savepoint 后再停止服务,以便于后面任何时间点再根据这个实时刷新的 Savepoint 还原点进行恢复服务。 归档服务: Savepoint 还提供还原点的归档服务,以便于用户能够指定时间点的 Savepoint 的服务数据进行重置应用服务的状态,进行恢复服务。 监控和控制应用服务 # 如其它应用服务一样,持续运行的流应用服务也需要监控及集成到一些基础设施资源管理服务中,例如一个组件的监控服务及日志服务等。监控服务有助于预测问题并提前做出反应,日志服务提供日志记录能够帮助追踪、调查、分析故障发生的根本原因。最后,便捷易用的访问控制应用服务运行的接口也是Flink的一个重要的亮点特征。
Flink与许多常见的日志记录和监视服务集成得很好,并提供了一个REST API来控制应用服务和查询应用信息。具体表现如下:
Web UI方式: Flink提供了一个web UI来观察、监视和调试正在运行的应用服务。并且还可以执行或取消组件或任务的执行。 日志集成服务:Flink实现了流行的slf4j日志接口,并与日志框架log4jlogback集成。 指标服务: Flink提供了一个复杂的度量系统来收集和报告系统和用户定义的度量指标信息。度量信息可以导出到多个报表组件服务,包括 JMX, Ganglia, Graphite, Prometheus, StatsD, Datadog, Slf4j. 标准的WEB REST API接口服务: Flink提供多种REST API接口,有提交新应用程序、获取正在运行的应用程序的Savepoint服务信息、取消应用服务等接口。REST API还提供元数据信息和已采集的运行中或完成后的应用服务的指标信息。 `}),e.add({id:9,href:"/zh/documentation/flink-kubernetes-operator-master/",title:"Kubernetes Operator Main (snapshot)",section:"Documentation",content:" Flink Kubernetes Operator documentation (latest snapshot) # You can find the Flink Kubernetes Operator documentation for the latest snapshot here. "}),e.add({id:10,href:"/zh/getting-started/with-flink-ml/",title:"With Flink ML",section:"教程",content:" Getting Started with Flink ML # Read how you can get started with Flink ML here. "}),e.add({id:11,href:"/zh/what-is-flink/use-cases/",title:"应用场景",section:"About",content:` 应用场景 # Apache Flink 功能强大,支持开发和运行多种不同种类的应用程序。它的主要特性包括:批流一体化、精密的状态管理、事件时间支持以及精确一次的状态一致性保障等。Flink 不仅可以运行在包括 YARN MesosKubernetes 在内的多种资源管理框架上,还支持在裸机集群上独立部署。在启用高可用选项的情况下,它不存在单点失效问题。事实证明,Flink 已经可以扩展到数千核心,其状态可以达到 TB 级别,且仍能保持高吞吐、低延迟的特性。世界各地有很多要求严苛的流处理应用都运行在 Flink 之上。
接下来我们将介绍 Flink 常见的几类应用并给出相关实例链接。
事件驱动型应用 数据分析应用 数据管道应用 事件驱动型应用 # 什么是事件驱动型应用? # 事件驱动型应用是一类具有状态的应用,它从一个或多个事件流提取数据,并根据到来的事件触发计算、状态更新或其他外部动作。
事件驱动型应用是在计算存储分离的传统应用基础上进化而来。在传统架构中,应用需要读写远程事务型数据库。
相反,事件驱动型应用是基于状态化流处理来完成。在该设计中,数据和计算不会分离,应用只需访问本地(内存或磁盘)即可获取数据。系统容错性的实现依赖于定期向远程持久化存储写入 checkpoint。下图描述了传统应用和事件驱动型应用架构的区别。
事件驱动型应用的优势? # 事件驱动型应用无须查询远程数据库,本地数据访问使得它具有更高的吞吐和更低的延迟。而由于定期向远程持久化存储的 checkpoint 工作可以异步、增量式完成,因此对于正常事件处理的影响甚微。事件驱动型应用的优势不仅限于本地数据访问。传统分层架构下,通常多个应用会共享同一个数据库,因而任何对数据库自身的更改(例如:由应用更新或服务扩容导致数据布局发生改变)都需要谨慎协调。反观事件驱动型应用,由于只需考虑自身数据,因此在更改数据表示或服务扩容时所需的协调工作将大大减少。
Flink 如何支持事件驱动型应用? # 事件驱动型应用会受制于底层流处理系统对时间和状态的把控能力,Flink 诸多优秀特质都是围绕这些方面来设计的。它提供了一系列丰富的状态操作原语,允许以精确一次的一致性语义合并海量规模(TB 级别)的状态数据。此外,Flink 还支持事件时间和自由度极高的定制化窗口逻辑,而且它内置的 ProcessFunction 支持细粒度时间控制,方便实现一些高级业务逻辑。同时,Flink 还拥有一个复杂事件处理(CEP)类库,可以用来检测数据流中的模式。
Flink 中针对事件驱动应用的明星特性当属 savepointSavepoint 是一个一致性的状态映像,它可以用来初始化任意状态兼容的应用。在完成一次 savepoint 后,即可放心对应用升级或扩容,还可以启动多个版本的应用来完成 A/B 测试。
典型的事件驱动型应用实例 # 反欺诈 异常检测 基于规则的报警 业务流程监控 (社交网络)Web 应用 数据分析应用 # 什么是数据分析应用? # 数据分析任务需要从原始数据中提取有价值的信息和指标。传统的分析方式通常是利用批查询,或将事件记录下来并基于此有限数据集构建应用来完成。为了得到最新数据的分析结果,必须先将它们加入分析数据集并重新执行查询或运行应用,随后将结果写入存储系统或生成报告。
借助一些先进的流处理引擎,还可以实时地进行数据分析。和传统模式下读取有限数据集不同,流式查询或应用会接入实时事件流,并随着事件消费持续产生和更新结果。这些结果数据可能会写入外部数据库系统或以内部状态的形式维护。仪表展示应用可以相应地从外部数据库读取数据或直接查询应用的内部状态。
如下图所示,Apache Flink 同时支持流式及批量分析应用。
流式分析应用的优势? # 和批量分析相比,由于流式分析省掉了周期性的数据导入和查询过程,因此从事件中获取指标的延迟更低。不仅如此,批量查询必须处理那些由定期导入和输入有界性导致的人工数据边界,而流式查询则无须考虑该问题。
另一方面,流式分析会简化应用抽象。批量查询的流水线通常由多个独立部件组成,需要周期性地调度提取数据和执行查询。如此复杂的流水线操作起来并不容易,一旦某个组件出错将会影响流水线的后续步骤。而流式分析应用整体运行在 Flink 之类的高端流处理系统之上,涵盖了从数据接入到连续结果计算的所有步骤,因此可以依赖底层引擎提供的故障恢复机制。
Flink 如何支持数据分析类应用? # Flink 为持续流式分析和批量分析都提供了良好的支持。具体而言,它内置了一个符合 ANSI 标准的 SQL 接口,将批、流查询的语义统一起来。无论是在记录事件的静态数据集上还是实时事件流上,相同 SQL 查询都会得到一致的结果。同时 Flink 还支持丰富的用户自定义函数,允许在 SQL 中执行定制化代码。如果还需进一步定制逻辑,可以利用 Flink DataStream API DataSet API 进行更低层次的控制。
典型的数据分析应用实例 # 电信网络质量监控 移动应用中的产品更新及实验评估分析 消费者技术中的实时数据即席分析 大规模图分析 数据管道应用 # 什么是数据管道? # 提取-转换-加载(ETL)是一种在存储系统之间进行数据转换和迁移的常用方法。ETL 作业通常会周期性地触发,将数据从事务型数据库拷贝到分析型数据库或数据仓库。
数据管道和 ETL 作业的用途相似,都可以转换、丰富数据,并将其从某个存储系统移动到另一个。但数据管道是以持续流模式运行,而非周期性触发。因此它支持从一个不断生成数据的源头读取记录,并将它们以低延迟移动到终点。例如:数据管道可以用来监控文件系统目录中的新文件,并将其数据写入事件日志;另一个应用可能会将事件流物化到数据库或增量构建和优化查询索引。
下图描述了周期性 ETL 作业和持续数据管道的差异。
数据管道的优势? # 和周期性 ETL 作业相比,持续数据管道可以明显降低将数据移动到目的端的延迟。此外,由于它能够持续消费和发送数据,因此用途更广,支持用例更多。
Flink 如何支持数据管道应用? # 很多常见的数据转换和增强操作可以利用 Flink SQL 接口(或 Table API)及用户自定义函数解决。如果数据管道有更高级的需求,可以选择更通用的 DataStream API 来实现。Flink 为多种数据存储系统(如:KafkaKinesisElasticsearchJDBC数据库系统等)内置了连接器。同时它还提供了文件系统的连续型数据源及数据汇,可用来监控目录变化和以时间分区的方式写入文件。
典型的数据管道应用实例 # 电子商务中的实时查询索引构建 电子商务中的持续 ETL `}),e.add({id:12,href:"/zh/documentation/flink-cdc-stable/",title:"CDC $FlinkCDCStableShortVersion (stable)",section:"Documentation",content:" Flink CDC documentation (latest stable release) # You can find the Flink CDC documentation for the latest stable release here. "}),e.add({id:13,href:"/zh/downloads/",title:"Downloads",section:"Apache Flink Documentation",content:` Apache Flink® Downloads # Apache Flink # Apache Flink® 1.19.0 是我们最新的稳定版本。
Apache Flink 1.19.0 # Apache Flink 1.19.0 (asc, sha512)
Apache Flink 1.19.0 Source Release (asc, sha512)
Release Notes # Please have a look at the Release Notes for Apache Flink 1.19.0 if you plan to upgrade your Flink setup from a previous version.
Apache Flink 1.18.1 # Apache Flink 1.18.1 (asc, sha512)
Apache Flink 1.18.1 Source Release (asc, sha512)
Release Notes # Please have a look at the Release Notes for Apache Flink 1.18.1 if you plan to upgrade your Flink setup from a previous version.
Apache Flink 1.17.2 # Apache Flink 1.17.2 (asc, sha512)
Apache Flink 1.17.2 Source Release (asc, sha512)
Release Notes # Please have a look at the Release Notes for Apache Flink 1.17.2 if you plan to upgrade your Flink setup from a previous version.
Apache Flink 1.16.3 # Apache Flink 1.16.3 (asc, sha512)
Apache Flink 1.16.3 Source Release (asc, sha512)
Release Notes # Please have a look at the Release Notes for Apache Flink 1.16.3 if you plan to upgrade your Flink setup from a previous version.
Apache Flink connectors # These are connectors that are released separately from the main Flink releases.
Apache Flink AWS Connectors 4.2.0 # Apache Flink AWS Connectors 4.2.0 Source Release (asc, sha512)
This component is compatible with Apache Flink version(s):
1.17.x
1.18.x
Apache Flink Cassandra Connector 3.1.0 # Apache Flink Cassandra Connector 3.1.0 Source Release (asc, sha512)
This component is compatible with Apache Flink version(s):
1.16.x
1.17.x
Apache Flink Elasticsearch Connector 3.0.1 # Apache Flink Elasticsearch Connector 3.0.1 Source Release (asc, sha512)
This component is compatible with Apache Flink version(s):
1.16.x
1.17.x
Apache Flink Google Cloud PubSub Connector 3.0.2 # Apache Flink Google Cloud PubSub Connector 3.0.2 Source Release (asc, sha512)
This component is compatible with Apache Flink version(s):
1.17.x
1.18.x
Apache Flink HBase Connector 3.0.0 # Apache Flink HBase Connector 3.0.0 Source Release (asc, sha512)
This component is compatible with Apache Flink version(s):
1.16.x
1.17.x
Apache Flink JDBC Connector 3.1.2 # Apache Flink JDBC Connector 3.1.2 Source Release (asc, sha512)
This component is compatible with Apache Flink version(s):
1.16.x
1.17.x
1.18.x
Apache Flink Kafka Connector 3.1.0 # Apache Flink Kafka Connector 3.1.0 Source Release (asc, sha512)
This component is compatible with Apache Flink version(s):
1.17.x
1.18.x
Apache Flink MongoDB Connector 1.1.0 # Apache Flink MongoDB Connector 1.1.0 Source Release (asc, sha512)
This component is compatible with Apache Flink version(s):
1.17.x
1.18.x
Apache Flink Opensearch Connector 1.1.0 # Apache Flink Opensearch Connector 1.1.0 Source Release (asc, sha512)
This component is compatible with Apache Flink version(s):
1.17.x
1.18.x
Apache Flink Pulsar Connector 3.0.1 # Apache Flink Pulsar Connector 3.0.1 Source Release (asc, sha512)
This component is compatible with Apache Flink version(s):
1.16.x Apache Flink Pulsar Connector 4.1.0 # Apache Flink Pulsar Connector 4.1.0 Source Release (asc, sha512)
This component is compatible with Apache Flink version(s):
1.17.x
1.18.x
Apache Flink RabbitMQ Connector 3.0.1 # Apache Flink RabbitMQ Connector 3.0.1 Source Release (asc, sha512)
This component is compatible with Apache Flink version(s):
1.16.x
1.17.x
Apache Flink Stateful Functions # Apache Flink® Stateful Functions 3.3 是我们最新的稳定版本。
Apache Flink Stateful Functions 3.3.0 # Apache Flink Stateful Functions 3.3.0 Source Release (asc, sha512)
This component is compatible with Apache Flink version(s):
1.16.2 Apache Flink ML # Apache Flink® ML 2.3 是我们最新的稳定版本。
Apache Flink ML 2.3.0 # Apache Flink ML 2.3.0 Source Release (asc, sha512)
Apache Flink ML 2.3.0 Python Source Release (asc, sha512)
This component is compatible with Apache Flink version(s):
1.17.* Apache Flink ML 2.2.0 # Apache Flink ML 2.2.0 Source Release (asc, sha512)
Apache Flink ML 2.2.0 Python Source Release (asc, sha512)
This component is compatible with Apache Flink version(s):
1.15.* Apache Flink Kubernetes Operator # Apache Flink® Kubernetes Operator 1.8 是我们最新的稳定版本。
Apache Flink Kubernetes Operator 1.8.0 # Apache Flink Kubernetes Operator 1.8.0 Source Release (asc, sha512)
This component is compatible with Apache Flink version(s):
1.18.x
1.17.x
1.16.x
1.15.x
Apache Flink Kubernetes Operator 1.7.0 # Apache Flink Kubernetes Operator 1.7.0 Source Release (asc, sha512)
This component is compatible with Apache Flink version(s):
1.18.x
1.17.x
1.16.x
1.15.x
额外组件 # 其他不包含在 Flink 的主要发布的组件如下所示:
Pre-bundled Hadoop 2.8.3 # Pre-bundled Hadoop 2.8.3 Source Release (asc, sha512)
Pre-bundled Hadoop 2.7.5 # Pre-bundled Hadoop 2.7.5 Source Release (asc, sha512)
Pre-bundled Hadoop 2.6.5 # Pre-bundled Hadoop 2.6.5 Source Release (asc, sha512)
Pre-bundled Hadoop 2.4.1 # Pre-bundled Hadoop 2.4.1 Source Release (asc, sha512)
Apache Flink-shaded 18.0 Source Release # Apache Flink-shaded 18.0 Source Release Source Release (asc, sha512)
Apache Flink-shaded 17.0 Source Release # Apache Flink-shaded 17.0 Source Release Source Release (asc, sha512)
Apache Flink-shaded 16.2 Source Release # Apache Flink-shaded 16.2 Source Release Source Release (asc, sha512)
Apache Flink-connector-parent 1.1.0 Source release # Apache Flink-connector-parent 1.1.0 Source release Source Release (asc, sha512)
验证哈希和签名 # 随着每次版本发布,我们还提供了包含 sha512 哈希的 *.sha512 文件和包含加密签名的 *.asc 文件。Apache 软件基金会有一个通用的教程来验证哈希和签名,你可以使用这些版本签名的 KEYS 来校验它们。
Maven 依赖 # Apache Flink # 你只要将以下依赖项添加到 pom.xml 中,就能在项目中引入 Apache Flink 。这些依赖项包含了本地执行环境,因此支持本地测试。
Scala API: 为了使用 Scala API,将 flink-java artifact id 替换为 flink-scala_2.12 ,同时将 flink-streaming-java 替换为 flink-streaming-scala_2.12 <dependency> <groupId>org.apache.flink</groupId> <artifactId>flink-java</artifactId> <version>1.19.0</version> </dependency> <dependency> <groupId>org.apache.flink</groupId> <artifactId>flink-streaming-java</artifactId> <version>1.19.0</version> </dependency> <dependency> <groupId>org.apache.flink</groupId> <artifactId>flink-clients</artifactId> <version>1.19.0</version> </dependency> Apache Flink Stateful Functions # 用户可以在 pom.xml 中包含以下依赖来在项目中使用 Apache Flink Stateful Functions
<dependency> <groupId>org.apache.flink</groupId> <artifactId>statefun-sdk</artifactId> <version>3.3.0</version> </dependency> <dependency> <groupId>org.apache.flink</groupId> <artifactId>statefun-flink-harness</artifactId> <version>3.3.0</version> </dependency> 本地开发程序仅需要依赖 statefun-sdkstatefun-flink-harness 提供了在 IDE 中测试用户开发的程序的本地执行环境。
Apache Flink ML # 用户需要在 pom.xml 中添加如下依赖来使在项目中使用 Apache Flink ML
<dependency> <groupId>org.apache.flink</groupId> <artifactId>flink-ml-core</artifactId> <version>2.3.0</version> </dependency> <dependency> <groupId>org.apache.flink</groupId> <artifactId>flink-ml-iteration</artifactId> <version>2.3.0</version> </dependency> <dependency> <groupId>org.apache.flink</groupId> <artifactId>flink-ml-lib</artifactId> <version>2.3.0</version> </dependency> 高级用户可以根据使用场景来只包含最小集合的依赖:
依赖组件 flink-ml-core 来开发不使用迭代的自定义机器学习算法。 依赖组件 flink-ml-core flink-ml-iteration 来开发使用迭代的自定义机器学习算法。 依赖组件 flink-ml-lib 来使用 Flink ML 提供的机器学习算法。 Apache Flink Kubernetes Operator # You can add the following dependencies to your pom.xml to include Apache Flink Kubernetes Operator in your project.
<dependency> <groupId>org.apache.flink</groupId> <artifactId>flink-kubernetes-operator</artifactId> <version>1.8.0</version> </dependency> 旧版本的更新策略 # 截至20173月,Flink 社区决定使用 bugfix 来支持当前和之前的次要版本。如果 1.2.x 是当前的正式版本,则 1.1.y 是之前的次要支持版本。这两个版本都将收到关键问题的 bugfix
As of March 2023, the Flink community decided that upon release of a new Flink minor version, the community will perform one final bugfix release for resolved critical/blocker issues in the Flink minor version losing support. If 1.16.1 is the current release and 1.15.4 is the latest previous patch version, once 1.17.0 is released we will create a 1.15.5 to flush out any resolved critical/blocker issues.
请注意,社区始终愿意讨论旧版本的 bugfix 版本。请在 dev@flink.apache.org 邮件列表中与开发人员联系。
所有稳定版本 # 所有的 Flink 版本均可通过 https://archive.apache.org/dist/flink/ 获得,包括校验和加密签名。在撰写本文时,这包括以下版本:
Apache Flink # Apache Flink 1.19.0 - 2024-03-18 (Source, Binaries, Docs, Javadocs, Scaladocs ) Apache Flink 1.18.1 - 2024-01-19 (Source, Binaries, Docs, Javadocs, Scaladocs ) Apache Flink 1.18.0 - 2023-10-25 (Source, Binaries, Docs, Javadocs, Scaladocs ) Apache Flink 1.17.2 - 2023-11-29 (Source, Binaries, Docs, Javadocs, Scaladocs ) Apache Flink 1.17.1 - 2023-05-25 (Source, Binaries, Docs, Javadocs, Scaladocs ) Apache Flink 1.17.0 - 2023-03-23 (Source, Binaries, Docs, Javadocs, Scaladocs ) Apache Flink 1.16.3 - 2023-11-20 (Source, Binaries, Docs, Javadocs, Scaladocs ) Apache Flink 1.16.2 - 2023-05-25 (Source, Binaries, Docs, Javadocs, Scaladocs ) Apache Flink 1.16.1 - 2023-01-30 (Source, Binaries, Docs, Javadocs, Scaladocs ) Apache Flink 1.16.0 - 2022-10-28 (Source, Binaries, Docs, Javadocs, Scaladocs ) Apache Flink 1.15.4 - 2023-03-15 (Source, Binaries, Docs, Javadocs, Scaladocs ) Apache Flink 1.15.3 - 2022-11-10 (Source, Binaries, Docs, Javadocs, Scaladocs ) Apache Flink 1.15.2 - 2022-08-24 (Source, Binaries, Docs, Javadocs, Scaladocs ) Apache Flink 1.15.1 - 2022-07-06 (Source, Binaries, Docs, Javadocs, Scaladocs ) Apache Flink 1.15.0 - 2022-05-05 (Source, Binaries, Docs, Javadocs, Scaladocs ) Apache Flink 1.14.6 - 2022-09-28 (Source, Binaries, Docs, Javadocs, Scaladocs ) Apache Flink 1.14.5 - 2022-06-22 (Source, Binaries, Docs, Javadocs, Scaladocs ) Apache Flink 1.14.4 - 2022-03-02 (Source, Binaries, Docs, Javadocs, Scaladocs ) Apache Flink 1.14.3 - 2022-01-17 (Source, Binaries, Docs, Javadocs, Scaladocs ) Apache Flink 1.14.2 - 2021-12-16 (Source, Binaries, Docs, Javadocs, Scaladocs ) Apache Flink 1.14.0 - 2021-09-29 (Source, Binaries, Docs, Javadocs, Scaladocs ) Apache Flink 1.13.6 - 2022-02-18 (Source, Binaries, Docs, Javadocs, Scaladocs ) Apache Flink 1.13.5 - 2021-12-16 (Source, Binaries, Docs, Javadocs, Scaladocs ) Apache Flink 1.13.3 - 2021-10-19 (Source, Binaries, Docs, Javadocs, Scaladocs ) Apache Flink 1.13.2 - 2021-08-02 (Source, Binaries, Docs, Javadocs, Scaladocs ) Apache Flink 1.13.1 - 2021-05-28 (Source, Binaries, Docs, Javadocs, Scaladocs ) Apache Flink 1.13.0 - 2021-04-30 (Source, Binaries, Docs, Javadocs, Scaladocs ) Apache Flink 1.12.7 - 2021-12-16 (Source, Binaries, Docs, Javadocs, Scaladocs ) Apache Flink 1.12.5 - 2021-08-06 (Source, Binaries, Docs, Javadocs, Scaladocs ) Apache Flink 1.12.4 - 2021-05-21 (Source, Binaries, Docs, Javadocs, Scaladocs ) Apache Flink 1.12.3 - 2021-04-29 (Source, Binaries, Docs, Javadocs, Scaladocs ) Apache Flink 1.12.2 - 2021-03-03 (Source, Binaries, Docs, Javadocs, Scaladocs ) Apache Flink 1.12.1 - 2021-01-19 (Source, Binaries, Docs, Javadocs, Scaladocs ) Apache Flink 1.12.0 - 2020-12-08 (Source, Binaries, Docs, Javadocs, Scaladocs ) Apache Flink 1.11.6 - 2021-12-16 (Source, Binaries, Docs, Javadocs, Scaladocs ) Apache Flink 1.11.4 - 2021-08-09 (Source, Binaries, Docs, Javadocs, Scaladocs ) Apache Flink 1.11.3 - 2020-12-18 (Source, Binaries, Docs, Javadocs, Scaladocs ) Apache Flink 1.11.2 - 2020-09-17 (Source, Binaries, Docs, Javadocs, Scaladocs ) Apache Flink 1.11.1 - 2020-07-21 (Source, Binaries, Docs, Javadocs, Scaladocs ) Apache Flink 1.11.0 - 2020-07-06 (Source, Binaries, Docs, Javadocs, Scaladocs ) Apache Flink 1.10.3 - 2021-01-29 (Source, Binaries, Docs, Javadocs, Scaladocs ) Apache Flink 1.10.2 - 2020-08-25 (Source, Binaries, Docs, Javadocs, Scaladocs ) Apache Flink 1.10.1 - 2020-05-12 (Source, Binaries, Docs, Javadocs, Scaladocs ) Apache Flink 1.10.0 - 2020-02-11 (Source, Binaries, Docs, Javadocs, Scaladocs ) Apache Flink 1.9.3 - 2020-04-24 (Source, Binaries, Docs, Javadocs, Scaladocs ) Apache Flink 1.9.2 - 2020-01-30 (Source, Binaries, Docs, Javadocs, Scaladocs ) Apache Flink 1.9.1 - 2019-10-18 (Source, Binaries, Docs, Javadocs, Scaladocs ) Apache Flink 1.9.0 - 2019-08-22 (Source, Binaries, Docs, Javadocs, Scaladocs ) Apache Flink 1.8.3 - 2019-12-11 (Source, Binaries, Docs, Javadocs, Scaladocs ) Apache Flink 1.8.2 - 2019-09-11 (Source, Binaries, Docs, Javadocs, Scaladocs ) Apache Flink 1.8.1 - 2019-07-02 (Source, Binaries, Docs, Javadocs, Scaladocs ) Apache Flink 1.8.0 - 2019-04-09 (Source, Binaries, Docs, Javadocs, Scaladocs ) Apache Flink 1.7.2 - 2019-02-15 (Source, Binaries, Docs, Javadocs, Scaladocs ) Apache Flink 1.7.1 - 2018-12-21 (Source, Binaries, Docs, Javadocs, Scaladocs ) Apache Flink 1.7.0 - 2018-11-30 (Source, Binaries, Docs, Javadocs, Scaladocs ) Apache Flink 1.6.4 - 2019-02-25 (Source, Binaries, Docs, Javadocs, Scaladocs ) Apache Flink 1.6.3 - 2018-12-22 (Source, Binaries, Docs, Javadocs, Scaladocs ) Apache Flink 1.6.2 - 2018-10-29 (Source, Binaries, Docs, Javadocs, Scaladocs ) Apache Flink 1.6.1 - 2018-09-19 (Source, Binaries, Docs, Javadocs, Scaladocs ) Apache Flink 1.6.0 - 2018-08-08 (Source, Binaries, Docs, Javadocs, Scaladocs ) Apache Flink 1.5.6 - 2018-12-21 (Source, Binaries, Docs, Javadocs, Scaladocs ) Apache Flink 1.5.5 - 2018-10-29 (Source, Binaries, Docs, Javadocs, Scaladocs ) Apache Flink 1.5.4 - 2018-09-19 (Source, Binaries, Docs, Javadocs, Scaladocs ) Apache Flink 1.5.3 - 2018-08-21 (Source, Binaries, Docs, Javadocs, Scaladocs ) Apache Flink 1.5.2 - 2018-07-31 (Source, Binaries, Docs, Javadocs, Scaladocs ) Apache Flink 1.5.1 - 2018-07-12 (Source, Binaries, Docs, Javadocs, Scaladocs ) Apache Flink 1.5.0 - 2018-05-25 (Source, Binaries, Docs, Javadocs, Scaladocs ) Apache Flink 1.4.2 - 2018-03-08 (Source, Binaries, Docs, Javadocs, Scaladocs ) Apache Flink 1.4.1 - 2018-02-15 (Source, Binaries, Docs, Javadocs, Scaladocs ) Apache Flink 1.4.0 - 2017-11-29 (Source, Binaries, Docs, Javadocs, Scaladocs ) Apache Flink 1.3.3 - 2018-03-15 (Source, Binaries, Docs, Javadocs, Scaladocs ) Apache Flink 1.3.2 - 2017-08-05 (Source, Binaries, Docs, Javadocs, Scaladocs ) Apache Flink 1.3.1 - 2017-06-23 (Source, Binaries, Docs, Javadocs, Scaladocs ) Apache Flink 1.3.0 - 2017-06-01 (Source, Binaries, Docs, Javadocs, Scaladocs ) Apache Flink 1.2.1 - 2017-04-26 (Source, Binaries, Docs, Javadocs, Scaladocs ) Apache Flink 1.2.0 - 2017-02-06 (Source, Binaries, Docs, Javadocs, Scaladocs ) Apache Flink 1.1.5 - 2017-03-22 (Source, Binaries, Docs, Javadocs, Scaladocs ) Apache Flink 1.1.4 - 2016-12-21 (Source, Binaries, Docs, Javadocs, Scaladocs ) Apache Flink 1.1.3 - 2016-10-13 (Source, Binaries, Docs, Javadocs, Scaladocs ) Apache Flink 1.1.2 - 2016-09-05 (Source, Binaries, Docs, Javadocs, Scaladocs ) Apache Flink 1.1.1 - 2016-08-11 (Source, Binaries, Docs, Javadocs, Scaladocs ) Apache Flink 1.1.0 - 2016-08-08 (Source, Binaries, Docs, Javadocs, Scaladocs ) Apache Flink 1.0.3 - 2016-05-12 (Source, Binaries, Docs, Javadocs, Scaladocs ) Apache Flink 1.0.2 - 2016-04-23 (Source, Binaries, Docs, Javadocs, Scaladocs ) Apache Flink 1.0.1 - 2016-04-06 (Source, Binaries, Docs, Javadocs, Scaladocs ) Apache Flink 1.0.0 - 2016-03-08 (Source, Binaries, Docs, Javadocs, Scaladocs ) Apache Flink 0.10.2 - 2016-02-11 (Source, Binaries) Apache Flink 0.10.1 - 2015-11-27 (Source, Binaries) Apache Flink 0.10.0 - 2015-11-16 (Source, Binaries) Apache Flink 0.9.1 - 2015-09-01 (Source, Binaries) Apache Flink 0.9.0 - 2015-06-24 (Source, Binaries) Apache Flink 0.9.0-milestone-1 - 2015-04-13 (Source, Binaries) Apache Flink 0.8.1 - 2015-02-20 (Source, Binaries) Apache Flink 0.8.0 - 2015-01-22 (Source, Binaries) Apache Flink 0.7.0-incubating - 2014-11-04 (Source, Binaries) Apache Flink 0.6.1-incubating - 2014-09-26 (Source, Binaries) Apache Flink 0.6-incubating - 2014-08-26 (Source, Binaries) Apache Flink connectors # Flink Elasticsearch Connector 3.0.0 - 2022-11-09 (Source) Flink AWS Connectors 3.0.0 - 2022-11-28 (Source) Flink Cassandra Connector 3.0.0 - 2022-11-30 (Source) Flink AWS Connectors 4.0.0 - 2022-12-09 (Source) Flink Pulsar Connector 3.0.0 - 2022-12-20 (Source) Flink JDBC Connector 3.0.0 - 2022-11-30 (Source) Flink RabbitMQ Connectors 3.0.0 - 2022-12-13 (Source) Flink Opensearch Connector 1.0.0 - 2022-12-21 (Source) Flink Google Cloud PubSub Connector 3.0.0 - 2023-01-31 (Source) Flink MongoDB Connector 1.0.0 - 2023-04-03 (Source) Flink AWS Connectors 4.1.0 - 2023-04-03 (Source) Flink Kafka Connector 3.0.0 - 2023-04-21 (Source) Flink MongoDB Connector 1.0.1 - 2023-04-24 (Source) Flink JDBC Connector 3.1.0 - 2023-05-05 (Source) Flink RabbitMQ Connectors 3.0.1 - 2023-05-08 (Source) Flink Elasticsearch Connector 3.0.1 - 2023-05-08 (Source) Flink Opensearch Connector 1.0.1 - 2023-05-08 (Source) Flink Pulsar Connector 4.0.0 - 2023-05-08 (Source) Flink Google Cloud PubSub Connector 3.0.1 - 2023-05-09 (Source) Flink Cassandra Connector 3.1.0 - 2023-05-25 (Source) Flink Pulsar Connector 3.0.1 - 2023-06-07 (Source) Flink JDBC Connector 3.1.1 - 2023-06-28 (Source) Flink MongoDB Connector 1.0.2 - 2023-08-15 (Source) Flink HBase Connector 3.0.0 - 2023-09-1 (Source) Flink Kafka Connector 3.0.1 - 2023-10-30 (Source) Flink AWS Connectors 4.2.0 - 2023-11-30 (Source) Flink Kafka Connector 3.0.2 - 2023-12-01 (Source) Flink Pulsar Connector 4.1.0 - 2023-12-28 (Source) Flink Google Cloud PubSub Connector 3.0.2 - 2024-01-12 (Source) Flink Opensearch Connector 1.1.0 - 2024-02-01 (Source) Flink Kafka Connector 3.1.0 - 2024-02-07 (Source) Flink MongoDB Connector 1.1.0 - 2024-02-19 (Source) Flink JDBC Connector 3.1.2 - 2024-02-21 (Source) Apache Flink Stateful Functions # Apache Flink Stateful Functions 3.3.0 - 2023-09-19 (Source, Docs, Javadocs) Apache Flink Stateful Functions 3.2.0 - 2022-01-27 (Source, Docs, Javadocs) Apache Flink Stateful Functions 3.1.1 - 2021-12-22 (Source, Docs, Javadocs) Apache Flink Stateful Functions 3.1.0 - 2021-08-30 (Source, Docs, Javadocs) Apache Flink Stateful Functions 3.0.0 - 2021-04-14 (Source, Docs, Javadocs) Apache Flink Stateful Functions 2.2.2 - 2021-01-02 (Source, Docs, Javadocs) Apache Flink Stateful Functions 2.2.1 - 2020-11-09 (Source, Docs, Javadocs) Apache Flink Stateful Functions 2.2.0 - 2020-09-28 (Source, Docs, Javadocs) Apache Flink Stateful Functions 2.1.0 - 2020-06-08 (Source, Docs, Javadocs) Apache Flink Stateful Functions 2.0.0 - 2020-04-02 (Source, Docs, Javadocs) Apache Flink Shaded # Apache Flink Shaded 18.0 - 2024-01-11 (Source) Apache Flink Shaded 17.0 - 2023-05-08 (Source) Apache Flink Shaded 16.2 - 2023-11-17 (Source) Apache Flink Shaded 16.1 - 2022-11-24 (Source) Apache Flink Shaded 16.0 - 2022-10-07 (Source) Apache Flink Shaded 15.0 - 2022-01-21 (Source) Apache Flink Shaded 14.0 - 2021-07-21 (Source) Apache Flink Shaded 13.0 - 2021-04-06 (Source) Apache Flink Shaded 12.0 - 2020-10-09 (Source) Apache Flink Shaded 11.0 - 2020-05-29 (Source) Apache Flink Shaded 10.0 - 2020-02-17 (Source) Apache Flink Shaded 9.0 - 2019-11-23 (Source) Apache Flink Shaded 8.0 - 2019-08-28 (Source) Apache Flink Shaded 7.0 - 2019-05-30 (Source) Apache Flink Shaded 6.0 - 2019-02-12 (Source) Apache Flink Shaded 5.0 - 2018-10-15 (Source) Apache Flink Shaded 4.0 - 2018-06-06 (Source) Apache Flink Shaded 3.0 - 2018-02-28 (Source) Apache Flink Shaded 2.0 - 2017-10-30 (Source) Apache Flink Shaded 1.0 - 2017-07-27 (Source) Apache Flink ML # Apache Flink ML 2.3.0 - 2023-07-01 (Source) Apache Flink ML 2.2.0 - 2023-04-19 (Source) Apache Flink ML 2.1.0 - 2022-07-12 (Source) Apache Flink ML 2.0.0 - 2021-01-07 (Source) Apache Flink Kubernetes Operator # Apache Flink Kubernetes Operator 1.8.0 - 2024-03-21 (Source, Helm Chart) Apache Flink Kubernetes Operator 1.7.0 - 2023-11-22 (Source, Helm Chart) Apache Flink Kubernetes Operator 1.6.1 - 2023-10-27 (Source, Helm Chart) Apache Flink Kubernetes Operator 1.6.0 - 2023-08-15 (Source, Helm Chart) Apache Flink Kubernetes Operator 1.5.0 - 2023-05-17 (Source, Helm Chart) Apache Flink Kubernetes Operator 1.4.0 - 2023-02-22 (Source, Helm Chart) Apache Flink Kubernetes Operator 1.3.1 - 2023-01-10 (Source, Helm Chart) Apache Flink Kubernetes Operator 1.3.0 - 2022-12-14 (Source, Helm Chart) Apache Flink Kubernetes Operator 1.2.0 - 2022-10-05 (Source, Helm Chart) Apache Flink Kubernetes Operator 1.1.0 - 2022-07-25 (Source, Helm Chart) Apache Flink Kubernetes Operator 1.0.1 - 2022-06-27 (Source, Helm Chart) Apache Flink Kubernetes Operator 1.0.0 - 2022-06-04 (Source, Helm Chart) Apache Flink Kubernetes Operator 0.1.0 - 2022-04-02 (Source, Helm Chart) Apache Flink Table Store # Apache Flink Table Store 0.3.0 - 2023-01-13 (Source, Binaries) Apache Flink Table Store 0.2.0 - 2022-08-29 (Source, Binaries) Apache Flink Table Store 0.1.0 - 2022-05-11 (Source, Binaries) `}),e.add({id:14,href:"/zh/what-is-flink/powered-by/",title:"Flink 用户",section:"About",content:` Powered By Flink # Apache Flink 为全球许多公司和企业的关键业务提供支持。在这个页面上,我们展示了一些著名的 Flink 用户,他们在生产中运行着有意思的用例,并提供了展示更详细信息的链接。
在项目的 wiki 页面中有一个 谁在使用 Flink 的页面,展示了更多的 Flink 用户。请注意,该列表并不全面。我们只添加明确要求列出的用户。
如果你希望加入此页面,请通过 Flink 用户邮件列表 告诉我们。
全球最大的零售商阿里巴巴(Alibaba)使用 Flink 的分支版本 Blink 来优化实时搜索排名。 阅读更多有关 Flink 在阿里巴巴扮演角色的信息 Amazon Managed Service for Apache Flink 是一项完全托管的 Amazon 服务;可以让您能够使用Apache Flink来处理和分析流数据。 BetterCloud 是一个多 SaaS 管理平台,它使用 Flink SaaS 应用程序活动中获取近乎实时的智能。 请参阅 BetterCloud Flink Forward SF 2017 上的分享 Bouygues Telecom 正在运行由 Flink 提供支持的 30 个生产应用程序,每天处理 100 亿个原始事件。 请参阅 Bouygues Telecom Flink Forward 2016 上的分享 财富 500 强金融服务公司 Capital One 使用 Flink 进行实时活动监控和报警。 了解 Capital One 的欺诈检测用例 康卡斯特(Comcast)是一家全球媒体和技术公司,它使用 Flink 来实现机器学习模型和近实时事件流处理。 了解 Flink 在康卡斯特的应用 Criteo 是开放互联网的广告平台,使用 Flink 进行实时收入监控和近实时事件处理。 了解 Criteo Flink 用例 滴滴出行是全球卓越的移动出行平台,使用 Apache Flink支持了实时监控、实时特征抽取、实时ETL等业务。 了解滴滴如何使用 Flink 的。 Drivetribe是由前“Top Gear”主持人创建的数字社区,它使用 Flink 作为指标和内容推荐。 了解 Flink Drivetribe stack 的应用 Ebay 的监控平台由 Flink 提供支持,可在指标和日志流上计算上千条自定义报警规则。 了解更多 Flink Ebay 的信息 爱立信使用 Flink 构建了一个实时异常检测器,通过大型基础设施进行机器学习。 阅读关于O’Reilly想法的详细概述 Gojek 是一个超级 App: 拥有超过20种服务,并使用 Flink 为其自助平台提供支持,从而实现跨功能的数据驱动决策。 更多信息请访问 Gojek 工程师博客 华为是全球领先的 ICT 基础设施和智能设备供应商。华为云提供基于 Flink 的云服务。 了解Flink 如何为云服务提供动力 KingCandy Crush Saga的创建者,使用 Flink 为数据科学团队提供实时分析仪表板。 阅读 King Flink 实现 Klaviyo使用 Apache Flink 扩展其实时分析系统,该系统每秒对超过一百万个事件进行重复数据删除和聚合。 阅读 Klaviyo 的实时分析 快手是中国领先的短视频分享 App,使用了 Apache Flink 搭建了一个实时监控平台,监控短视频和直播的质量。 阅读 Flink 在快手的应用实践 Lyft 使用 Flink 作为其流媒体平台的处理引擎,例如为机器学习持续生成特征。 阅读更多关于 Lyft 的流媒体 MediaMath 是一家程序化营销公司,它使用 Flink 为其实时报告基础架构提供支持。 请参阅 MediaMath Flink Forward SF 2017 上的分享 Mux 是一家流媒体视频提供商的分析公司,它使用 Flink 进行实时异常检测和报警。 详细了解 Mux 如何使用 Flink OPPO, 作为中国最大的手机厂商之一,利用 Apache Flink 构建了实时数据仓库,用于即时分析运营活动效果及用户短期兴趣。 了解 OPPO 如何使用 Flink 全球第二大在线零售商奥托集团(Otto Group)使用 Flink 进行商业智能流处理。 请参阅 Otto Flink Forward 2016 上的分享 OVH 使用 Flink 开发面向流的应用程序,比如实时商业智能系统或警报系统。 详细了解 OVH 如何使用 Flink Pinterest 使用基于 Apache Flink 的实时实验分析平台每天进行上千次的实验。 阅读更多在 Pinterest 有关实时实验分析的信息 Razorpay 是印度最大的支付门户网站之一,使用 Flink 构建了自己的内部平台 Mitra,用以扩展 AI 特征生成和实时模型服务。 阅读更多在 Razorpay 有关 Flink 数据分析的信息 ResearchGate 是科学家的社交网络,它使用 Flink 进行网络分析和近似重复检测。 请参阅 ResearchGate Flink Forward 2016 上的分享 三星(SK telecom)是韩国最大的无线运营商。它在很多应用中使用了 Flink,包括智能工厂和移动应用程序。 了解其中一个 SK telecom 的使用案例。 Telefónica NEXT TÜV 认证数据匿名平台由 Flink 提供支持。 了解更多关于 Telefónica NEXT 的信息 作为最大的互联网公司之一,腾讯利用 Apache Flink 构建了一个内部平台,以提高开发和操作实时应用程序的效率。 阅读有关腾讯平台的更多信息。 Uber Apache Flink 上构建了基于 SQL 的开源流媒体分析平台 AthenaX 更多信息请访问Uber工程博客 Vip,中国最大的品牌特卖网站之一,应用Flink实时的将数据流ETLHive中用于数据处理和分析. 详细了解Vip如何使用 Flink 小米,作为中国最大的专注于硬件与软件开发的公司之一,利用 Flink 构建了一个内部平台,以提高开发运维实时应用程序的效率,并用于实时推荐等场景。 详细了解小米如何使用 Flink 的。 Yelp 利用 Flink 为其数据连接器生态系统和流处理基础架构提供支持。 请参阅 Flink Forward 上的演讲 Zalando 是欧洲最大的电子商务公司之一,它使用 Flink 进行实时过程监控和 ETL 更多信息请访问 Zalando 技术博客 `}),e.add({id:15,href:"/zh/getting-started/with-flink-stateful-functions/",title:"With Flink Stateful Functions",section:"教程",content:" Getting Started with Flink Stateful Functions # Read how you can get started with Flink Stateful Functions here. "}),e.add({id:16,href:"/zh/documentation/flink-cdc-master/",title:"CDC Master (snapshot)",section:"Documentation",content:" Flink CDC documentation (latest snapshot) # You can find the Flink CDC documentation for the latest snapshot here. "}),e.add({id:17,href:"/zh/getting-started/training-course/",title:"Training Course",section:"教程",content:" Training Course # Read all about the Flink Training Course here. "}),e.add({id:18,href:"/zh/what-is-flink/roadmap/",title:"开发计划",section:"About",content:` Roadmap # 导读: 此计划路线图旨在对Flink社区当前正在进行的项目进行总结摘要,并对这些项目根据工作内容进行分组。 鉴于Flink每个分组中现在都有非常多的工作正在进行,我们希望此计划书有助于用户和贡献者理解每个项目乃至于整个Flink的未来方向。 这个计划书既涵盖刚起步的项目,也包括接近完成的项目,这样可以使大家更好地了解各项目的发展方向以及当前的进展。
关于各个项目更多的细节讨论和其他较小的改动记录在 FLIPs
路线图会不断更新。一旦达成共识,新的特性和工作都会添加到路线图中。 这里的共识是指这些特性和工作将来确定会发生,以及这些工作对于用户来说大致是什么样的。
Last Update: 2023-09-01
功能图谱 # 功能图谱旨在为用户提供有关功能成熟度方面的引导,包括哪些功能正在积极推进,哪些功能即将寿终正寝。 如有任何疑问,请联系开发人员邮件列表:dev@flink.apache.org
功能阶段 # MVP: 可以了解一下这个功能,也许在将来对您有所帮助。 Beta: 您可以从中受益,但是您在使用之前应该仔细评估该功能。 Ready and Evolving: 生产可用,但是请注意,将来在升级Flink时,可能需要对您的应用和设置进行一些调整。 Stable: 可以在生产中稳定不受限制地使用。 Approaching End-of-Life: 仍然可以稳定使用,但请考虑替代方法。对于新的长期项目而言,不建议使用。 Deprecated: 不推荐使用,您需要开始寻找替代产品。 Scenarios We Focus On # Batch / Streaming Unification and Mixing # Flink is a streaming data system in its core, that executes batch as a special case of streaming”. Efficient execution of batch jobs is powerful in its own right; but even more so, batch processing capabilities (efficient processing of bounded streams) open the way for a seamless unification of batch and streaming applications. Unified streaming/batch up-levels the streaming data paradigm: It gives users consistent semantics across their real-time and lag-time applications. Furthermore, streaming applications often need to be complemented by batch (bounded stream) processing, for example when reprocessing data after bugs or data quality issues, or when bootstrapping new applications. A unified API and system make this much easier.
Both DataStream API and SQL provide unified API to execute the same application in different modes of batch and streaming. There have been some efforts to make the unification much more seamless, such as unified Source API (FLIP-27) and SinkV2 API (FLIP-191). Beyond unification, we want to go one step further. Our goal is to mix and switch between batch/streaming execution in the future to make it a seamless experience. We have supported checkpointing when some tasks are finished & bounded stream programs shut down with a final checkpoint (FLIP-147). There are initial discussions and designs about jobs with mixed batch/streaming execution, so stay tuned for more news in that area.
Dynamic checkpoint interval for processing bounded stream of historical data and unbounded stream of incremental data (FLIP-309). Event notification mechanism for the boundary of bounded part and unbounded part in a stream. This can unlock many exciting features and improvements, such as FLINK-19830. Bootstrap states using a batch job (bounded stream program) with a final checkpoint, and continue processing with a streaming job (unbounded stream program) from the checkpoint and state. Unified SQL Platform # The community has been building Flink to a powerful basis for a unified (batch and streaming) SQL analytics platform and is continuing to do so.
SQL has very strong cross-batch-streaming semantics, allowing users to use the same queries for ad-hoc analytics and as continuous queries. Flink already contains an efficient unified query engine and a wide set of integrations. With user feedback, those are continuously improved.
Going Beyond a SQL Stream/Batch Processing Engine # The experience of updating Flink SQL based jobs has been rather cumbersome as it could have led to new job graphs making restoring from savepoints/checkpoints impossible. FLIP-190 which already has been shipped as MVP is targeting this. To extend the capability of a stream-batch processing engine and make Flink ready for the unified SQL platform, there is an ongoing effort to allow Flink better manage data and metadata, including DELETE/UPDATE, Call Procedures, rich DDLs, Time Travel, and so on. This is especially useful for building a lakehouse with Flink and Paimon/Iceberg/Hudi. There are some initial discussions to support JSON data type for Flink SQL. This can enable Flink SQL to better analyze semi-structured data and better adapt to NoSQL databases. Platform Infrastructure # After FLIP-163 the community is working again on a set of SQL Client usability improvements (FLIP-189, FLIP-222) which is aiming at improving the user experience when using the SQL client. To simplify the building of production SQL platforms with Flink, we are improving the SQL Gateway component as the service of the Flink SQL platform. There are many ongoing exciting features around it, including supporting application mode (FLIP-316), JDBC driver client (FLIP-293), persisted catalog registration (FLIP-295), authentication, and high availability. Support for Common Languages # Hive syntax compatibility can help users migrate existing Hive SQL tasks to Flink seamlessly, and it is convenient for users who are familiar with Hive syntax to use Hive syntax to write SQL to query tables registered in Flink. Until now, the Hive syntax compatibility has reached 94.1% which is measured using the Hive qtest suite. Flink community is continuously improving the compatibility and execution performance (FLINK-29717). With FLIP-216 theres now the initiative to introduce pluggable SQL dialects on the example of the Hive syntax. It makes Flink easier to support other SQL dialects in the future, for example, Spark SQL and PostgreSQL. Towards Streaming Warehouses # Flink has become the leading technology and factual standard for stream processing. The concept of unifying streaming and batch data processing is gaining recognition and is being successfully implemented in more and more companies. To further unify streaming-batch analytics, Flink has proposed the concept of Streaming Warehouse. This new concept aims to unify not only computation but also storage, ensuring that data flows and is processed in real time. As a result, the data in the warehouse is always up-to-date, and any analytics or insights generated from it reflect the current state of the business. This combines the advantages of traditional data warehouses with real-time insights.
The Apache Flink community initiated the Flink Table Store subproject (FLIP-188) with the vision of streaming-batch unified storage. With the project growing rapidly, Flink Table Store joined the Apache incubator as an independent project called Apache Paimon. Apache Paimon has its own roadmap under the documentation. The unified storage opens the way for Flink to improve the performance and experience of streaming-batch unified applications.
OLAP is an important scenario after Flink streaming-batch data processing, users need an OLAP engine to analyze data in the streaming warehouse. Flink could execute OLAP as a special case of batch and the community is trying to explore the possibility of improvement for short-lived jobs without affecting streaming and batch processing. It is a nice-to-have feature and it will bring great value for users in Flink becoming a unified streaming-batch-OLAP data processing system.
In order to build an efficient streaming warehouse, there are a lot of things that need to be improved in Flink, for example:
Support rich warehouse APIs to manage data and metadata, such as: CTAS/RTAS (FLIP-303), CALL (FLIP-311), TRUNCATE (FLIP-302), and so on. CBO (cost-based optimizations) with statistics in streaming lakehouses for streaming queries. Make full use of the layout and indexes on streaming lakehouse to reduce data reading and processing for streaming queries. Improvements for short-lived jobs to support OLAP queries with low latency and concurrent execution. Engine Evolution # Disaggregated State Management # One major advantage of Flink is its efficient and easy-to-use state management mechanism. However, this mechanism has evolved a little since it was born and is not suitable in the cloud-native era. In the past several releases, weve made significant efforts to improve the procedure of state snapshotting (FLIP-76 unaligned checkpoint, FLIP-158 generic incremental checkpoint) and state repartitioning. In doing so, we gradually find that a lot of problems (slow state snapshotting and state recovery for example) are root-caused by computation and state management bounded together, especially for large jobs with large states. Hence, starting from Flink 2.0, we aim at disaggregating Flink computation and state management and we believe that is more suitable for a modern cloud-native architecture.
In the new design, DFS is played as primary storage. Checkpoints are shareable between operators so we do not need to compute and store multiple copies of the same state table. Queryable state APIs can be provided based on these checkpoints. Compaction and clean-up of state files are not bounded to the same Task manager anymore so we can do better load-balancing and avoid burst CPU and network peaks.
Evolution of Flink APIs # With Flink 2.0 approaching, the community is planning to evolve the APIs of Apache Flink.
We are planning to remove some long deprecated APIs in Flink 2.0, to make Flink move faster, including: The DataSet API, all Scala APIs, the legacy SinkV1 API, the legacy TableSource/TableSink API Deprecated methods / fields / classes in the DataStream API, Table API and REST API Deprecated configuration options and metrics We are also planning to retire the legacy SourceFunction / SinkFunction APIs, and Queryable State API in the long term. This may not happen shortly, as the prerequisites for users to migrate from these APIs are not fully met at the moment. We are aware of some problems of the current DataStream API, such as the exposing of and dependencies on the Flink internal implementations, which requires significant changes to fix. To provide a smooth migration experience, the community is designing a new ProcessFunction API, which aims to gradually replace the DataStream API in the long term. Flink as an Application # The goal of these efforts is to make it feel natural to deploy (long-running streaming) Flink applications. Instead of starting a cluster and submitting a job to that cluster, these efforts support deploying a streaming job as a self-contained application.
For example as a simple Kubernetes deployment; deployed and scaled like a regular application without extra workflows.
There is currently a Flink Kubernetes Operator subproject being developed by the community and has its own roadmap under the documentation. Streaming query as an application. Make SQL Client/Gateway supports submitting SQL jobs in the application mode (FLIP-316). Performance # Continuous work to keep improving the performance of both Flink streaming and batch processing.
Large-Scale Streaming Jobs # Streaming Join is a headache for Flink users because of its large-scale state. The community is putting lots of effort into further improving the performance of streaming join, such as minibatch join, multi-way join, and reducing duplicated states. The community is also continuously improving and working on some other joins, such as unordered async lookup join and processing-time temporal join (FLIP-326). They can be very efficient alternatives for streaming joins. Change data capture and processing with Flink SQL is widely used, and the community is improving cost and performance in this case, e.g. reducing normalize and materialize state. Faster Batch Queries # The community’s goal is to make Flink’s performance on bounded streams (batch use cases) competitive with that of dedicated batch processors. While Flink has been shown to handle some batch processing use cases faster than widely-used batch processors, there are some ongoing efforts to make sure this is the case for broader use cases: The community has introduced Dynamic Partition Pruning (DPP) which aims to minimize I/O costs of the data read from the data sources. There are some ongoing efforts to further reduce the I/O and shuffle costs, such as Runtime Filter (FLIP-324). Operator Fusion CodeGen (FLIP-315) improves the execution performance of a query by fusing an operator DAG into a single optimized operator that eliminates virtual function calls and leverages CPU registers for intermediate data. The community has supported some adaptive batch execution and scheduling (FLIP-187). We are trying to support broader adaptive cases, such as Adaptive Query Execution that makes use of runtime statistics to choose the most efficient query execution plan. The community has started improving scheduler and execution performance (FLINK-25318) for short-lived jobs to support OLAP. Flink executes OLAP as a special case of batch”, we are trying to extend Flink to execute low-latency and currency queries in Session Cluster and users can perform streaming, batch, and OLAP data processing on the unified Flink engine.
Stability # The community is keeping improving the stability of jobs, by better tolerating failures, and speeding up the recovery process.
The instability of the environment is unavoidable. It can lead to a crash of JobManager and TaskManager nodes, or slow data processing. The community has introduced speculative execution (FLIP-168, FLIP-245, FLIP-281) for batch jobs to reduce the impact of problematic machines which slows down data processing.
JobManager node crash is usually unacceptable for a batch job because the job has to be re-run from the very beginning. Therefore, the community is planning to improve the JobManager recovery process to avoid re-run finished stages. Another planned improvement is to retain running tasks when the JobManager node goes down unexpectedly, to further reduce the impact of the JobManager crash. This can also benefit streaming jobs even if they have periodical checkpointing, to avoid interruption or regression of data processing in this case.
Usability # Now and then we hear people say that, while Flink is powerful in functionality, it is not that easy to master. Such voices are heard. The community is working on several efforts to improve the usability of Flink.
We are working on reducing the number of configuration options that users need to specify, as well as making them easier to understand and tune. This includes: Removing options that require in-depth knowledge of Flink internals to understand and use. Making Flink automatically and dynamically decide the proper behavior where possible. Improving the default values of the options so that users need not to touch them in most cases. Improving the definition and description of the options so that they are easier to understand and work with when its necessary.
We have already made some progress along this direction. Flink 1.17 requires less than 10 configurations to achieve well enough performance on TPC-DS. Hybrid shuffle supports dynamically switching between different shuffle modes and decouples its memory footprint from the parallelism of the job.
Developer Experience # Ecosystem # There is almost no use case in which Apache Flink is used on its own. It has established itself as part of many data related reference architectures. In fact youll find the squirrel logo covering several aspects.
All connectors will be hosted in an external repository going forward and many of them have been successfully externalized. See the mailing list thread. Catalog as a first-class citizen. Flink catalog lets users issue batch and streaming queries connecting to external systems without registering DDLs/schemas manually. It is recommended to support Catalog in the highest priority for connectors. The community is working on supporting more catalogs for connectors (e.g. GlueCatalog, SchemaRegistryCatalog). There is ongoing work on introducing more new connectors (e.g. Pinot, Redshift, ClickHouse)
Documentation # There are various dedicated efforts to simplify the maintenance and structure (more intuitive navigation/reading) of the documentation.
Docs Tech Stack: FLIP-157 General Docs Structure: FLIP-42 SQL Docs: FLIP-60 `}),e.add({id:19,href:"/zh/documentation/flinkml-stable/",title:"ML $FlinkMLStableShortVersion (stable)",section:"Documentation",content:" Flink ML documentation (latest stable release) # You can find the Flink ML documentation for the latest stable release here. "}),e.add({id:20,href:"/zh/what-is-flink/community/",title:"社区 & 项目信息",section:"About",content:` 社区 & 项目信息 # 如何从 Apache Flink 获得帮助? # 我们可以通过多种方式从 Apache Flink 社区获得帮助。Flink committer 主要活跃在 邮件列表。对于用户支持和问题咨询,则可以通过 用户邮件列表 获得帮助。你还可以加入社区专属的 Slack。有些 Committer 同时会关注 Stack Overflow。请在提问的时候记得添加 apache-flink 的标签。问题反馈以及新特性的讨论则可以在 开发邮件列表 或者 Jira 上进行讨论。有兴趣对 Flink 进行贡献的人请查阅 贡献指南.
邮件列表 # 名字 订阅 摘要 退订 发送 归档 news@flink.apache.org
Flink 社区的新闻和公告 订阅 订阅 退订 只读邮件列表 归档 community@flink.apache.org
与会议,博客以及工作机会相关的更广泛的社区讨论 订阅 订阅 退订 发送 归档 user@flink.apache.org
用户支持以及问题咨询邮件列表 订阅 订阅 退订 发送 归档 user-zh@flink.apache.org
中文用户支持以及问题咨询邮件列表 订阅 订阅 退订 发送 归档 dev@flink.apache.org
开发相关讨论 订阅 订阅 退订 发送 归档 builds@flink.apache.org
Flink 主仓库的构建通知 订阅 订阅 退订 只读邮件列表 归档 issues@flink.apache.org
所有 Jira 活动的镜像 订阅 订阅 退订 只读邮件列表 归档 commits@flink.apache.org
仓库的所有 commit 订阅 订阅 退订 只读邮件列表 归档 在给邮件列表发邮件之前,请确认已经订阅了该邮件列表 如果你没有订阅对应的邮件列表的话,对于 dev 邮件列表,你的消息会被拒收,对于 user 邮件列表,你则收不到相应的回复。 如何订阅邮件列表 # 在往邮件列表中发送消息前,需要先订阅邮件列表。
发送一封不包含任何内容或主题的邮件到 listname-subscribe@flink.apache.org(替换 listname dev, user, user-zh 等等) 等待直到收到一封主题为 confirm subscribe to listname@flink.apache.org 的邮件。回复该邮件,不用修改主题和添加邮件内容。 等待直到收到一封主题为 WELCOME to listname@flink.apache.org 的邮件。 如果你的邮件中包含代码,请根据如下要求进行检查:
请确认你所使用的外链不会被修改、删除等,这些操作会使得归档后的邮件变得无效 粘贴文字而不是文字的截图 对代码进行格式化操作,以提高可读性 添加足够的上下文,确保代码没有模棱两可的地方 Slack # 你可以通过 此链接 加入 Apache Flink 社区专属的 Slack 工作空间。 在成功加入后,不要忘记在 #introductions 频道介绍你自己。 Slack 规定每个邀请链接最多可邀请 100 人,如果遇到上述链接失效的情况,请联系 Dev 邮件列表。 所有已经加入社区 Slack 空间的成员同样可以邀请新成员加入。
Slack 空间交流时,请遵守以下规则:
保持尊重 - 这是最重要的规则 所有重要的决定和结论 必须在邮件列表中有所体现。 “没有发生在邮件列表上的事情,即视为没有发生。” - Apache 准则 使用 Slack 消息列(Thread 使频道(Channel)中的多组同时进行的对话保持有序。 Use either #pyflink (for all Python Flink questions) or #troubleshooting (for all other Flink questions). 不要通过私信(Direct Message 要求他人答疑、指派 Jira、审查 PR。这些事务应遵从自愿原则。 注意: 来自我们 Slack 中公共渠道的所有消息都 永久存储并发布 linen.dev 上的 Apache Flink Slack 存档。 这个存档的目的是让搜索引擎在 Flink Slack 中找到过去的讨论。
Stack Overflow # Committer 们会关注 Stack Overflow apache-flink 相关标签的问题。
请确认你为自己的问题打上了正确的标签,从而可以获得 Flink 社区的帮助。
Issue 追踪 # 我们使用 Jira 进行所有代码相关的 issues 追踪 https://issues.apache.org/jira/browse/FLINK。 所有 issue 必须使用英文。
如果您没有ASF JIRA帐户,可以通过ASF自助门户请求新的账户。
所有 issue 的活动也会同步到 issue 邮件列表。
报告安全漏洞 # 如果你希望报告安全漏洞, 请联系 security@apache.org Apache Flink 遵循标准的 Apache漏洞处理流程 来报告漏洞。请注意,在项目做出响应之前,请不要公开披露漏洞。
Meetups # meetup.com 上可以找到很多 Flink 相关的 meetup
源代码 # Main Repositories # Flink Core 仓库
ASF 仓库: https://gitbox.apache.org/repos/asf/flink.git GitHub 镜像: https://github.com/apache/flink.git Flink Docker 仓库
ASF 仓库: https://gitbox.apache.org/repos/asf/flink-docker.git GitHub 镜像: https://github.com/apache/flink-docker.git Flink Stateful Functions 仓库
ASF 仓库: https://gitbox.apache.org/repos/asf/flink-statefun.git GitHub 镜像: https://github.com/apache/flink-statefun Flink Stateful Functions Docker 仓库
ASF 仓库: https://gitbox.apache.org/repos/asf/flink-statefun-docker.git GitHub 镜像: https://github.com/apache/flink-statefun-docker Flink ML 仓库
ASF 仓库: https://gitbox.apache.org/repos/asf/flink-ml.git GitHub 镜像: https://github.com/apache/flink-ml Flink Kubernetes Operator 仓库
ASF 仓库: https://gitbox.apache.org/repos/asf/flink-kubernetes-operator.git GitHub 镜像: https://github.com/apache/flink-kubernetes-operator Apache Paimon(incubating) (formerly Flink Table Store) 仓库
ASF 仓库: https://gitbox.apache.org/repos/asf/incubator-paimon.git GitHub 镜像: https://github.com/apache/incubator-paimon Flink Website 仓库
ASF 仓库: https://gitbox.apache.org/repos/asf/flink-web.git GitHub 镜像: https://github.com/apache/flink-web.git Complete List of Repositories # The complete list of repositories of Apache Flink can be found under https://gitbox.apache.org/repos/asf#flink.
Training # Ververica 目前维护了一些免费的 Apache Flink 培训。 training website 有相应的演示文档和带解答的练习。当然还可以在 SlideShare 找到所有的演示文档。
项目 Wiki # Apache Flink 项目 wiki 包含了大量的 Flink 用户相关的资源。不过 wiki 上的资料可能会过时,如果有任何疑问,请查阅 Flink 文档。
Flink Forward # Flink Forward 大会每年都会在世界的不同地方举办。关于大会最新的信息可以到 Flink-Forward.org 网站获取到。
PMC Committer 列表 # 以下列表可能不是最新。最新列表请参考 此页面。
素材以及 Apache Flink Logo # 素材页面 提供了不同尺寸以及不同颜色的 Apache Flink Logo
`}),e.add({id:21,href:"/zh/documentation/flinkml-master/",title:"ML Master (snapshot)",section:"Documentation",content:" Flink ML documentation (latest snapshot) # You can find the Flink ML documentation for the latest snapshot here. "}),e.add({id:22,href:"/zh/what-is-flink/security/",title:"Security",section:"About",content:` Security # Security Updates # This section lists fixed vulnerabilities in Flink.
CVE ID Affected Flink versions Notes CVE-2020-1960 1.1.0 to 1.1.5, 1.2.0 to 1.2.1, 1.3.0 to 1.3.3, 1.4.0 to 1.4.2, 1.5.0 to 1.5.6, 1.6.0 to 1.6.4, 1.7.0 to 1.7.2, 1.8.0 to 1.8.3, 1.9.0 to 1.9.2, 1.10.0 Users are advised to upgrade to Flink 1.9.3 or 1.10.1 or later versions or remove the port parameter from the reporter configuration (see advisory for details). CVE-2020-17518 1.5.1 to 1.11.2 Fixed in commit a5264a6f41524afe8ceadf1d8ddc8c80f323ebc4 Users are advised to upgrade to Flink 1.11.3 or 1.12.0 or later versions. CVE-2020-17519 1.11.0, 1.11.1, 1.11.2 Fixed in commit b561010b0ee741543c3953306037f00d7a9f0801 Users are advised to upgrade to Flink 1.11.3 or 1.12.0 or later versions. CVE-2023-41834 Flink Stateful Functions 3.1.0, 3.1.1, 3.2.0 Fixed in commit b06c0a23a5a622d48efc8395699b2e4502bd92be Users are advised to upgrade to Flink Stateful Functions 3.3.0 or later versions. Frequently Asked Questions # During a security analysis of Flink, I noticed that Flink allows for remote code execution, is this an issue? # Apache Flink is a framework for executing user-supplied code in clusters. Users can submit code to Flink processes, which will be executed unconditionally, without any attempts to limit what code can run. Starting other processes, establishing network connections or accessing and modifying local files is possible.
Historically, we’ve received numerous remote code execution vulnerability reports, which we had to reject, as this is by design.
We strongly discourage users to expose Flink processes to the public internet. Within company networks or “cloud” accounts, we recommend restricting access to a Flink cluster via appropriate means.
I found a vulnerability in Flink, how do I report it? # Thanks a lot for looking into the security of Apache Flink! We appreciate reports improving the security of Flink. We accept vulnerability reports through the Apache Security Team, via their private email address security@apache.org.
If you want to discuss a potential security issue privately with the Flink PMC, you can reach us also via private@flink.apache.org.
`}),e.add({id:23,href:"/zh/documentation/flink-stateful-functions-stable/",title:"Stateful Functions $StateFunStableShortVersion (stable)",section:"Documentation",content:" Flink documentation (latest stable release) # You can find the Flink documentation for the latest stable release here. "}),e.add({id:24,href:"/zh/what-is-flink/special-thanks/",title:"特殊致谢",section:"About",content:` 特殊致谢 # Apache 赞助商 # 没有这些赞助商,ASF 将无法维持其活动:
https://www.apache.org/foundation/thanks.html
如果您想了解更多关于 Apache 赞助计划的信息,请查看:
https://www.apache.org/foundation/sponsorship.html
感谢!
那些帮助了我们项目的公司… # 我们还要感谢那些赞助了机器或服务的公司,感谢他们的赞助帮助了 Apache Flink 项目的开发:
Alibaba 捐赠了 8 台机器(32vCPU,64GB)为 Flink 仓库和 Pull Reqeust 运行持续集成的任务。 AWS 捐赠了 AWS 服务的开销,这些 AWS 服务用在了 flink-connector-aws 项目的集成测试中。 Ververica 捐赠了一台机器(1vCPU,2GB)用于维护 flink-ci 镜像仓库,以及一台机器(8vCPU,64GB)运行日常的 Flink Benchmark `}),e.add({id:25,href:"/zh/documentation/flink-stateful-functions-master/",title:"Stateful Functions Master (snapshot)",section:"Documentation",content:" Flink Stateful Functions documentation (latest snapshot) # You can find the Flink Stateful Functions documentation for the latest snapshot here. "}),e.add({id:26,href:"/zh/getting-started/",title:"教程",section:"Apache Flink Documentation",content:" Documentation # "}),e.add({id:27,href:"/zh/documentation/",title:"Documentation",section:"Apache Flink Documentation",content:" Documentation # "}),e.add({id:28,href:"/zh/how-to-contribute/overview/",title:"如何参与贡献",section:"How to Contribute",content:` 如何参与贡献 # Apache Flink 是由一个开放友好的社区开发的。我们诚挚地欢迎每个人加入社区并为 Apache Flink 做出贡献。与社区交流和为 Flink 做贡献的方式包括:提问题、报告 bug、提议新特性、参与邮件列表的讨论、贡献代码或文档、改进网站和测试候选发布版本。
你想做什么? # Apache Flink 做贡献不仅仅包括贡献代码。下面列出来不同的贡献形式:
可以贡献的领域 详细说明 报告 Bug 要报告 Flink 的问题,请登录 Flinks Jira,然后点击顶部红色的 Create 按钮。 请提供你遇到问题的详细信息,如果可以,请附上能够帮助我们复现问题的描述。 贡献代码 请阅读 `}),e.add({id:29,href:"/zh/how-to-contribute/contribute-code/",title:"贡献代码",section:"How to Contribute",content:` 贡献代码 # Apache Flink 是一个通过志愿者贡献的代码来维护、改进和扩展的项目。我们欢迎给 Flink 做贡献,但由于项目的规模大,以及为了保持高质量的代码库,我们要求贡献者遵循本文所阐述的贡献流程。
请随时提出任何问题! 可以发送邮件到 dev mailing list,也可以对正在处理的 Jira issue 发表评论。
重要提示:在开始准备代码贡献之前,请仔细阅读本文档。请遵循如下所述的流程和指南,为 Apache Flink 做贡献并不是从创建 pull request 开始的。我们希望贡献者先和我们联系,共同讨论整体方案。如果没有与 Flink committers 达成共识,那么贡献可能需要大量返工或不予审核通过。
寻找可贡献的内容 # 如果你已经有好的想法可以贡献,可以直接参考下面的 “代码贡献步骤”。 如果你在寻找可贡献的内容,可以通过 Flink 的问题跟踪列表 浏览处于 open 状态且未被分配的 Jira 工单,然后根据 “代码贡献步骤” 中的描述来参与贡献。 如果你是一个刚刚加入到 Flink 项目中的新人,并希望了解 Flink 及其贡献步骤,可以浏览 适合新手的工单列表 这个列表中的工单都带有 starter 标记,适合新手参与。
代码贡献步骤 # 注意:最近(2019 6 月),代码贡献步骤有改动。社区决定将原来直接提交 pull request 的方式转移到 Jira 上,要求贡献者在创建 pull request 之前需在 Jira 上达成共识(通过分配到的工单来体现),以减轻 PR review 的压力。 1讨论 Jira 上创建工单或邮件列表讨论并达成共识
商定重要性、相关性、工单的范围,讨论实现方案,并找到愿意审查和合并更改的 committer
只有 committers 才能分配 Jira 工单。
2实现 根据代码样式和质量指南,以及 Jira 工单中商定的方法去实现更改。
只有在达成共识时,才开始去实现(例如已经有工单分配给你了)
3审查 创建一个 pull request 并与 reviewer 一起审查。
未被分配 Jira 工单的 pull request 将不会被社区审查或合并。
4合并 Flink committer 审查此贡献是否满足需求,并将代码合并到代码库中。
注意:诸如拼写错误或语法错误之类的简单热修复可以不用创建 Jira 工单,直接提交 [hotfix] pull request 即可。 1. 创建 Jira 工单并达成共识。 # Apache Flink 做出贡献的第一步是与 Flink 社区达成共识,这意味着需要一起商定更改的范围和实现的方法。
在大多数情况下,我们应该在 Flink Bug 追踪器:Jira 中进行讨论。
以下类型的更改需要向 Flink dev@flink.apache.org 邮件列表发一封以 [DISCUSS] 开头的邮件:
重大变化(主要新功能、大重构和涉及多个组件) 可能存在争议的改动或问题 采用非常不明确的方法或有多种实现方法 在讨论未达成一致之前,不要为这些类型的更改创建 Jira 工单。 基于 dev 邮件讨论的 Jira 工单需要链接到该讨论,并总结结果。
Jira 工单获得共识的要求:
正式要求 描述问题的 Title 要简明扼要。 Description 中要提供了解问题或功能请求所需的所有详细信息。 要设置 Component 字段:许多 committers 和贡献者,只专注于 Flink 的某些子系统。设置适当的组件标签对于引起他们的注意很重要。 社区一致同意使用工单是有效解决问题的方法,而且这非常适合 Flink Flink 社区考虑了以下几个方面: 这种贡献是否会改变特性或组件的性能,从而破坏以前的用户程序和设置?如果是,那么就需要讨论并达成一致意见,证明这种改变是可取的。 这个贡献在概念上是否适合 Flink ?这是否是一种特殊场景?支持这种场景后会导致通用的场景变得更复杂,还是使整理抽象或者 APIs 变得更臃肿? 该功能是否适合 Flink 的架构?它是否易扩展并保持 Flink 未来的灵活性,或者该功能将来会限制 Flink 吗? 该特性是一个重要的新增内容(而不是对现有内容的改进)吗?如果是,Flink 社区会承诺维护这个特性吗? 这个特性是否与 Flink 的路线图以及当前正在进行的工作内容一致? 该特性是否为 Flink 用户或开发人员带来了附加价值?或者它引入了回归的风险而没有给相关的用户或开发人员带来好处? 该贡献是否存在于其他仓库中,例如 Apache Bahir 或者其他第三方库? 这仅仅是为了在开源项目中获得提交而做出的贡献吗(仅仅是为了获得贡献而贡献,才去修复拼写错误、改变代码风格)? 在如何解决这个问题上已有共识,包括以下需要考虑的因素 API、数据向后兼容性和迁移策略 测试策略 Flink 构建时间的影响 依赖关系及其许可证 如果在 Jira 的讨论中发现改动是一个大的或有争议的变更,则可能需要起草 Flink 改动建议(FLIP) 或在 dev 邮件列表 中讨论以达成一致的意见。
一般 Committer 会在几天内对工单进行回应。如果工单没有得到任何关注,我们建议你联系 dev 邮件列表。请注意,Flink 社区有时无法处理发来的所有贡献信息。
一旦满足了工单的所有条件后,Committer 就会将工单*分配*给某个人,然后被分配到工单的人就可以继续后续的工作了。 只有 Committer 才能分配工单(包括分配给他自己和其他人)。
社区不会审查或合并未关联 Jira 工单的 pull request
2. 实现你的改动 # 你一旦被分配到了 Jira issue,那么你就可以开始去实现所需的改动了。
以下是在实现时要注意的一些要点:
设置 Flink 的开发环境 遵循 Flink 的代码风格和质量指南 接受来自 Jira issue 或设计文档中的任何讨论和要求。 不要将不相关的问题混合到一个贡献中。 3. 创建 Pull Request # 在创建 pull request 之前的注意事项:
确保 mvn clean verify 成功执行,以保证所有检查都通过、代码成功构建和所有测试用例都成功执行。 执行 Flink 的端到端测试。 确保不包含任何不相关或不必要的格式化更改。 确保你的提交历史符合要求。 确保你的改动是基于最新的 base 分支提交的。 确保 pull request 引用的是相应的 Jira,并且每个 Jira issue 都对应一个 pull request(如果一个 Jira 有多个 pull requests,首先解决这种情况) 创建 pull request 之前或之后的注意事项:
确保分支在 Travis 上已经成功构建。 Flink 中的代码更改将通过 GitHub pull request 进行审查和合并。
这里有关于如何审查 pull request 的单独指南,包括我们的 pull request 审核流程。作为代码作者,在你准备 pull request 前,应该满足以上所有要求。
4. 合并改动 # 审核完成后,代码将由 Flink committer 合并。Jira 工单将在合并之后关闭。
`}),e.add({id:30,href:"/zh/how-to-contribute/reviewing-prs/",title:"审核 Pull Request",section:"How to Contribute",content:` 如何审核 Pull Request # 本指南适用于希望帮助审核代码的所有提交者和贡献者。感谢你的努力 - 良好的审核是开源项目中最重要也是最关键的部分之一。本文旨在协助社区开展代码审核工作,以达到下列目的:
让贡献者拥有良好的贡献体验。 将审核过程结构化,以涵盖所有需要检查的重要方面。 保持 Flink 代码的高质量。 避免贡献者和审核者花费大量时间完善代码却最终被拒绝提交的情况。 审核清单 # 每次审核都需要检查以下六个方面。 我们建议按照以下顺序进行检查,以避免在还没有就是否添加某项功能或需要改动达成共识之前或没有满足一些正式条件前,就花费时间进行详细的代码质量审核。
1. 贡献的描述是否清晰? # 检查贡献是否有充分的描述以方便审核,不重要的更改和修复不需要很长的描述。如果实现方案完全是按照之前在 Jira dev 邮件列表上讨论结论进行的话,只需要一个对讨论的简短的引用即可。 如果实现方案与之前达成一致的方案不同的话,关于实现的详细描述是需要的,以便 review 贡献时更深入地讨论。
任何改变功能或行为的 pull request 都需要描述这些改变的重点, 以便知道审核什么内容(并且不必钻研代码来了解更改的作用)。
如果在不查看代码的情况下能回答以下问题234,则该贡献得到了很好的描述。
2. 是否一致认为这一变更或者功能应该进入 Flink # 这个问题要直接在关联的 Jira issue 中回答。对于在达成一致前创建的 pull request 来说,需要先在 Jira 中寻求一致的意见。
对于 [hotfix] 类型的的 pull request,可以在 pull request 中寻求意见一致。
3. 贡献是否需要一些特定的 committer 的关注,这些 committer 有时间投入吗? # 一些更改需要特定的 committer 的注意和批准。例如,对性能非常敏感或对分布式协调和容错有关键影响的部件中的更改,这需要一个对相应组件非常熟悉的 committer 的审核。
根据经验,当 pull request 描述中对模板里问题 Does this pull request potentially affect one of the following parts 的回答为 yes 时,需要特别注意。
这个问题可以参考如下回答
Does not need specific attention Needs specific attention for X (X 可以是例如 checkpointingjobmanager 等) Has specific attention for X by @committerA, @contributorB 如果 pull request 需要特别关注,则其中一个标记的 committers contributors 应该给出最终批准。
4. 实现方案是否遵循了商定的整体方案/架构? # 在这一步中,我们会检查一个贡献的实现是否遵循了在 Jira 或邮件列表中商定的方案。 这个问题应该尽可能地从 pull request 描述(或链接的 Jira )中得到回答。
我们建议你在深入了解更改的各个部分进行评论之前先检查这一点。
5. 整体代码质量是否良好,是否符合我们希望在 Flink 中维护的标准? # 这是对实际变更的详细代码审核,包括:
变更是否按照 Jira issue pull request 说明中的描述进行? 代码是否遵循正确的软件工程实践?代码是否正确、健壮、可维护、可测试? 在更改性能敏感部分时,是否对性能进行了优化? 测试是否覆盖了全部改动? 测试执行速度是否够快?(是否仅在必要时才使用重量级集成测试?) 代码格式是否遵循 Flink checkstyle 模式? 代码是否避免引入额外的编译器警告? 如果依赖更新了,NOTICE 文件是否也更新了? 可以在 Flink代码样式和质量指南 中找到编码的规范和指南。
6. 英文和中文文档是否都更新了? # 如果这个 pull request 引入了一个新功能,该功能应该被文档化。Flink 社区正在同时维护英文和中文文档。所以如果你想要更新或扩展文档,英文和中文文档都需要更新。如果你不熟悉中文,请创建一个用于中文文档翻译的 JIRA 并附上 chinese-translation 的组件名,并与当前 JIRA 关联起来。如果你熟悉中文,我们鼓励在一个 pull request 中同时更新两边的文档。
阅读如何贡献文档了解更多。
`}),e.add({id:31,href:"/zh/how-to-contribute/code-style-and-quality-preamble/",title:"代码样式与质量指南",section:"How to Contribute",content:` Apache Flink Code Style and Quality Guide # 序言 # Pull Requests & Changes # 常用编码指南 # Java 语言指南 # Scala 语言指南 # 组件指南 # 格式指南 # 这是对我们想要维护的代码和质量标准的一种尝试。
一次代码贡献(或者任何代码片段)可以从很多角度进行评价:一组评判标准是代码是否正确和高效。这需要正确且良好的解决逻辑或算法问题。
另一组评判标准是代码是否使用了简洁的设计和架构,是否通过概念分离实现了良好的架构,是否足够简单易懂并且明确假设。该评判标准需要良好的解决软件工程问题。一个好的解决方案需要代码是容易被测试的,可以被除了原作者之外的其他人维护的(因为打破之后再维护是非常困难的),同时还需要能够高效的迭代演进的。
不过第一组标准有相当客观的达成条件,相比之下要达到第二组评判标准更加困难,但是对于 Apache Flink 这样的开源项目来说却非常重要。为了能够吸引更多贡献者,为了的开源贡献能够更容易被开发者理解,同时也为了众多开发者同时开发时代码的健壮性,良好工程化的代码是至关重要的。1 对于良好的工程代码来说,更加容易保证代码的正确性和高效不会随着时间的推移受到影响
当然,本指南并不是一份如何写出良好的工程代码的全方位指导。有相当多的书籍尝试说明如何实现良好的代码。本指南只是作为最佳实践的检查清单,包括我们在开发 Flink 过程中遇到的模式,反模式和常见错误。
高质量的开源代码很大一部分是关于帮助 reviewer 理解和双重检查执行结果。所以,本指南的一个重要目的是关于如何为为 review 构建一个良好的 pull request
在早期,我们(Flink 社区)并没有一直对此给予足够的重视,导致 Flink 的一些组件更难进化和贡献。 ↩︎
`}),e.add({id:32,href:"/zh/how-to-contribute/",title:"How to Contribute",section:"Apache Flink Documentation",content:" How to contribute # "}),e.add({id:33,href:"/zh/how-to-contribute/contribute-documentation/",title:"贡献文档",section:"How to Contribute",content:` 贡献文档 # 良好的文档对任何类型的软件都至关重要。这对于复杂的软件系统尤其如此,例如 Apache Flink 这样的分布式数据处理引擎。Apache Flink 社区旨在提供简明、精确和完整的文档,并欢迎任何改进 Apache Flink 文档的贡献。
获取文档资源 # Apache Flink 的文档和代码保存在相同的 git 仓库中。这样做是为了确保代码和文档可以轻松保持同步。
贡献文档的最简单方法是在 GitHub Flink 的镜像仓库 页面,通过单击右上角的 fork 按钮讲 Flink 克隆到你自己的 GitHub 帐户中。如果你没有 GitHub 帐户,可以免费创建一个帐户。
接下来,将 fork 的代码克隆到本地计算机。
git clone https://github.com/<your-user-name>/flink.git 文档位于 Flink 代码库的 docs/ 子目录中。
在开始贡献文档之前… # …请确保已经有一个相对应的 Jira issue 存在了。我们要求所有文档更改都需要关联一个 Jira issue,除了一些微不足道的修复,如拼写错误。
同时,先阅读一下 文档样式指南 能够很好的帮助你写出易懂、连贯和全面的文档。
更新或扩展文档 # Flink 文档是用 Markdown 编写的。Markdown 是一种轻量级标记语言,可以通过工具转化成 HTML
为了更新或扩展文档,你必须修改 Markdown (.md) 文件。请通过在预览模式下启动构建脚本来验证你的更改。
./build_docs.sh -p 该脚本会将 Markdown 文件编译成静态 HTML 页面并在本地启动一个 Web 服务器。在浏览器中打开 http://localhost:1313/ ,查看包含更改文档页面。当你修改并保存 Markdown 文件,然后刷新浏览器,修改过的文档将自动被重新编译和更新。
如果有任何疑问,请在开发者邮件列表随时提问。
中文文档翻译 # Flink 社区正在同时维护英文和中文文档。所以如果你想要更新或扩展文档,英文和中文文档都需要更新。如果你不熟悉中文,请创建一个用于中文文档翻译的 JIRA 并附上 chinese-translation 的组件名,并与当前JIRA关联起来。如果你熟悉中文,我们鼓励在一个 pull request 中同时更新两边的文档。
注意:Flink 社区目前正在翻译中文文档,有部分文档可能还未翻译。如果你正在更新的文档还未翻译,可以简单地将英文改动复制到中文文档中。
The Chinese documents are located in the content.zh/docs folder. You can update or extend the Chinese file in the content.zh/docs folder according to the English documents changes.
提交你的贡献 # Flink 项目通过 GitHub Mirror Pull Requests 方式接受文档的贡献。Pull request 是一种提供补丁的简单方法,它提供了一个指向包含更改的代码分支的链接。
请按照以下步骤准备和提交 pull request
将更改提交到本地 git 仓库。提交消息应该以 [FLINK-XXXX] 开头,对应了相关联的 Jira issue
将你提交的贡献推送到 GitHub 上你 fork Flink 仓库中。
git push origin myBranch 打开你的 fork 仓库网页 (https://github.com/<your-user-name>/flink) 并使用 “Create Pull Request” 按钮开始创建 pull request。确保 base fork 是 apache/flink master,并且 head fork 是包含更改的分支。再为 pull request 添加一个有意义的描述并创建它。
也可以将补丁(patch)附加到 Jira issue 上。
`}),e.add({id:34,href:"/zh/how-to-contribute/documentation-style-guide/",title:"文档样式指南",section:"How to Contribute",content:` 文档样式指南 # 本指南概述了在编辑以及贡献 Flink 文档中必要的样式原则。目的是在你的贡献之旅中可以投入更好的社区精力去改进和扩展既有文档,并使其更 易读、一致 全面。
语言 # Flink 同时维护了 英文 中文 两种文档,当你拓展或者更新文档时,需要在 pull request 中包含两种语言版本。如果你不熟悉中文,确保本次贡献补充了如下额外操作:
开一个翻译的 JIRA 请求单,并打上 chinese-translation 的标签; 在此请求单上添加到原始 JIRA 请求单的链接。 正在寻求有助于将现有文档翻译成中文的风格指南?请继续查阅 这个翻译规范。
语言风格 # 如下,你可以看到一些初步的原则,这些原则可以确保书写中的可读性和通俗易懂。如果想更深入、更细致的了解语言风格,也可以参考 通用准则。
语态和语气 # 使用主动语态。主动语态简洁,并让内容更具有吸引力。如果你在句子的动词后添加 by zombies 后仍然读的通,那么你用的就是被动语态。
主动语态 “You can run this example in your IDE or on the command line.” 被动语态 “This example can be run in your IDE or on the command line (by zombies).” 关于语态
如上语态规范主要是写英文文档过程中注意,中文文档仍然以 这个翻译规范 为准 使用你,而不是我们。 我们 会让用户感到困惑以及傲慢,给人“我们是一个秘密组织的成员,而 并没有获得会员邀请”的感觉。所以用 来建议用户。
**避免使用针对性别和文化的语言。**文档无需指定性别:技术写作应当 性别中立。还有,在你的文化和日常交流中被认为是理所应当的行话和惯例,在其他地方可能很不一样。幽默就是很典型的例子:在某个文化中很棒的笑话,但在其他文化中可能被广泛误解。
**避免对操作做能力限定以及对难度提前下结论。**对于很艰难才能完成操作或者操作中很容易沮丧的用户,使用诸如 快速 或者 容易 是糟糕的文档体验。
避免使用大写单词来突出或者强调陈述。使用例如 加粗 或者 斜体 来突出关键词通常会更礼貌。如果一个不明显的声明需要突出以引起更多的注意,可以按照段落分组,段落以标签开头,配合对应的 HTML 标记来突出显示:
<span class="label label-info">Note</span> <span class="label label-warning">Warning</span> <span class="label label-danger">Danger</span> 使用 Flink 特定术语 # 使用清晰的术语定义,也可以对要表达的内容提供有帮助的资源链接来辅助说明,例如其他的文档页面或者 Flink 术语表 。目前,术语表仍在编辑中,新术语可以开 pull-request 来提交。
代码仓库 # Markdown 文件(.md)的文件名应该是能高度总结主题的短名称,文件名全部 小写 并用 破折号(-) 分隔单词。中文的文件名和英文一致,但以 .zh.md 结尾。
语法 # The documentation website is generated using Hugo and the pages are written in Markdown, a lightweight portable format for web publishing (but not limited to it).
拓展语法 # Markdown 还可以混合使用 GitHub 风格的 Markdown 和纯 HTML 例如,一些贡献者更喜欢使用 HTML 标签来表示图片,这种混合的方式就很方便。
前言 # Markdown 之外,每个文件还包含一个 YAML 前言区块,用于设置页面变量以及元数据。前言必须在文件的最开始,由三条虚线之间的有效 YAML 集合来指定。
Apache 许可证 # 对于每一个文档, 前言后都应当紧随一个Apache 许可证声明。两种语言版本的声明都用英语表示,并按照如下实例完全复制。
--- title: Concepts layout: redirect --- <!-- Licensed to the Apache Software Foundation (ASF) under one or more contributor license agreements. See the NOTICE file distributed with this work for additional information regarding copyright ownership. The ASF licenses this file to you under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. --> 下面是 Flink 文档前言中常用的变量。
变量名 可能值 描述 布局 layout {base,plain,redirect} 要使用的布局文件。布局文件位于 _layouts 目录下。 内容 title %s 此标题是页面最顶部 1级) 的标题。 导航 nav-id %s 页面 ID。其他页面可以使用此 ID 作为他们的 nav-parent_id nav-parent_id {root,%s} 页面父级 ID。最低导航级别为 root nav-pos %d 在每个导航级别下页面的相对位置。 nav-title %s 此标题用于重载默认的文本链接(标题) 文档范围的信息和配置位于 _config.yml 下,在前言中也是可用的,通过 site 变量使用。可以使用以下语法访问这些设置:
{{ "{{ site.CONFIG_KEY " }}}} 当生成文档时,占位符会被替换成变量 CONFIG_KEY 的值。
格式化 # 以下各节列出了基本的格式准则,可以帮助你开始编写一致且易于浏览的文档。
标题 # Markdown 中,标题是任意以井号(#)开头的行,井号的数量表示标题级别。标题永远是嵌套和连续的,不能因为样式原因跳过标题级别!
语法 级别 描述 # 标题 1 页面标题在前言中定义,此级别标题 不应该使用。 ## 标题 2 章节的起始级别。用于按照高级别的主题或者目标来组织内容。 ### 标题 3 子章节。在每个章节中用于分隔次要信息或者任务。 #### 标题 4 最佳实践 # 标题使用叙述语言的措辞。例如,一个动态表格的文档页面,“动态表格和连续查询”就比“背景”或者“技术信息”更有描述性。
目录 # 在文档构建过程中,标题(TOC) 从页面标题自动生成,通过如下行标记使用:
{{ "{:toc" }}} 仔细考虑下大于 3 的标题。在 TOC 中去除指定标题:
{{ "# 排除在外的标题 {:.no_toc" }}} 最佳实践 # 为所涵盖的主题写一个简短的介绍,并放在 TOC 之前。一些上下文,例如关键信息的概述,对于确保文档的连贯、降低阅读门槛都大有帮助。
导航 # 在文档构建中,导航的属性通过每个页面中的 前言变量配置。
在比较长的文档页面中使用 回到首页 是很有必要的,这样用户就可以直接跳转到顶部而不用手动向上滑动。在使用标记中,通过在构建文档时替换占位符为一个默认的链接来实现:
{{ "{% top " }}%} 最佳实践 # 建议至少要在 2 级章节的结尾处添加回到首页链接。
标注 # 如果你需要在文档中添加边缘案例、紧密相关或者最好了解的信息,使用特殊的标注来高亮是一个(很)好的实践。
突出显示提示以及有助于理解的信息:
<div class="alert alert-info"> // Info Message </div> 发出陷阱危险信号,或提醒关注必须要遵循的重要信息:
<div class="alert alert-danger"> // Danger Message </div> 链接 # 添加文档链接是一种有效的方法–可以引导用户更好的理解正在讨论的主题,而不会有重写的风险。
指向页面中各节的链接。 每个标题都会生成一个隐式标识符,以便在页面中直接跳转。此标识符是通过将标题设置为小写并将内部空格替换为连字符来生成的。
标题: ## Heading Title ID #heading-title [Link Text](#heading-title) 链接到 Flink 文档的其他页面。
{% raw %}
[Link Text]({% link path/to/link-page.md %}) {% endraw %}
指向外部页面的链接
[Link Text](external_url) 最佳实践 # 链使用可以提供操作或者目标信息的描述性链接名称。例如,避免使用“了解更多”或“单击此处”链接。
可视化内容 # 图形和其他可视化内容放置在根目录的 fig 目录下,可以使用类似于链接的语法在文档页面中引用:
最佳实践 # 在适当或必要的情况下使用流程图、表格和图形进行额外说明,但切勿作为独立的信息来源。确保内容中的字体大小不影响阅读,并且整体分辨率足够。
代码 # 行内代码、 使用包围的反引号( \`)来高亮正常文本流中的小代码段或者语言结构类型的引用。
代码块。 表示自包含示例、功能演练、最佳实践演示或其他有用场景的代码,应使用带有适当 语法高亮显示的围栏代码块(fenced code block)进行包装。其中一种代码块实现方式如下:
\`\`\`java // Java Code \`\`\` 指定多个编程语言时,每个代码块都应设置为选项卡样式:
<div class="codetabs" markdown="1"> <div data-lang="java" markdown="1"> \`\`\`java // Java Code \`\`\` </div> <div data-lang="scala" markdown="1"> \`\`\`scala // Scala Code \`\`\` </div> </div> 在学习和探索过程会经常使用代码块,留心这些最佳实践:
展示关键开发任务。 对用户有意义的通用实现场景需要保留代码样例。对教程或者演示提供足够长度和复杂的示例代码。
确保代码是独立的。 代码示例应该是自包含的,并且没有外部依赖项(异常情况除外,例如有关如何使用特定连接器的示例)。包括所有不使用通配符的导入语句,以便新手理解和学习正在使用哪些包。
避免捷径。 例如,像处理实际代码一样处理异常和清理。
使用注释,但不要过度。 提供说明,用于描述代码的主要功能和可能的注意事项,这些注意事项可能在阅读时并不明显。使用注释来阐明实现细节并描述预期输出。
**代码块中的命令。**可以使用 bash 语法记录命令。当给文档添加命令的时候考虑如下内容:
参数名称长一点。 长一点的参数名能很好的帮助用户理解命令的目的。相对于短名称,用户应该更喜欢长名称。 **每个参数占据一行。**长名称可能会让命令难以阅读。每个参数占据一行能提升可读性。为了支持复制粘贴,需要在命令的每个中间行使用反斜杠 \\ 转义换行。 **缩进。**每个新参数行应缩进6个空格。 **用前缀 $ 来标识命令的开始。**同一处代码块中的多行命令会影响可读性。在每个新命令前放美元符 $ 有助于识别命令的开头。 一个格式正确的命令如下:
$ ./bin/flink run-application \\ --target kubernetes-application \\ -Dkubernetes.cluster-id=my-first-application-cluster \\ -Dkubernetes.container.image=custom-image-name \\ local:///opt/flink/usrlib/my-flink-job.jar 通用准则 # 本风格指南的首要目标是为写出易读、一致、客观、合乎逻辑以及全面的文档奠定基础。
易读的 # Flink 社区是多元化和国际化的,所以在编写文档时需要放眼全球。不是每个人的母语都是英语,而且使用 Flink (以及一般的流处理)的经验也是从初学者到资深不等。因此要确保内容的技术准确性以及语言清晰度,以便所有的用户都能理解。
一致的 # 坚持本样式指南中详细的基本准则,并用自己的最佳判断来统一拼写、大小写、连字符、粗体和斜体。正确的语法、标点符号和拼写是值得做的,但并不是必须的–贡献文档对任何语言熟练度都是开放的。
客观的 # 句子应该简洁和提纲挈领。根据经验,如果一个句子少于 14 个单词,读者就会很容易理解 90% 的内容。但如果大于 25 个单词通常就会很难理解了,应尽可能修改和拆分。简明和众所周知的关键词能让用户轻松的定位到相关的文档。
合乎逻辑的 # 请注意,大部分用户只会浏览大约 28% 的在线内容 。这突出表明了将相关的概念按照清晰的信息结构分组、内容聚焦以及使用描述性标题的重要性。将最相关的内容放在每个章节的头两个段落是很好的实践,这样能增加用户的“时间投入回报”。
全面的 # 使用积极主动的语法以及准确、有关联性的样例,以确保内容可被检索到并且对所有用户都是友好可读的。文档也会被翻译成其他语言,所以使用简单的语法和熟悉的单词有助于减少翻译的工作量。
`}),e.add({id:35,href:"/zh/how-to-contribute/improve-website/",title:"贡献网站",section:"How to Contribute",content:` 改进网站 # Apache Flink 官网 介绍了 Apache Flink 及其社区。包括如下多种用途:
向来访者介绍 Apache Flink 及其特性。 鼓励来访者下载并使用 Flink 鼓励来访者与社区进行互动。 我们欢迎任何改进官网的贡献。本文档包含了所有改进 Flink 官网所需要的信息。
获取官网源码 # Apache Flink 官网的源码托管在专用的 git 仓库中,并在 Github 中有一个镜像 https://github.com/apache/flink-web.
向官网贡献的最简单方式是通过单击右上角的 fork 按钮,将 Github 上官网的镜像 镜像到自己的仓库中。如果没有 Github 帐户,你可以免费创建一个。
接下来,把你镜像的仓库克隆到本地机器上。
git clone https://github.com/<your-user-name>/flink-web.git flink-web 目录包含了拷贝的仓库。官网的代码位于 asf-site 分支上。运行如下命令切换到 asf-site 分支
cd flink-web git checkout asf-site 目录结构和文件 # Flink 官网使用 Markdown 语言。Markdown 是一种轻量级标记语言,可以转换为 HTML。我们使用 Hugo Markdown 生成静态 HTML 文件。
flink-web git 仓库中的文件和目录具有以下作用:
所有以 .md 结尾的文件都是 Markdown 文件。这些文件将被转换为静态 HTML 文件。 docs 目录包含所有文档、主题和其他用于渲染和生成网站的内容。 docs/content/docs 文件夹包含所有英文内容。docs/content.zh/docs 文件夹包含所有中文内容。 docs/content/posts 文件夹包含所有博客文章。 content/ 目录包含 Hugo 生成的 HTML 文件。鉴于托管 Flink 官网的 Apache Infrastructure 从该目录中拉取 HTML 网页内容,因此将生成文件放置在此目录中这一步至关重要。( Committer 注意:在向 git 仓库推送更改的同时,需要同时更新 content/ 目录中的内容!) 更新文档 # 可以通过修改已有文档,或新增资源–比如 CSS 文件等方式对网站进行更新。想验证你的修改,可以执行如下命令:
./build.sh 该脚本将 Markdown 文件编译为 HTML 并启动本地 Web 服务器。在浏览器中打开 http://localhost:1313 以查看包括修改后的网站。中文版本位于 http://localhost:1313/zh/ 。当您做出修改、保存任何文件并刷新浏览器时,网站内容会自动重新编译和更新。
如果要在文档或者博客文章中添加 Flink 官方文档的外链引用,请使用以下语法:
{{< docs_link file="relative_path/" name="Title">}} 例如:
{{< docs_link file="flink-docs-stable/docs/dev/datastream/side_output/" name="Side Output">}} 如果有任何疑问,欢迎在开发者邮件列表中咨询。
提交你的贡献 # Flink 项目通过 GitHub Mirror 以提交 Pull Requests 方式接受网站贡献。Pull requests 是一种通过向特定代码分支提交补丁的简单方法。
请按以下步骤操作准备并提交 pull request
将你的更改提交到本地 git 仓库。如果不是重大重构,请将代码压缩到一个提交中。
请将提交推送到 GitHub 上你自己仓库的一个特定分支。
git push origin myBranch 打开你镜像的仓库 (https://github.com/<your-user-name>/flink-web) 并使用 “Create Pull Request” 按钮开始创建新的 pull request。确保基础分支是 apache/flink-web asf-site ,并且 head fork 选择带有更改内容的分支。 为 pull request 提供有意义的描述并提交。
Committer 章节 # 本章节仅适用于 Committer
ASF 网站的 git 仓库 # ASF writable: https://gitbox.apache.org/repos/asf/flink-web.git
有关如何设置 ASF git 仓库凭据的详细信息可以参考 链接。
合并 pull request # 默认所有的修改仅在源文件上完成(对 content/ 目录中自动生成的文件没有修改)。 在推送网站更改之前,请运行构建脚本。
./build.sh 将更改添加到 content/ 目录作为附加提交,并将更改推送到 ASF 基本仓库。
`}),e.add({id:36,href:"/zh/how-to-contribute/getting-help/",title:"获取帮助",section:"How to Contribute",content:` 获取帮助 # 有问题吗? # Apache Flink 社区每天都会回答许多用户的问题。你可以从历史存档中搜索答案和建议,也可以联系社区寻求帮助和指导。
用户邮件列表 # 许多 Flink 用户、贡献者和提交者都订阅了 Flink 的用户邮件列表。用户邮件列表是一个寻求帮助的好地方。
在发送邮件到邮件列表之前,你可以搜索以下网站的邮件列表存档,从中找到你关注问题的相关讨论。
Apache Pony 邮件存档 如果你想发送到邮件列表,你需要:
发送电子邮件至 user-subscribe@flink.apache.org 来订阅邮件列表 通过回复确认邮件来确认订阅 发送你的电子邮件到 user@flink.apache.org. 请注意,如果你没有订阅邮件列表,你将不会收到邮件的回复。
Slack # 你可以通过 此链接 加入 Apache Flink 社区专属的 Slack 工作空间。 在成功加入后,不要忘记在 #introductions 频道介绍你自己。 Slack 规定每个邀请链接最多可邀请 100 人,如果遇到上述链接失效的情况,请联系 Dev 邮件列表。 所有已经加入社区 Slack 空间的成员同样可以邀请新成员加入。
Slack 空间交流时,请遵守以下规则:
保持尊重 - 这是最重要的规则 所有重要的决定和结论 必须在邮件列表中有所体现。 “没有发生在邮件列表上的事情,即视为没有发生。” - Apache 准则 使用 Slack 消息列(Thread 使频道(Channel)中的多组同时进行的对话保持有序。 Use either #pyflink (for all Python Flink questions) or #troubleshooting (for all other Flink questions). 不要通过私信(Direct Message 要求他人答疑、指派 Jira、审查 PR。这些事务应遵从自愿原则。 Stack Overflow # Flink 社区的许多成员都活跃在 Stack Overflow。你可以在这里搜索问题和答案,或者使用 [apache-flink] 标签来发布你的问题。
发现 Bug? # 如果你发现一个意外行为可能是由 Bug 导致的,你可以在 Flink’s JIRA 中搜索已经上报的 Bug 或者发布该 Bug
如果你不确定意外行为的发生是否由 Bug 引起的,请发送问题到 用户邮件列表。
收到错误信息? # 找到导致错误的原因通常是比较困难的。在下文中,我们列出了最常见的错误消息并解释了如何处理它们。
我有一个 NotSerializableException 异常。 # Flink 使用 Java 序列化来分发应用程序逻辑(你实现的函数和操作,以及程序配置等)的副本到并行的工作进程。 因此,传递给 API 的所有函数都必须是可序列化的,见 java.io.Serializable 定义。
如果你使用的函数是匿名内部类,请考虑以下事项:
为函数构建独立的类或静态内部类。 使用 Java 8 lambda 函数。 如果函数已经是静态类,则在创建该类的实例时会检查该类的字段。其中很可能包含不可序列化类型的字段。
Java 中,使用 RichFunction 并且在 open() 方法中初始化有问题的字段。 Scala 中,你通常可以简单地使用 lazy val 声明来推迟初始化,直到分布式执行发生。这可能是一个较小的性能成本。你当然也可以在 Scala 中使用 RichFunction 使用 Scala API,我收到有关隐式值和证据参数的错误。 # 此错误意味着无法提供类型信息的隐式值。确保在你的代码中存在 import org.apache.flink.streaming.api.scala._ (DataStream API) import org.apache.flink.api.scala._ (DataSet API) 语句。
如果在接受泛型参数的函数或类中使用 Flink 操作,则必须为参数提供 TypeInformation 类型参数。 这可以通过使用上下文绑定来实现:
def myFunction[T: TypeInformation](input: DataSet[T]): DataSet[Seq[T]] = { input.reduceGroup( i => i.toSeq ) } 请参阅 类型提取和序列化 深入讨论 Flink 如何处理类型。
我看到一个 ClassCastException: X cannot be cast to X. # 当你看到 com.foo.X cannot be cast to com.foo.X ( 或者 cannot be assigned to com.foo.X), 样式的异常时,这意味着 com.foo.X 类的多个版本已经由不同的类加载器加载,并且尝试相互赋值。
原因可能是:
通过 child-first 的类加载方式实现类复制。这是一种预期的机制,该机制允许用户使用相同依赖的不同版本。然而,如果这些类的不同副本在 Flink 的核心代码和用户应用程序代码之间移动,则可能发生这种异常。为了验证这个原因,请尝试在配置中设置 classloader.resolve-order: parent-first
如果这可以使错误消失,请写信到邮件列表以检查是否可能是 Bug
从不同的执行中尝试缓存类,例如使用像 Guava Interners Avro Schema 等通用工具进行缓存操作。尝试不使用 Interners,或减少 interner/cache 的使用范围,以确保每当新任务开始执行时都会创建新的缓存。
我有一个 AbstractMethodError NoSuchFieldError 错误。 # 此类错误通常表示混淆了某些依赖的版本。这意味着在执行期间加载了不同版本的依赖项(库),而不是编译代码的版本。
Flink 1.4.0 开始,在默认激活 child-first 类加载方式的情况下,相比 Flink core 所使用的依赖或类路径中的其他依赖(例如来自 Hadoop )而言,应用程序 JAR 文件中的依赖更可能带有不同的版本。
如果你在 Flink 1.4 以上的版本中看到这些问题,则可能是属于以下某种情况:
你的程序代码中存在依赖项版本冲突,确保所有依赖项版本都一致。 你与一个 Flink 不能支持 child-first 类加载的库发生了冲突。目前会产生这种情况的有 Scala 标准库类、Flink 自己的类、日志 API 和所有的 Hadoop 核心类。 尽管事件正在持续发送,我的 DataStream 程序还是没有输出。 # 如果你的 DataStream 程序使用了 事件时间,那么请检查你的 Watermark 是否已经更新。如果没有产生 Watermark 事件时间窗口可能永远不会触发,程序将不会产生任何结果。
你可以在 Flink Web UIWatermark 部分)中查看 Watermark 是否正在更新。
我看到了一个 Insufficient number of network buffers 的异常报告。 # 如果你用非常高的并行度运行 Flink 程序,则可能需要增加网络缓冲区的大小。
默认情况下,Flink 占用 JVM 堆的 10% 作为网络缓冲区的大小,最小为64MB,最大为1GB 你可以通过 taskmanager.network.memory.fraction, taskmanager.network.memory.min taskmanager.network.memory.max 参数调整这些值。
详情请参考 配置参考。
我的 Job 因为 HDFS/Hadoop 代码的各种异常失败了,我该怎么办? # 最常见的原因是 Flink 的类路径中的 Hadoop 版本与你要访问的 Hadoop 集群(HDFS / YARN)版本不同。
解决这个问题的最简单方法是选择一个不含 Hadoop Flink 版本,并通过 export 的方式设置 Hadoop 路径和类路径即可。
`}),e.add({id:37,href:"/zh/how-to-contribute/code-style-and-quality-components/",title:"Apache Flink 代码样式和质量指南 — 组件",section:"How to Contribute",content:` Apache Flink 代码样式和质量指南 组件 # 序言 # Pull Requests & Changes # 常用编码指南 # Java 语言指南 # Scala 语言指南 # 组件指南 # 格式指南 # 组件特定指南 # 关于特定组件更改的附加指南。
配置更改 # 配置选项应该放在哪里?
flink-conf.yaml’: 所有属于可能要跨作业标准的执行行为的配置。可以将其想像成 Ops 的工作人员或为其他团队提供流处理平台的工作人员设置的参数。 ExecutionConfig’: 执行期间算子需要特定于单个 Flink 应用程序的参数,典型的例子是水印间隔,序列化参数,对象重用。 ExecutionEnvironment (in code): 所有特定于单个 Flink 应用程序的东西,仅在构建程序/数据流时需要,在算子执行期间不需要。 如何命名配置键:
配置键名应该分层级。将配置视为嵌套对象(JSON 样式)
taskmanager: { jvm-exit-on-oom: true, network: { detailed-metrics: false, request-backoff: { initial: 100, max: 10000 }, memory: { fraction: 0.1, min: 64MB, max: 1GB, buffers-per-channel: 2, floating-buffers-per-gate: 16 } } } 因此生成的配置键应该:
不是 "taskmanager.detailed.network.metrics"
而是 "taskmanager.network.detailed-metrics"
连接器 # 连接器历来很难实现,需要处理多线程、并发和检查点等许多方面。
作为 FLIP-27 的一部分,我们正在努力使数据源(source)的实现更简单。新的数据源应该不必处理并发/线程和检查点的任何方面。
预计在不久的将来,会有类似针对数据汇(sink)的 FLIP
示例 # 示例应该是自包含的,不需要运行 Flink 以外的系统。除了显示如何使用具体的连接器的示例,比如 Kafka 连接器。数据源/数据汇可以使用 StreamExecutionEnvironment.socketTextStream,这个不应该在生产中使用,但对于研究示例如何运行是相当方便的,以及基于文件的数据源/数据源。(对于流,Flink 提供了连续的文件数据源读取数据) 示例也不应该是纯粹的玩具示例,而是在现实世界的代码和纯粹的抽象示例之间取得平衡。WordCount 示例到现在已经很久了,但它是一个很好的功能突出并可以做有用事情的简单代码示例。
示例中应该有不少的注释。他们可以在类级 Javadoc 中描述示例的总体思路,并且描述正在发生什么和整个代码里使用了什么功能。还应描述预期的输入数据和输出数据。
示例应该包括参数解析,以便你可以运行一个示例(使用 bin/flink run path/to/myExample.jar --param1 --param2 运行程序)。
表和 SQL API # 语义 # SQL 标准应该是事实的主要来源。
语法、语义和功能应该和 SQL 保持一致! 我们不需要重造轮子。大部分问题都已经在业界广泛讨论过并写在 SQL 标准中了。 我们依靠最新的标准(在写这篇文档时使用 SQL:2016 or ISO/IEC 9075:2016 ([下载])。并不是所有的部分都能在网上找到,但可以通过网络查找确认。 讨论与标准或厂商特定解释的差异。
一旦定义了语法或行为就不能轻易撤销。 需要扩展或解释标准的贡献需要与社区进行深入的讨论。 请通过一些对 PostgresMicrosoft SQL ServerOracleHiveCalciteBeam 等其他厂商如何处理此类案例进行初步的探讨来帮助提交者。 Table API 视为 SQL Java/Scala 编程世界之间的桥梁。
Table API 是一种嵌入式域特定语言,用于遵循关系模型的分析程序。 在语法和名称方面不需要严格遵循 SQL 标准,但如果这有助于使其感觉更直观,那么可以更接近编程语言的方式/命名函数和功能。 Table API 可能有一些非 SQL 功能(例如 map()、flatMap() 等),但还是应该“感觉像 SQL”。如果可能,函数和算子应该有相等的语义和命名。 常见错误 # 添加功能时支持 SQL 的类型系统。 SQL 函数、连接器或格式化从一开始就应该原生的支持大多数 SQL 类型。 不支持的类型会导致混淆,限制可用性,多次修改相同代码会增加负担。 例如,当添加 SHIFT_LEFT 函数时,确保贡献足够通用,不仅适用于 INT 也适用于 BIGINT TINYINT. 测试 # 测试为空性
几乎每个操作,SQL 都原生支持 NULL,并具有 3 值布尔逻辑。 确保测试每个功能的可空性。 尽量避免集成测试
启动一个 Flink 集群并且对 SQL 查询生成的代码进行编译会很耗时。 避免对 planner 测试或 API 调用的变更进行集成测试。 相反,使用单元测试来验证 planner 产生的优化计划。或者直接测试算子的运行时行为。 兼容性 # 不要在次要版本中引入物理计划更改!
流式 SQL 中状态的向后兼容性依赖于物理执行计划保持稳定的事实。否则,生成的 Operator Names/IDs 将发生变化,并且无法匹配和恢复状态。 导致流传输管道的优化物理计划改变的每个 bug 修复均会破坏兼容性。 因此,导致不同优化计划的此类更改目前仅可以合并到大版本中。 Scala / Java 互操作性(遗留代码部分) # 在设计接口时要牢记 Java
考虑一个类将来是否需要与 Java 类交互。 在接口中使用 Java 集合和 Java Optional,以便与 Java 代码平滑集成。 如果要将类转换为 Java,不要使用 .copy() apply() case class 的功能进行构造。 Scala 面向用户的 API 应该使用纯 Scala 集合/迭代/等与 Scala 自然和惯用的(“scalaesk”)集成。 `}),e.add({id:38,href:"/zh/how-to-contribute/code-style-and-quality-common/",title:"Code Style and Quality Guide — Common Rules",section:"How to Contribute",content:` Code Style and Quality Guide Common Rules # 序言 # Pull Requests & Changes # 常用编码指南 # Java 语言指南 # Scala 语言指南 # 组件指南 # 格式指南 # 1. Copyright # Each file must include the Apache license information as a header.
/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ 2. Tools # We recommend to follow the IDE Setup Guide to get IDE tooling configured.
Warnings # We strive for zero warnings Even though there are many warnings in existing code, new changes should not add any additional compiler warnings If it is not possible to address the warning in a sane way (in some cases when working with generics) add an annotation to suppress the warning When deprecating methods, check that this does not introduce additional warnings 3. Comments And Code Readability # Comments # Golden rule: Comment as much as necessary to support code understanding, but dont add redundant information.
Think about
What is the code doing? How does the code do this? Why is the code like that? The code alone should explain as much as possible the what and the how
Use JavaDocs to describe the roles of classes and the contracts of methods, in cases where the contract is not obvious or intuitive from the method name (the what”). The flow of the code should give a good description of the how”. Think of variable and method names as part of the code documenting itself. It often makes reading the code easier if larger blocks that form a unit are moved into a private method with a descriptive name of what that block is doing In-code comments help explain the why
For example // this specific code layout helps the JIT to better do this or that Or // nulling out this field here means future write attempts are fail-fast Or // for arguments with which this method is actually called, this seemingly naive approach works actually better than any optimized/smart version In-code comments should not state redundant information about the “what” and “how” that is already obvious in the code itself.
JavaDocs should not state meaningless information (just to satisfy the Checkstyle checker).
Dont:
/** * The symbol expression. */ public class CommonSymbolExpression {} Do:
/** * An expression that wraps a single specific symbol. * A symbol could be a unit, an alias, a variable, etc. */ public class CommonSymbolExpression {} Branches and Nesting # Avoid deep nesting of scopes, by flipping the if condition and exiting early.
Dont:
if (a) { if (b) { if (c) { the main path } } } Do
if (!a) { return .. } if (!b) { return ... } if (!c) { return ... } the main path 4. Design and Structure # While it is hard to exactly specify what constitutes a good design, there are some properties that can serve as a litmus test for a good design. If these properties are given, the chances are good that the design is going into a good direction. If these properties cannot be achieved, there is a high probability that the design is flawed.
Immutability and Eager Initialization # Try to use immutable types where possible, especially for APIs, messages, identifiers, properties, configuration, etc. A good general approach is to try and make as many fields of a class final as possible. Classes that are used as keys in maps should be strictly immutable and only have final fields (except maybe auxiliary fields, like lazy cached hash codes). Eagerly initialize classes. There should be no init() or setup() methods. Once the constructor completes, the object should be usable. Nullability of the Mutable Parts # For nullability, the Flink codebase aims to follow these conventions:
Fields, parameters, and return types are always non-null, unless indicated otherwise All fields, parameters and method types that can be null should be annotated with @javax.annotation.Nullable. That way, you get warnings from IntelliJ about all sections where you have to reason about potential null values. For all mutable (non-final) fields that are not annotated, the assumption is that while the field value changes, there always is a value. This should be double check whether these can in fact not be null throughout the lifetime of the object. Note: This means that @Nonnull annotations are usually not necessary, but can be used in certain cases to override a previous annotation, or to point non-nullability out in a context where one would expect a nullable value.
Optional is a good solution as a return type for method that may or may not have a result, so nullable return types are good candidates to be replaced with Optional. See also usage of Java Optional.
Avoid Code Duplication # Whenever you are about to copy/paste some code, or reproduce a similar type of functionality in a different place, think about the ways how to refactor/reuse/abstract the changes to avoid the duplication. Common behavior between different specializations should be shared in a common component (or a shared superclass). Always use private static final constants instead of duplicating strings or other special values at different locations. Constants should be declared in the top member area of a class. Design for Testability # Code that is easily testable typically has good separation of concerns and is structured to be reusable outside the original context (by being easily reusable in tests).
A good summary or problems / symptoms and recommended refactoring is in the PDF linked below. Please note that while the examples in the PDF often use a dependency injection framework (Guice), it works in the same way without such a framework.1
http://misko.hevery.com/attachments/Guide-Writing%20Testable%20Code.pdf
Here is a compact summary of the most important aspects.
Inject dependencies
Reusability becomes easier if constructors dont create their dependencies (the objects assigned to the fields), but accept them as parameters.
Effectively, constructors should have no new keyword. Exceptions are creating a new empty collection (new ArrayList<>()) or similar auxiliary fields (objects that have only primitive dependencies). To make instantiation easy / readable, add factory methods or additional convenience constructors to construct whole object with dependencies.
In no case should it ever be required to use a reflection or a Whitebox util to change the fields of an object in a test, or to use PowerMock to intercept a new call and supply a mock.
Avoid too many collaborators
If you have to take a big set of other components into account during testing (“too many collaborators”), consider refactoring.
The component/class you want to test probably depends on another broad component (and its implementation), rather than on the minimal interface (abstraction) required for its work.
In that case, segregate the interfaces (factor out the minimal required interface) and supply a test stub in that case.
For example, if testing a S3RecoverableMultiPartUploader requires actual S3 access then the S3 access should be factored out into an interface and test should replace it by a test stub This naturally requires to be able to inject dependencies (see above) Please note that these steps often require more effort in implementing tests (factoring out interfaces, creating dedicated test stubs), but make the tests more resilient to changes in other components, i.e., you do not need to touch the tests when making unrelated changes.
Performance Awareness # We can conceptually distinguish between code that coordinates and code that processes data”. Code that coordinates should always favor simplicity and cleanness. Data processing code is highly performance critical and should optimize for performance.
That means still applying the general idea of the sections above, but possibly forgoing some aspects in some place, in order to achieve higher performance.
Which code paths are Data Processing paths?
Per-record code paths: Methods and code paths that are called for each record. Found for example in Connectors, Serializers, State Backends, Formats, Tasks, Operators, Metrics, runtime data structures, etc. I/O methods: Transferring messages or chunks of data in buffers. Examples are in the RPC system, Network Stack, FileSystems, Encoders / Decoders, etc. Things that performance critical code may do that we would otherwise avoid
Using (and reusing) mutable objects to take pressure off the GC (and sometimes help with cache locality), thus forgoing the strive for immutability. Using primitive types, arrays of primitive types, or MemorySegment/ByteBuffer and encoding meaning into the primitive types and byte sequences, rather than encapsulating the behavior in dedicated classes and using objects. Structuring the code to amortize expensive work (allocations, lookups, virtual method calls, …) across multiple records, for example by doing the work once per buffer/bundle/batch. Code layout optimized for the JIT rather than for readability. Examples are inlining fields from other classes (in cases where it is doubtful whether the JIT would do that optimization at runtime), or structuring code to help the JIT compiler with inlining, loop unrolling, vectorization, etc. 5. Concurrency and Threading # Most code paths should not require any concurrency. The right internal abstractions should obviate the need for concurrency in almost all cases.
The Flink core and runtime use concurrency to provide these building blocks. Examples are in the RPC system, Network Stack, in the Tasks mailbox model, or some predefined Source / Sink utilities. We are not fully there, but any new addition that introduces implements its own concurrency should be under scrutiny, unless it falls into the above category of core system building blocks. Contributors should reach out to committers if they feel they need to implement concurrent code to see if there is an existing abstraction/building-block, or if one should be added. When developing a component think about threading model and synchronization points ahead.
For example: single threaded, blocking, non-blocking, synchronous, asynchronous, multi threaded, thread pool, message queues, volatile, synchronized block/methods, mutexes, atomics, callbacks, Getting those things right and thinking about them ahead is even more important than designing classes interfaces/responsibilities, since its much harder to change later on. Try to avoid using threads all together if possible in any way.
If you feel you have a case for spawning a thread, point this out in the pull request as something to be explicitly reviewed. Be aware that using threads is in fact much harder than it initially looks
Clean shutdown of threads is very tricky. Handling interruptions in a rock solid fashion (avoid both slow shutdown and live locks) requires almost a Java Wizard Ensuring clean error propagation out of threads in all cases needs thorough design. Complexity of multi-threaded application/component/class grows exponentially, with each additional synchronisation point/block/critical section. Your code initially might be easy enough to understand, but can quickly grow beyond that point. Proper testing of multithreaded code is basically impossible, while alternative approaches (like asynchronous code, non-blocking code, actor model with message queues) are quite easy to test. Usually multi-threaded code is often even less efficient compared to alternative approaches on modern hardware. Be aware of the java.util.concurrent.CompletableFuture
Like with other concurrent code, there should rarely be the need to use a CompletableFuture Completing a future would also complete on the calling thread any chained futures that are waiting for the result to be completed, unless a completion executor specified explicitly. This can be intentional, if the entire execution should be synchronous / single-threaded, as for example in parts of the Scheduler / ExecutionGraph. Flink even makes use of a main-thread executor to allow calling chained handlers in the same thread as a single-threaded RPC endpoint runs This can be unexpected, if the thread that completes the future is a sensitive thread. It may be better to use CompletableFuture.supplyAsync(value, executor) in that case, instead of future.complete(value) when an executor is available When blocking on a future awaiting completion, always supply a timeout for a result instead of waiting indefinitely, and handle timeouts explicitly. Use CompletableFuture.allOf()/anyOf(), ExecutorCompletionService, or org.apache.flink.runtime.concurrent.FutureUtils#waitForAll if you need to wait for: all the results/any of the results/all the results but handled by (approximate) completion order. 6. Dependencies and Modules # Keep the dependency footprint small The more dependencies the harder it gets for the community to manage them as a whole. Dependency management includes dependency conflicts, maintaining licenses and related notices, and handling security vulnerabilities. Discuss whether the dependency should be shaded/relocated to avoid future conflicts. Dont add a dependency for just one method Use Java built-in means if possible. If the method is Apache-licensed, you can copy the method into a Flink utility class with proper attribution. Declaration of dependencies Declare dependencies that you explicitly rely on, whether it provides classes you directly import and use or it’s something that provides a service you directly use, like Log4J. Transitive dependencies should only supply dependencies that are needed at runtime but that you don’t use yourself. [source] Location of classes in the Maven modules Whenever you create a new class, think about where to put it. A class might be used by multiple modules in the future and might belong into a common module in this case. 7. Testing # Tooling # We are moving our codebase to JUnit 5 and AssertJ as our testing framework and assertions library of choice.
Unless there is a specific reason, make sure you use JUnit 5 and AssertJ when contributing to Flink with new tests and even when modifying existing tests. Don’t use Hamcrest, JUnit assertions and assert directive. Make your tests readable and don’t duplicate assertions logic provided by AssertJ or by custom assertions provided by some flink modules. For example, avoid:
assert list.size() == 10; for (String item : list) { assertTrue(item.length() < 10); } And instead use:
assertThat(list) .hasSize(10) .allMatch(item -> item.length() < 10); Write targeted tests # Test contracts not implementations: Test that after a sequence of actions, the components are in a certain state, rather than testing that the components followed a sequence of internal state modifications.
For example, a typical antipattern is to check whether one specific method was called as part of the test A way to enforce this is to try to follow the Arrange, Act, Assert test structure when writing a unit test (https://xp123.com/articles/3a-arrange-act-assert/)
This helps to communicate the intention of the test (what is the scenario under test) rather than the mechanics of the tests. The technical bits go to a static methods at the bottom of the test class.
Example of tests in Flink that follow this pattern are:
https://github.com/apache/flink/blob/master/flink-core/src/test/java/org/apache/flink/util/LinkedOptionalMapTest.java https://github.com/apache/flink/blob/master/flink-filesystems/flink-s3-fs-base/src/test/java/org/apache/flink/fs/s3/common/writer/RecoverableMultiPartUploadImplTest.java Avoid Mockito - Use reusable test implementations # Mockito-based tests tend to be costly to maintain in the long run by encouraging duplication of functionality and testing for implementation rather than effect More details: https://docs.google.com/presentation/d/1fZlTjOJscwmzYadPGl23aui6zopl94Mn5smG-rB0qT8 Instead, create reusable test implementations and utilities That way, when some class changes, we only have to update a few test utils or mocks Avoid timeouts in JUnit tests # Generally speaking, we should avoid setting local timeouts in JUnit tests but rather depend on the global timeout in Azure. The global timeout benefits from taking thread dumps just before timing out the build, easing debugging.
At the same time, any timeout value that you manually set is arbitrary. If it’s set too low, you get test instabilities. What too low means depends on numerous factors, such as hardware and current utilization (especially I/O). Moreover, a local timeout is more maintenance-intensive. It’s one more knob where you can tweak a build. If you change the test a bit, you also need to double-check the timeout. Hence, there have been quite a few commits that just increase timeouts.
We are keeping such frameworks out of Flink, to make debugging easier and avoid dependency clashes. ↩︎
`}),e.add({id:39,href:"/zh/how-to-contribute/code-style-and-quality-formatting/",title:"Code Style and Quality Guide — Formatting Guide",section:"How to Contribute",content:` Code Style and Quality Guide Formatting Guide # 序言 # Pull Requests & Changes # 常用编码指南 # Java 语言指南 # Scala 语言指南 # 组件指南 # 格式指南 # Java Code Formatting Style # We recommend to set up the IDE to automatically check the code style. Please follow the IDE Setup Guide to set up spotless and checkstyle .
License # Apache license headers. Make sure you have Apache License headers in your files. The RAT plugin is checking for that when you build the code. Imports # Empty line before and after package declaration. No unused imports. No redundant imports. No wildcard imports. They can cause problems when adding to the code and in some cases even during refactoring. Import order. Imports must be ordered alphabetically, grouped into the following blocks, with each block separated by an empty line: <imports from org.apache.flink.*> <imports from org.apache.flink.shaded.*> <imports from other libraries> <imports from javax.*> <imports from java.*> <imports from scala.*> <static imports> Naming # Package names must start with a letter, and must not contain upper-case letters or special characters. Non-private static final fields must be upper-case, with words being separated by underscores.(MY_STATIC_VARIABLE) Non-static fields/methods must be in lower camel case. (myNonStaticField) Whitespaces # Tabs vs. spaces. We are using spaces for indentation, not tabs. No trailing whitespace. Spaces around operators/keywords. Operators (+, =, >, …) and keywords (if, for, catch, …) must have a space before and after them, provided they are not at the start or end of the line. Breaking the lines of too long statements # In general long lines should be avoided for the better readability. Try to use short statements which operate on the same level of abstraction. Break the long statements by creating more local variables, defining helper functions etc.
Two major sources of long lines are:
Long list of arguments in function declaration or call: void func(type1 arg1, type2 arg2, ...) Long sequence of chained calls: list.stream().map(...).reduce(...).collect(...)... Rules about breaking the long lines:
Break the argument list or chain of calls if the line exceeds limit or earlier if you believe that the breaking would improve the code readability If you break the line then each argument/call should have a separate line, including the first one Each new line should have one extra indentation (or two for a function declaration) relative to the line of the parent function name or the called entity Additionally for function arguments:
The opening parenthesis always stays on the line of the parent function name The possible thrown exception list is never broken and stays on the same last line, even if the line length exceeds its limit The line of the function argument should end with a comma staying on the same line except the last argument Example of breaking the list of function arguments:
public void func( int arg1, int arg2, ...) throws E1, E2, E3 { } The dot of a chained call is always on the line of that chained call proceeding the call at the beginning.
Example of breaking the list of chained calls:
values .stream() .map(...) .collect(...); Braces # Left curly braces ({) must not be placed on a new line. Right curly braces (}) must always be placed at the beginning of the line. Blocks. All statements after if, for, while, do, must always be encapsulated in a block with curly braces (even if the block contains one statement). Javadocs # All public/protected methods and classes must have a Javadoc. The first sentence of the Javadoc must end with a period. Paragraphs must be separated with a new line, and started with . Modifiers # No redundant modifiers. For example, public modifiers in interface methods. Follow JLS3 modifier order. Modifiers must be ordered in the following order: public, protected, private, abstract, static, final, transient, volatile, synchronized, native, strictfp. Files # All files must end with \\n. File length must not exceed 3000 lines. Misc # Arrays must be defined Java-style. For example, public String[] array. Use Flink Preconditions. To increase homogeneity, consistently use the org.apache.flink.Preconditions methods checkNotNull and checkArgument rather than Apache Commons Validate or Google Guava. `}),e.add({id:40,href:"/zh/how-to-contribute/code-style-and-quality-java/",title:"Code Style and Quality Guide — Java",section:"How to Contribute",content:` Code Style and Quality Guide Java # 序言 # Pull Requests & Changes # 常用编码指南 # Java 语言指南 # Scala 语言指南 # 组件指南 # 格式指南 # Java Language Features and Libraries # Preconditions and Log Statements # Never concatenate strings in the parameters Dont: Preconditions.checkState(value <= threshold, "value must be below " + threshold) Dont: LOG.debug("value is " + value) Do: Preconditions.checkState(value <= threshold, "value must be below %s", threshold) Do: LOG.debug("value is {}", value) Generics # No raw types: Do not use raw types, unless strictly necessary (sometimes necessary for signature matches, arrays). Suppress warnings for unchecked conversions: Add annotations to suppress warnings, if they cannot be avoided (such as unchecked”, or serial”). Otherwise warnings about generics flood the build and drown relevant warnings. equals() / hashCode() # equals() / hashCode() should be added when they are well defined only. They should not be added to enable a simpler assertion in tests when they are not well defined. Use hamcrest matchers in that case: https://github.com/junit-team/junit4/wiki/matchers-and-assertthat A common indicator that the methods are not well defined is when they take a subset of the fields into account (other than fields that are purely auxiliary). When the methods take mutable fields into account, you often have a design issue. The equals()/hashCode() methods suggest to use the type as a key, but the signatures suggest it is safe to keep mutating the type. Java Serialization # Do not use Java Serialization for anything !!!
Do not use Java Serialization for anything !!! !!!
Do not use Java Serialization for anything !!! !!! !!!
Internal to Flink, Java serialization is used to transport messages and programs through RPC. This is the only case where we use Java serialization. Because of that, some classes need to be serializable (if they are transported via RPC).
Serializable classes must define a Serial Version UID:
private static final long serialVersionUID = 1L;
The Serial Version UID for new classes should start at 1 and should generally be bumped on every incompatible change to the class according to the Java serialization compatibility definition (i.e: changing the type of a field, or moving the position of a class in the class hierarchy).
Java Reflection # Avoid using Javas Reflection API
Javas Reflection API can be a very useful tool in certain cases but in all cases it is a hack and one should research for alternatives. The only cases where Flink should use reflection are Dynamically loading implementations from another module (like webUI, additional serializers, pluggable query processors). Extracting types inside the TypeExtractor class. This is fragile enough and should not be done outside the TypeExtractor class. Some cases of cross-JDK version features, where we need to use reflection because we cannot assume a class/method to be present in all versions. If you need reflection for accessing methods or fields in tests, it usually indicates some deeper architectural issues, like wrong scoping, bad separation of concerns, or that there is no clean way to provide components / dependencies to the class that is tested Collections # ArrayList and ArrayDeque are almost always superior to LinkedList, except when frequently insert and deleting in the middle of the list For Maps, avoid patterns that require multiple lookups contains() before get() get() and check null contains() before put() putIfAbsent() or computeIfAbsent() Iterating over keys, getting values iterate over entrySet() Set the initial capacity for a collection only if there is a good proven reason for that, otherwise do not clutter the code. In case of Maps it can be even deluding because the Map’s load factor effectively reduces the capacity. Java Optional # Use @Nullable annotation where you do not use Optional for the nullable values. If you can prove that Optional usage would lead to a performance degradation in critical code then fallback to @Nullable. Always use Optional to return nullable values in the API/public methods except the case of a proven performance concern. Do not use Optional as a function argument, instead either overload the method or use the Builder pattern for the set of function arguments. Note: an Optional argument can be allowed in a private helper method if you believe that it simplifies the code (example). Do not use Optional for class fields. Lambdas # Prefer non-capturing lambdas (lambdas that do not contain references to the outer scope). Capturing lambdas need to create a new object instance for every call. Non-capturing lambdas can use the same instance for each invocation.
dont:
map.computeIfAbsent(key, x -> key.toLowerCase()) do:
map.computeIfAbsent(key, k -> k.toLowerCase()); Consider method references instead of inline lambdas
dont:
map.computeIfAbsent(key, k-> Loader.load(k)); do:
map.computeIfAbsent(key, Loader::load); Java Streams # Avoid Java Streams in any performance critical code. The main motivation to use Java Streams would be to improve code readability. As such, they can be a good match in parts of the code that are not data-intensive, but deal with coordination.. Even in the latter case, try to limit the scope to a method, or a few private methods within an internal class. `}),e.add({id:41,href:"/zh/how-to-contribute/code-style-and-quality-pull-requests/",title:"Code Style and Quality Guide — Pull Requests & Changes",section:"How to Contribute",content:` Code Style and Quality Guide Pull Requests & Changes # 序言 # Pull Requests & Changes # 常用编码指南 # Java 语言指南 # Scala 语言指南 # 组件指南 # 格式指南 # Rationale: We ask contributors to put in a little bit of extra effort to bring pull requests into a state that they can be more easily and more thoroughly reviewed. This helps the community in many ways:
Reviews are much faster and thus contributions get merged sooner. We can ensure higher code quality by overlooking fewer issues in the contributions. Committers can review more contributions in the same time, which helps to keep up with the high rate of contributions that Flink is experiencing Please understand that contributions that do not follow this guide will take longer to review and thus will typically be picked up with lower priority by the community. That is not ill intend, it is due to the added complexity of reviewing unstructured Pull Requests.
1. JIRA issue and Naming # Make sure that the pull request corresponds to a JIRA issue.
Exceptions are hotfixes, like fixing typos in JavaDocs or documentation files.
Name the pull request in the form [FLINK-XXXX][component] Title of the pull request, where FLINK-XXXX should be replaced by the actual issue number. The components should be the same as used in the JIRA issue.
Hotfixes should be named for example [hotfix][docs] Fix typo in event time introduction or [hotfix][javadocs] Expand JavaDoc for PuncuatedWatermarkGenerator.
2. Description # Please fill out the pull request template to describe the contribution. Please describe it such that the reviewer understands the problem and solution from the description, not only from the code.
A stellar example of a well-described pull request is https://github.com/apache/flink/pull/7264
Make sure that the description is adequate for the problem solved by PR. Small changes do not need a wall of text. In ideal cases, the problem was described in the Jira issue and the description be mostly copied from there.
If additional open questions / issues were discovered during the implementation and you made a choice regarding those, describe them in the pull request text so that reviewers can double check the assumptions. And example is in https://github.com/apache/flink/pull/8290 (Section “Open Architecture Questions”).
3. Separate Refactoring, Cleanup and Independent Changes # NOTE: This is not an optimization, this is a critical requirement.
Pull Requests must put cleanup, refactoring, and core changes into separate commits. That way, the reviewer can look independently at the cleanup and refactoring and ensure that those changes to not alter the behavior. Then the reviewer can look at the core changes in isolation (without the noise of other changes) and ensure that this is a clean and robust change.
Examples for changes that strictly need to go into a separate commit include
Cleanup, fixing style and warnings in pre-existing code Renaming packages, classes, or methods Moving code (to other packages or classes) Refactoring structure or changing design patterns Consolidating related tests or utilities Changing the assumptions in existing tests (add a commit message that describes why the changed assumptions make sense). There should be no cleanup commits that fix issues that have been introduced in previous commits of the same PR. Commits should be clean in themselves.
In addition, any larger contributions should split the changes into a set of independent changes that can be independently reviewed.
Two great examples of splitting issues into separate commits are:
https://github.com/apache/flink/pull/6692 (splits cleanup and refactoring from main changes) https://github.com/apache/flink/pull/7264 (splits also main changes into independently reviewable pieces) If a pull request does still contain big commits (e.g. a commit with more than 1000 changed lines), it might be worth thinking about how to split the commit into multiple subproblems, as in the example above.
4. Commit Naming Conventions # Commit messages should follow a similar pattern as the pull request as a whole: [FLINK-XXXX][component] Commit description.
In some cases, the issue might be a subtask here, and the component may be different from the Pull Requests main component. For example, when the commit introduces an end-to-end test for a runtime change, the PR would be tagged as [runtime], but the individual commit would be tagged as [e2e].
Examples for commit messages:
[hotfix] Fix update_branch_version.sh to allow version suffixes [hotfix] [table] Remove unused geometry dependency [FLINK-11704][tests] Improve AbstractCheckpointStateOutputStreamTestBase [FLINK-10569][runtime] Remove Instance usage in ExecutionVertexCancelTest [FLINK-11702][table-planner-blink] Introduce a new table type system 5. Changes to the observable behavior of the system # Contributors should be aware of changes in their PRs that break the observable behavior of Flink in any way because in many cases such changes can break existing setups. Red flags that should raise questions while coding or in reviews with respect to this problem are for example:
Assertions have been changed to make tests pass again with the breaking change. Configuration setting that must suddenly be set to (non-default) values to keep existing tests passing. This can happen in particular for new settings with a breaking default. Existing scripts or configurations have to be adjusted. `}),e.add({id:42,href:"/zh/how-to-contribute/code-style-and-quality-scala/",title:"Code Style and Quality Guide — Scala",section:"How to Contribute",content:` Code Style and Quality Guide Scala # 序言 # Pull Requests & Changes # 常用编码指南 # Java 语言指南 # Scala 语言指南 # 组件指南 # 格式指南 # Scala 语言特性 # 在哪儿使用(和不使用) Scala # 对于 Scala API 或者纯 Scala libraries,我们会选择使用 Scala
core API 运行时的组件中,我们不使用 Scala。我们的目标是从这些组件中删除现有的 Scala 使用(代码和依赖项)。
这并不是因为我们不喜欢 Scala,而是考虑到“用正确的工具做正确的事”的结果(见下文)。
对于 API,我们使用 Java 开发基础内容,并在上层使用 Scala
这在传统上为 Java Scala 提供了最佳的互通性 这意味着要致力于保持 Scala API 的更新 为什么我们不在 Core API Runtime 中使用 Scala
过去的经验显示, Scala 在功能上的变化太快了。对于 Flink 社区来说,每次 Scala 版本升级都是一个比较棘手的处理过程。 Scala 并不总能很好地与 Java 的类交互,例如 Scala 的可见性范围的工作方式不同,而且常常向 Java 消费者公开的内容比预期的要多。 由于使用 Scala ,所以 Flink artifact/dependency 管理增加了一层额外的复杂性。 * 我们希望通过接口抽象,同时也在运行时保留像 Akka 这样依赖 Scala 的库,然后将它们加载到单独的类加载器中,以保护它们并避免版本冲突。 Scala 让懂 Scala 的程序员很容易编写代码,而对于不太懂 Scala 的程序员来说,这些代码很难理解。对于一个拥有不同经验水平的广大社区的开源项目来说,这尤其棘手。解决这个问题意味着大量限制 Scala 特性集,这首先就违背了使用 Scala 的很多目的。 API 等价 # 保持 Java API Scala API 在功能和代码质量方面的同步。
Scala API 也应该涵盖 Java API 的所有特性。
Scala API 应该有一个“完整性测试”,就如下面 DataStream API 的示例中的一样: https://github.com/apache/flink/blob/master/flink-streaming-scala/src/test/scala/org/apache/flink/streaming/api/scala/StreamingScalaAPICompletenessTest.scala
语言特性 # 避免 Scala 隐式转换。 Scala 的隐式转换应该只用于面向用户的 API 改进,例如 Table API 表达式或类型信息提取。 不要把它们用于内部 magic”。 为类成员添加显式类型。 对于类字段和方法返回类型,不要依赖隐式类型推断:
不要这样:
var expressions = new java.util.ArrayList[String]() 要这样:
var expressions: java.util.List[String] = new java.util.ArrayList[]() 堆栈上局部变量的类型推断是可以的。
用严格的可见性。 避免使用 Scala 的包私有特性(如 private[flink]),而是使用常规 private/protected 替代。 请注意:在 Java 中, private[flink] protected 的成员是公开的。 请注意:在 Flink 提供的示例中, private[flink] 仍然会暴露所有成员。 编码格式 # 使用换行来构造你的代码。
Scala 的函数性质允许长的转换链 (x.map().map().foreach()). 为了强制让实现者构造其代码,因此将行长度限制为 100 个字符以内。 为了更好的可维护性,每次转换使用一行。 `}),e.add({id:43,href:"/zh/flink-packages/",title:"flink-packages.org",section:"Apache Flink Documentation",content:` What is the Flink Kubernetes Operator? # All information on the flink-packages can be found on the flink-packages website.
`}),e.add({id:44,href:"/zh/what-is-flink-ml/",title:"What is Flink ML?",section:"Apache Flink Documentation",content:` What is Stateful Functions? # All information on Flink ML can be found on the Flink ML website.
`}),e.add({id:45,href:"/zh/what-is-flink-table-store/",title:"What is Paimon(incubating) (formerly Flink Table Store)?",section:"Apache Flink Documentation",content:` What is Apache Paimon (formerly Flink Table Store)? # The Flink Table Store had joined Apache Incubator as Apache Paimon(incubating). All information on the Apache Paimon(incubating) can be found on the Paimon website.
`}),e.add({id:46,href:"/zh/what-is-stateful-functions/",title:"What is Stateful Functions?",section:"Apache Flink Documentation",content:` What is Stateful Functions? # All information on Stateful Functions can be found on the Stateful Functions project website.
`}),e.add({id:47,href:"/zh/what-is-the-flink-kubernetes-operator/",title:"What is the Flink Kubernetes Operator?",section:"Apache Flink Documentation",content:` What is the Flink Kubernetes Operator? # All information on the Flink Kubernetes Operator can be found on the Flink Kubernetes Operator website.
`}),e.add({id:48,href:"/zh/material/",title:"素材",section:"Apache Flink Documentation",content:` Material # Apache Flink Logos # 我们提供不同大小、不同格式的 Apache Flink logo。你可以 下载所有 logo (7.4 MB)或者从当前页面选择你需要的 logo
便携式网络图像格式 (PNG) # 彩色 logo 白色填充 logo 黑色轮廓 logo 尺寸 (px): 50x50, 100x100, 200x200, 500x500, 1000x1000 尺寸 (px):: 50x50, 100x100, 200x200, 500x500, 1000x1000
尺寸 (px):: 50x50, 100x100, 200x200, 500x500, 1000x1000 你可以在这个目录 寻找更多 PNG 格式的 logo 或者 下载所有 logo (7.4 MB)。
可扩展矢量图像格式 (SVG) # 彩色 logo 白色填充 logo 黑色轮廓 logo 带黑色文本的彩色 logo (color_black.svg) 白色填充 logo (white_filled.svg) 黑色轮廓 logo (black_outline.svg) 你可以在这个目录 寻找更多 SVG 格式的 logo 或者下载所有 logo (7.4 MB).
Photoshop 格式 (PSD) # 你也可以下载 PSD 格式的 logo:
彩色 logo: 1000x1000. 带文字的黑色轮廓 logo: 1000x1000, 5000x5000. 你可以在这个目录 寻找更多 PSD 格式的 logo 或者下载所有 logo (7.4 MB).
配色方案 # 你可以使用我们提供的配色方案,这些方案包含了 Flink logo 的部分颜色。
PDF 配色方案 Powerpoint 配色方案 `})})()