目的

本文档的目的是为下游开发人员提供清晰的参考,以了解构建应用程序时可以对Hadoop源代码有哪些期望。

该文档主要是对Hadoop兼容性准则的概括,因此侧重于不同Hadoop接口在不同版本之间的兼容性保证。

目标受众

本文档的目标受众是任何正在开发与Apache Hadoop相关的项目或应用程序的开发人员,无论依赖于源代码本身,构建产物,还是与运行中的系统进行交互。

Hadoop发布

Hadoop开发社区定期发布新的Hadoop版本,以引入新功能并修复现有问题。发布分为三类:

  • 主要版本(Major): 主要版本通常包括重要的新功能,通常代表着最大的升级兼容性风险。主要版本会递增版本号的第一个数字,例如从2.8.2升级到3.0.0。

  • 次要版本(Minor): 次要版本通常包括一些新功能以及修复一些显著问题。在大多数情况下,次要版本不应构成太大的升级风险。次要版本会递增版本号的中间数字,例如从2.8.2升级到2.9.0。

  • 维护版本(Maintenance): 维护版本不应包括任何新功能。维护版本的目的是解决开发社区认为足够重要以值得推送新版本来解决的一组问题。维护版本应该几乎没有升级风险。维护版本会递增版本号的最后一个数字,例如从2.8.2升级到2.8.3。

使用Hadoop API

在编写调用属于Apache Hadoop的方法或使用其类的软件时,开发人员应遵循以下准则。未能遵循这些准则可能导致从一个Hadoop版本过渡到另一个版本时出现问题。

隐私

包、类和方法可以使用面向受众的注释。隐私级别有三种:Public(公共)、Limited-Private(有限私有)和Private(私有)。下游开发人员只应使用标记为Public的包、类、方法和字段。未标记为Public的包、类和方法被视为Hadoop内部使用,仅供其他Hadoop组件使用。

如果元素的注释与其包含元素的注释相冲突,则最严格的注释优先。例如,如果一个Private方法包含在一个Public类中,那么该方法应被视为Private。如果一个Public方法包含在一个Private类中,该方法应被视为Private。

如果方法没有隐私注释,则它从其类继承其隐私。如果类没有隐私,则它从其包继承其隐私。如果包没有隐私,则应假定其为Private。

稳定性

包、类和方法可以使用稳定性注释。有三类稳定性:Stable(稳定)、Evolving(演变)和Unstable(不稳定)。稳定性注释确定何时允许进行不兼容的更改。Stable表示在主要版本之间不允许进行不兼容的更改。Evolving表示在次要版本之间不允许进行不兼容的更改。Unstable表示可以在任何时候进行不兼容的更改。作为下游开发人员,最好避免Unstable的API,并在可能的情况下优先选择Stable的API。

如果方法没有稳定性注释,则它从其类继承其稳定性。如果类没有稳定性,则它从其包继承其稳定性。如果包没有稳定性,则应假定其为Unstable。

发布和稳定性

根据上述API稳定性规则,新版本允许进行如下API更改:

  • 发布类型: 允许稳定API的更改,允许在次要版本之间进行演变API的更改,允许在任何时候进行不稳定API的更改。

  • 主要版本: 允许打破任何API的兼容性,尽管Hadoop开发社区努力保持兼容性,甚至跨主要版本。

  • 次要版本: 不允许进行稳定API的更改,允许在次要版本之间进行演变API的更改,允许在任何时候进行不稳定API的更改。

  • 维护版本: 不允许进行稳定API的更改,不允许进行演变API的更改,允许在任何时候进行不稳定API的更改。

请注意,主要版本允许打破任何API的兼容性,即使Hadoop开发社区努力保持尽可能的兼容性,甚至跨主要版本。此外,Unstable API可能随时进行更改而无需通知。

弃用

被注释为@Deprecated的类或方法不再安全使用。被弃用的元素应该继续运行,但可能会在后续的版本中被删除。稳定性注释将确定可以删除弃用元素的最早版本。

Stable元素在下一个主要版本之前不能被删除。Evolving元素在下一个次要版本之前不能被删除。Unstable元素可能随时被删除,并且通常在删除之前不会标记为弃用。

Stable和Evolving元素在可以删除之前必须在一个完整的主要版本或次要版本(分别)中被标记为弃用。例如,如果一个Stable在Hadoop 3.1中被标记为弃用,则不能在Hadoop 5.0之前被删除。

语义兼容性

Apache Hadoop开发社区努力确保API的行为在版本之间保持一致,尽管为了修复正确性可能会导致行为变化。API的JavaDocs被认为是对API期望行为的主要权威。

在JavaDocs不足或缺失的情况下,单元测试被认为是期望行为的备用权威。在没有单元测试的情况下,应该从命名中推断出预期的行为。

尽量避免下游开发人员查看API本身的源代码以确定预期的行为,因为这种方法可能会对Hadoop开发社区明确规定的预期行为产生依赖于实现细节的依赖。

在JavaDocs不足以推断预期行为的情况下,强烈鼓励下游开发人员提出Hadoop JIRA请求添加或改进JavaDocs。

请注意,由于修复正确性原因所做的修复可能会导致API的预期行为发生更改,尽管此类更改预计将附有澄清新行为的文档。

Apache Hadoop开发社区尽力保持在版本之间对端用户应用程序的二进制兼容性。理想情况下,升级到新的Hadoop版本时不需要更新应用程序,假设应用程序不使用Private、Limited-Private或Unstable API。特别是,MapReduce应用程序保证在版本之间具有二进制兼容性。

兼容性问题

Hadoop兼容性规范规定了Hadoop开发社区应该遵守的标准,但出于各种原因,源代码可能无法达到兼容性规范的理想标准。

下游开发人员可能会遇到的两个常见问题是:

  1. 需要用于应用程序开发的API不是Public的。
  2. 下游应用程序依赖的Public API出现意外和不兼容的更改。

在这两种情况下,强烈鼓励下游开发人员向Hadoop开发社区提出问题,可以通过发送电子邮件到适当的开发者邮件列表或提出JIRA等方式。开发社区对反馈表示感激。

无论何时在开发应用程序时遇到问题,都鼓励下游开发人员与Hadoop开发社区联系。

很有可能,如果对一个开发人员有问题,那么对许多开发人员而言也是一个问题。

使用FileSystem API

在使用Hadoop中的流(例如,FSDataOutputStream)的特定情况下,应用程序可以使用StreamCapabilities类的方法以编程方式查询流的功能。动态调整到流的功能可以使应用程序在面对不断变化的实现和环境时更加健壮。

使用Hadoop REST API

Hadoop REST API是各种下游和内部应用程序和服务的主要接口。为了支持REST客户端,Hadoop REST API进行了版本化,并且在版本内部不会发生不兼容的更改。在REST端点版本内,端点本身以及支持的参数列表和端点输出都禁止不兼容的更改。然而,请注意,引入新字段和其他可添加的更改被视为兼容的更改,因此REST API的任何使用者应该足够灵活,以忽略未知字段。

REST API版本是一个数字,与Hadoop版本号无关。版本号以’v’为前缀编码在端点URL中,例如’v1’。只能在次要或主要版本中引入新的REST端点版本。只有在被标记为完全主要版本之前,才能删除REST端点版本。

使用Hadoop输出

Hadoop生成各种可能由应用程序客户端或下游库消耗的输出。在消耗Hadoop输出时,请考虑以下几点:

  1. Hadoop日志输出不会在维护版本中更改,除非它解决了正确性问题。虽然日志输出可以直接被软件消耗,但它主要用于人类读者。

  2. Hadoop生成各种操作的审计日志。审计日志旨在是可机器读取的,尽管添加新记录和字段被认为是兼容的更改。任何审计日志的使用者都应该允许意外的记录和字段。审计日志格式在主要版本之间不能发生不兼容的更改。

  3. Hadoop生成的指标数据主要用于自动消耗。在主要版本之间,度量格式不得以不兼容的方式更改,但可以随时兼容地添加新的记录和字段。度量数据的使用者应该允许未知的记录和字段。

使用Hadoop数据

Hadoop用于存储数据的二进制文件格式,例如序列文件、HAR文件等,在次要版本之间保证保持兼容性。此外,在主要版本之间进行更改时,必须保持向后和向前的兼容性。请注意,只有序列文件格式保证不发生不兼容的更改,而不是其中包含的序列化类。

除了由操作产生的数据外,Hadoop还以各种格式维护其状态信息,例如HDFS元数据存储、YARN资源管理器状态存储和YARN联邦状态存储。所有Hadoop内部数据存储都被视为内部和Hadoop私有。下游开发人员不应尝试从Hadoop状态存储中消耗数据,因为数据和/或数据格式可能会不可预测地更改。

使用Hadoop CLI进行操作自动化

构成Hadoop命令行界面的一组工具既适用于最终用户使用,也适用于创建执行CLI工具并解析输出的下游开发人员。因此,Hadoop CLI工具被视为一个接口,并在主要版本之间保持稳定。在主要版本之间,不会删除或在语义上更改CLI工具选项。同样,CLI工具的输出将在一个主要版本号内保持不变。请注意,对CLI工具输出的任何更改都被视为不兼容的更改,因此在主要版本之间,CLI输出不会更改。请注意,CLI工具输出与CLI工具生成的日志输出是不同的。日志输出不适用于自动消耗,并且可以随时更改。

使用Hadoop Web UI

Hadoop公开的Web UI仅供人类使用。不支持通过Web UI对数据进行抓取。在各个Web UI中显示的数据之间不会做任何兼容性的保证。

处理Hadoop配置

Hadoop使用两种主要形式的配置文件:XML配置文件和日志配置文件。

XML配置文件

XML配置文件包含一组属性,以名称-值对的形式存在。属性的名称和含义由Hadoop定义,并保证在次要版本之间保持稳定。只有在主要版本中才能删除属性,而且只有在它被标记为至少一个完整主要版本的过时属性时才能删除。大多数属性都有一个默认值,如果在XML配置文件中未明确设置该属性,则将使用默认属性值。默认属性值在维护版本期间不会更改。有关各种Hadoop组件支持的属性的详细信息,请参阅组件文档。

下游开发人员和用户可以将自己的属性添加到XML配置文件中,供其工具和应用程序使用。虽然Hadoop对定义新属性没有正式的限制,但与Hadoop定义的属性冲突的新属性可能导致意外和不希望的结果。建议用户避免使用与Hadoop定义属性的命名空间冲突的自定义配置属性名称,因此应避免使用Hadoop使用的任何前缀,例如hadoop、io、ipc、fs、net、ftp、ha、file、dfs、mapred、mapreduce和yarn。

日志配置文件

Hadoop守护程序和CLI生成的日志输出受一组配置文件的控制。这些文件控制将由Hadoop各个组件输出的日志消息的最低级别,以及这些消息将如何存储以及存储在何处。在次要版本之间,不会对减少、消除或重定向日志消息的日志配置进行更改。

其他配置文件

Hadoop使用许多其他类型的配置文件,采用各种格式,例如JSON资源配置文件或XML公平调度器配置。

在次要版本内,将不会引入对配置文件格式的不兼容更改。即使在次要版本之间,如果可能的话,也将避免引入不兼容的配置文件格式更改。

使用和消费Hadoop构件

源代码和配置文件

作为Hadoop的下游开发者或使用者,可以访问Hadoop平台的所有元素,包括源代码、配置文件、构建构件等。尽管平台的开放性允许这样做,但开发者不应该在这些Hadoop内部细节上创建依赖关系,因为它们可能随时更改。然而,Hadoop开发社区将尝试在主要版本内保持现有结构的稳定性。

Hadoop配置文件、作业历史信息(由作业历史服务器使用)的位置和一般结构将在维护版本之间保持不变。

构建构件

Hadoop构建过程生成的构建构件,例如JAR文件,可能随时发生更改,不应视为可靠,除非是客户端构件。客户端构件及其内容将在主要版本内保持兼容。Hadoop开发社区的目标是允许应用程序代码在次要版本之间继续保持不变,并在可能的情况下在主要版本之间保持不变。当前的客户端构件列表如下:

  • hadoop-client
  • hadoop-client-api
  • hadoop-client-minicluster
  • hadoop-client-runtime
  • hadoop-hdfs-client
  • hadoop-hdfs-native-client
  • hadoop-mapreduce-client-app
  • hadoop-mapreduce-client-common
  • hadoop-mapreduce-client-core
  • hadoop-mapreduce-client-jobclient
  • hadoop-mapreduce-client-nativetask
  • hadoop-yarn-client

环境变量

一些Hadoop组件通过环境变量接收信息。例如,大多数Hadoop进程都将HADOOP_OPTS环境变量解释为新启动JVM时要使用的附加JVM参数的字符串。在次要版本之间,Hadoop解释环境变量的方式不会以不兼容的方式更改。换句话说,将相同的值放入相同的变量中,应该在同一主要版本的所有Hadoop版本中产生相同的结果。

库依赖

Hadoop依赖于大量第三方库进行运行。尽可能,Hadoop开发社区致力于隐藏这些依赖性,但在Hadoop 3之前,一些常见的库,例如Guava,可能会在Hadoop和下游应用程序之间引起重大兼容性问题,如果这些依赖性向下暴露。尽管如此,Hadoop确实会向下暴露一些依赖性。在主要版本之间,Hadoop将不会通过客户端构件引入新的依赖关系。

常见的下游反模式是使用hadoop classpath的输出来设置下游应用程序的类路径,或将包含在Hadoop中的所有第三方JAR添加到下游应用程序的类路径。这种做法在下游应用程序与Hadoop的第三方依赖之间创建了紧密的耦合,导致难以在Hadoop的依赖关系发生更改时进行维护的脆弱应用程序。强烈不建议这种做法。

Hadoop依赖于Java虚拟机进行运行,这可能会影响下游应用程序。为了最小化中断,支持的JVM的最低版本在Hadoop的主要版本之间不会更改。如果当前支持的JVM版本在主要版本之间变得不受支持,则可以在次要版本中更改最低支持的JVM版本。

Hadoop还包括一些本机组件,包括压缩、容器执行程序二进制文件和各种本机集成。这些本机组件引入了Hadoop的一组本机依赖关系。本机依赖关系的集合可以在次要版本中更改,但Hadoop开发社区将尽量限制对次要版本更改的任何依赖版本更改。

硬件和操作系统依赖关系

Hadoop目前由Hadoop开发社区在x86和AMD处理器上支持的Linux和Windows上支持。这些操作系统和处理器可能在可预见的未来继续得到支持。如果支持计划发生变化,将记录要在至少一个完整的次要版本(理想情况下是完整的主要版本)中弃用的OS或处理器,然后才能实际弃用。Hadoop可能在其他操作系统和处理器体系结构上运行,但在出现问题时社区可能无法提供帮助。

对于Hadoop守护程序所需的最低资源在版本之间如何更改,即使是维护版本,也没有保证。尽管如此,Hadoop开发社区将尽力避免在次要版本内增加要求。

任何由Hadoop支持的文件系统,例如通过FileSystem API,通常将在一个主要版本中继续受到支持。在一个主要版本内,唯一支持的文件系统不再受支持的情况是,如果为替代客户端实现提供了干净的迁移路径。

参考资料

https://hadoop.apache.org/docs/stable/hadoop-project-dist/hadoop-common/DownstreamDev.html