本文档阐述了Apache Hadoop项目的兼容性目标。列举了影响Hadoop开发者、下游项目和终端用户的不同Hadoop版本间的兼容性类型。针对每种兼容性类型,本文档将:
所有Hadoop接口都根据目标用户群体和稳定性进行分类,以保持与之前版本的兼容性。有关分类的详细信息,请参阅Hadoop接口分类法。
本文档面向Hadoop开发者社区。文档阐述了评估Hadoop项目变更时应遵循的标准。为确保终端用户和第三方开发者对跨版本兼容性保持信心,开发者社区必须确保开发工作符合这些政策规范。项目提交者有责任验证所有变更是否保持兼容性,或明确标注为不兼容变更。
在组件内部,Hadoop开发者可以自由使用私有和受限私有API,但当使用来自不同模块的组件时,Hadoop开发者应遵循与第三方开发者相同的准则:除非明确允许,否则不应使用私有或受限私有接口,并尽可能优先选择稳定接口而非演进中或不稳定接口。若无法避免,首选解决方案是扩大API的受众范围,而非对这些兼容性准则引入或延续例外情况。在使用Maven模块时,Hadoop开发者应尽可能对其他Maven模块中的组件保持同等程度的约束。
最重要的是,Hadoop开发者必须注意其变更带来的影响。稳定接口在主要版本之间不得更改。演进中的接口在次要版本之间不得更改。新类和组件必须根据目标受众和稳定性进行适当标记。有关何时适用各种标记的详细信息,请参阅Hadoop接口分类。一般来说,所有新接口和API都应采用最严格的标记(例如私有不稳定),但不应限制接口或API的预期用途。
本文档根据不同兼容性问题划分为多个章节。每个章节开篇会解释该部分兼容性的含义、其重要性以及支持兼容性的目标意图。随后的"政策"部分则具体阐述相关管理政策。
关键词"MUST"、"MUST NOT"、"REQUIRED"、"SHALL"、"SHALL NOT"、"SHOULD"、"SHOULD NOT"、"RECOMMENDED"、"MAY"和"OPTIONAL"应按照RFC 2119中的描述进行解释。
Java API提供了@Deprecated注解来标记一个API元素为已弃用。该注解的标准含义是该API元素不应再使用,并可能在后续版本中被移除。
在所有情况下,从API中移除元素都属于不兼容性变更。元素的稳定性级别将决定何时允许进行此类变更。Stable级别的元素必须在完整的主版本发布周期内标记为弃用状态后才可以移除,且不得在次要版本或维护版本中移除。Evolving级别的元素必须在完整的次要版本发布周期内标记为弃用状态后才可以移除,且不得在维护版本中移除。Unstable级别的元素可随时移除。在可能的情况下,Unstable级别的元素应在移除前至少保持一个版本的弃用状态。例如,若某个方法在Hadoop 2.8中被标记为弃用,则该方法的移除最早只能在Hadoop 4.0版本中进行。
Stable API元素在被标记为废弃(通过@Deprecated注解或其他适当文档)后,必须经过一个完整的主版本周期才能移除。如果某个API元素在引入时就被标记为废弃(表明这是一个计划移除的临时措施),则可以在下一个主版本中移除该元素。当修改Stable API时,开发者应当优先考虑引入新方法或端点并废弃现有方法,而不是对现有方法或端点进行不兼容的更改。
开发者应当使用@InterfaceAudience和@InterfaceStability注解来标注所有Hadoop接口和类,以描述其目标受众和稳定性。
注解可以应用于包、类或方法级别。如果方法没有隐私或稳定性注解,则应从所属类继承其目标受众或稳定性级别。如果类没有隐私或稳定性注解,则应从所属包继承其目标受众或稳定性级别。如果包没有隐私或稳定性注解,则应分别假定为Private和Unstable。
当元素的受众范围或稳定性注解与其父元素(无论是显式还是继承的)对应的注解发生冲突时,该元素的受众范围或稳定性(分别)应由限制性更强的注解决定。例如,如果一个Private方法包含在Public类中,那么该方法应被视为Private。如果一个Public方法包含在Private类中,该方法也应被视为Private。
兼容性策略应由相关包、类、成员变量或方法注解确定。
注意:从proto文件生成的API必须兼容滚动升级。有关更多详情,请参阅有线协议兼容性部分。因此,API与有线协议的兼容性策略必须保持一致。
Apache Hadoop致力于确保API行为在版本迭代中保持一致,尽管出于正确性考虑的行为变更可能导致功能变化。API行为规范应以完整存在的JavaDoc API文档为准。若无JavaDoc API文档,则应以相关单元测试预期的行为作为规范标准。当既无JavaDoc API文档又无单元测试覆盖时,预期行为应被视为不言自明,且应假定为接口命名所隐含的最小功能集。社区正在推进更严格地规范部分API,并通过增强测试套件来验证是否符合规范要求,这实际上为可轻松测试的行为子集创建了正式规范。
任何API的行为都可以根据其稳定性进行更改以修正错误行为,此类变更需伴随更新现有文档和测试,以及/或添加新的文档或测试。
Apache Hadoop的修订版本应保持二进制兼容性,以确保最终用户应用程序无需任何修改即可继续运行。同一主版本内的次要Apache Hadoop修订必须保持兼容性,使得现有的MapReduce应用程序(例如最终用户应用程序及Apache Pig、Apache Hive等项目)、现有的YARN应用程序(例如最终用户应用程序及Apache Spark、Apache Tez等项目)以及直接访问HDFS的应用程序(例如最终用户应用程序及Apache HBase、Apache Flume等项目)在与原始构建目标相同主版本的任何Apache Hadoop集群使用时,无需修改或重新编译即可正常运行。
特别是对于MapReduce应用程序,即使用org.apache.hadoop.mapred和/或org.apache.hadoop.mapreduce API的应用程序,开发者社区应支持跨主要版本的二进制兼容性。MapReduce API应在各主要版本间保持兼容性支持。详情请参阅Compatibility for MapReduce applications between hadoop-1.x and hadoop-2.x。
某些应用程序可能会受到磁盘布局变更或其他内部变更的影响。请参阅以下章节,了解如何处理非API接口的不兼容变更的相关策略。
Hadoop包含多个原生组件,包括压缩功能、容器执行器二进制文件以及各种原生集成。这些原生组件为Hadoop引入了一系列编译时和运行时的原生依赖项,例如cmake、gcc、zlib等。这组原生依赖项是Hadoop ABI的组成部分。
Hadoop在编译时和/或运行时依赖的本地组件的最低要求版本应被视为Evolving。在主要版本内的次要版本之间,最低要求版本不应增加,但出于安全问题、许可问题或其他原因可能会进行更新。当Hadoop依赖的本地组件必须在主要版本内的次要版本之间更新时,在可能的情况下,更改应仅调整组件的次要版本而不改变主要版本。
线缆兼容性关注的是Hadoop进程之间“通过线缆”传输的数据。Hadoop在大多数RPC通信中使用Protocol Buffers。保持兼容性需要禁止如下所述的修改。非RPC通信也应考虑在内,例如使用HTTP传输HDFS镜像作为快照的一部分或传输MapReduce映射任务输出。这些通信可分为以下几类:
Apache Hadoop的组件可能包含依赖项,这些依赖项涉及它们自己的协议,例如Zookeeper、S3、Kerberos等。这些协议依赖项应被视为内部协议,并遵循相同的管理策略。
除了协议本身的兼容性外,维护跨版本通信还需要确保支持的传输方式也保持稳定。传输变更最可能的来源是安全传输协议,例如SSL。将服务从SSLv2升级到SSLv3可能会破坏现有的SSLv2客户端。在任何主要版本的小版本更新中,所支持传输协议的最低主版本号不应增加,但出于安全问题、许可问题或其他原因可能会进行更新。当必须在主要版本的小版本更新中升级传输协议时,在可能的情况下,变更应仅调整组件的次版本号而不改变主版本号。
服务端口被视为传输机制的一部分。必须保持默认服务端口号一致,以防止客户端中断。
Hadoop有线协议在.proto(ProtocolBuffers)文件中定义。客户端-服务器和服务器-服务器协议应根据其.proto文件中注明的受众和稳定性分类进行分类。如果未提供分类,则应假定协议为Private和Stable。
对.proto文件的以下更改应被视为兼容:
对.proto文件的以下修改应被视为不兼容:
对.proto文件的以下修改应被视为不兼容:
未通过.proto文件定义的Hadoop有线协议应被视为私有且稳定。
除了Stable状态所施加的限制外,Hadoop的通信协议还必须遵循以下规则,确保在主版本内的小版本更新中保持向前兼容:
新的传输机制只能在主版本或次版本变更时引入。现有传输机制必须在主版本内的次版本之间持续得到支持。默认服务端口号应被视为稳定。
REST API兼容性适用于公开的REST端点(URL)和响应数据格式。Hadoop REST API专门设计用于跨版本(包括主要版本)的客户端稳定使用。就本文档而言,公开的REST API是指在公共文档中记录的API。以下是非详尽列出的公开REST API:
每个API都有一个特定于API的版本号。任何不兼容的变更都必须增加API版本号。
公开的Hadoop REST API应被视为Public和Evolving。关于API版本号,公开的Hadoop REST API应被视为Public和Stable,即不允许在同一个API版本号内进行不兼容的更改。REST API版本必须被标记为已弃用,并经过一个完整的主要版本周期后才能被移除。
Hadoop守护进程和命令行界面通过Log4j生成日志输出,旨在帮助管理员和开发人员理解并排查集群行为问题。日志消息主要供人工查阅,同时也支持自动化使用场景。
多个组件配备了审计日志系统,以机器可读的格式记录系统信息。对该数据格式的不兼容更改可能会破坏现有的自动化工具。对于审计日志而言,任何导致现有解析器无法解析日志的格式变更都属于不兼容变更。
虽然Metrics API的兼容性受Java API兼容性约束,但Hadoop公开的Metrics数据格式必须保持兼容,以确保数据消费者(例如自动化任务)能够正常使用。
用户和系统级别的数据(包括元数据)以各种文件格式存储。对元数据或用于存储数据/元数据的文件格式的更改可能导致版本间不兼容。以下将分别讨论各类文件格式。
终端用户用于存储数据的格式变更可能会阻碍他们在后续版本中访问这些数据,因此保持兼容性非常重要。这些格式的示例包括har、war、SequenceFileFormat等。
用户级别的文件格式应被视为公开且稳定。用户级别的文件格式变更应在主要版本间保持向前兼容,且必须在同一主要版本内保持向前兼容。开发者社区应优先考虑创建新的衍生文件格式,而非对现有文件格式进行不兼容的修改。此类新文件格式必须作为可选功能创建,即用户应能继续使用现有兼容格式,直至他们明确选择使用新文件格式为止。
Hadoop内部数据也可能存储在文件或其他数据存储中。更改这些数据存储的模式可能导致不兼容问题。
MapReduce使用类似I-File的格式来存储MapReduce特定的数据。
所有MapReduce内部文件格式,例如I-File格式或作业历史服务器的jhist文件格式,应被视为Private和Stable。
HDFS以私有文件格式持久化存储元数据(镜像和编辑日志)。对该格式或元数据的不兼容更改会阻止后续版本读取较旧的元数据。不兼容的更改必须包含升级现有元数据的流程。
根据变更的不兼容程度,可能会出现以下潜在情况:
HDFS数据节点将数据存储在私有目录结构中。对目录结构的不兼容更改可能会阻止旧版本访问存储的数据。不兼容的更改必须包含一个流程,通过该流程可以升级现有数据目录。
HDFS元数据格式应被视为私有且演进中。不兼容的变更必须包含一个升级现有元数据的流程。升级流程允许需要多次升级操作。该流程必须支持将集群元数据回滚到旧版本及其旧磁盘格式。回滚操作必须恢复原始数据,但不要求恢复更新后的数据。任何对格式的不兼容变更都必须导致模式的主版本号递增。
数据节点目录格式应被视为私有且可演进。不兼容的变更必须包含一个升级现有数据目录的流程。该升级流程应允许需要多次升级操作。升级流程必须支持将数据目录回滚到旧版布局。
过去S3Guard元数据存储用于在DynamoDB表中存储元数据,因此必须维护兼容性策略。现在S3Guard已被移除,不再需要这些表。
配置为使用非“null”存储的S3A元数据存储的应用程序将失败。
YARN资源管理器将集群状态信息存储在外部状态存储中,用于故障转移和恢复。如果状态存储数据使用的模式不保持兼容,资源管理器将无法恢复其状态并启动失败。状态存储数据模式包含一个指示兼容性的版本号。
YARN资源管理器状态存储数据模式应被视为私有且演进中。对模式进行的任何不兼容更改必须导致模式的主版本号递增。对模式进行的任何兼容更改必须导致模式的次版本号递增。
YARN节点管理器将节点状态信息存储在外部状态存储中,以便在恢复时使用。如果状态存储数据使用的模式不保持兼容性,节点管理器将无法恢复其状态并启动失败。状态存储数据模式包含一个指示兼容性的版本号。
YARN节点管理器的状态存储数据模式应被视为私有且演进中。对该模式的任何不兼容变更必须导致模式的主版本号递增。对该模式的任何兼容变更必须导致模式的次版本号递增。
YARN资源管理器联邦服务将有关联邦集群、运行中的应用程序和路由策略的信息存储在外部状态存储中,用于复制和恢复。如果状态存储数据使用的模式不保持兼容性,联邦服务将无法初始化。状态存储数据模式包含一个指示兼容性的版本号。
YARN联邦服务的状态存储数据模式应被视为私有且演进中。对该模式进行的任何不兼容变更必须导致模式主版本号递增。对该模式进行的任何兼容变更必须导致次版本号递增。
Hadoop命令行程序既可以通过系统shell直接使用,也可以通过shell脚本调用。这些CLI既包含面向用户的命令(如hdfs命令或yarn命令),也包含面向管理员的命令(如用于启动和停止守护进程的脚本)。更改命令路径、删除或重命名命令行选项、参数顺序、命令返回码及输出内容都会破坏兼容性并对用户造成负面影响。
除非明确标注为实验性且可能变更,否则所有Hadoop CLI路径、用法及输出均应视为公开且稳定。
请注意,CLI输出应与Hadoop CLI生成的日志输出区分开来。后者应遵循日志输出策略。另外,对于CLI输出,所有变更都应视为不兼容变更。
Web界面,尤其是网页的内容和布局,其变更可能会干扰通过屏幕抓取获取网页信息的尝试。然而,Hadoop Web界面页面并非设计用于被爬取,例如用于自动化目的。用户应使用REST API以编程方式访问集群信息。
用户依赖Hadoop集群在不同版本间保持行为一致。导致集群出现意外不同行为的变更会引发用户困扰并延长采用周期。在假设集群配置文件保持不变的前提下,不应添加任何会改变现有集群行为的新配置。对于任何新定义的设置,都应谨慎确保新设置不会改变现有集群的行为。
对现有功能的更改不得在同一小版本内的维护版本之间改变默认行为或现有配置设置的含义,无论这些更改是源自系统或逻辑的变化,还是内部或外部默认配置值的调整。
对现有功能的更改在同一主版本的小版本之间不应改变默认行为或现有配置设置的含义,尽管某些更改(如修复正确性或安全问题)可能需要不兼容的行为变更。在可能的情况下,此类行为变更默认应处于关闭状态。
用户使用Hadoop定义的属性来配置并向Hadoop提供提示,同时使用自定义属性向作业传递信息。建议用户避免使用与Hadoop定义属性命名空间冲突的自定义配置属性名称,并应避免使用Hadoop使用的任何前缀,例如hadoop、io、ipc、fs、net、file、ftp、kfs、ha、file、dfs、mapred、mapreduce和yarn。
除了属性文件外,Hadoop还使用其他配置文件来设置系统行为,例如公平调度器配置文件或资源配置文件。
Hadoop定义的属性(名称和含义)应被视为公开且稳定。Hadoop定义的属性所隐含的单位不得更改,即使是跨主要版本。Hadoop定义属性的默认值应被视为公开且演进中。
不受上述关于Hadoop定义属性规则约束的Hadoop配置文件应被视为公开且稳定。不兼容更改的定义取决于特定配置文件的格式,但一般规则是:兼容性更改应确保在更改前有效的配置文件在更改后仍然有效。
Hadoop守护进程和命令行界面生成的日志输出由一组配置文件控制。这些文件决定了Hadoop各组件输出的最低日志级别,以及这些消息的存储位置和方式。
源代码、构建产物(源码和测试)、用户日志、配置文件、输出内容以及作业历史记录都存储在本地文件系统或HDFS的磁盘上。更改这些用户可访问文件的目录结构可能会破坏兼容性,即使通过符号链接保留了原始路径(例如当路径被配置为不跟踪符号链接的servlet访问时)。
源代码和构建产物的布局应被视为私有且不稳定。在主要版本内,开发者社区应保持整体目录结构,但可能会在无预警的情况下添加、移动或删除个别文件。
Hadoop提供了多个客户端构件,供应用程序与系统交互使用。这些构件通常对公共库有自身的依赖关系。当这些依赖项暴露给终端用户应用程序或下游消费者时(即未经过shaded处理),对这些依赖项的更改可能会造成破坏性影响。强烈建议开发者通过使用shading等技术手段,避免向客户端暴露依赖关系。
关于依赖关系,添加依赖项是一项不兼容的变更,而移除依赖项则是一项兼容的变更。
一些基于Hadoop构建的用户应用程序可能会将所有Hadoop JAR文件(包括Hadoop的库依赖项)添加到应用程序的类路径中。添加新的依赖项或更新现有依赖项的版本可能会干扰应用程序类路径中的依赖项,从而影响其正常运行。因此不建议用户采用这种做法。
Hadoop客户端构件暴露的依赖项集合应被视为Public和Stable。任何未暴露给客户端的依赖项(无论是被遮蔽还是仅存在于非客户端构件中)应被视为Private和Unstable
用户和相关项目经常使用Hadoop导出的环境变量(例如HADOOP_CONF_DIR)。因此,删除或重命名环境变量可能会影响最终用户应用程序。
Hadoop所使用的环境变量以及通过YARN SHALL向应用程序公开的环境变量应被视为Public和Evolving。开发社区应尽量将变更限制在主要版本中。
Hadoop使用Maven进行项目管理。对生成工件内容的更改可能会影响现有的用户应用程序。
Hadoop测试构件的内容应被视为私有且不稳定。测试构件包括从测试源代码生成的所有JAR文件,以及文件名中包含"tests"的所有JAR文件。
Hadoop客户端构件应被视为公共和稳定。客户端构件包括以下内容:
为了跟上硬件、操作系统、JVM和其他软件的最新进展,新的Hadoop版本可能包含需要比之前Hadoop版本更新的硬件、操作系统版本或JVM版本的特性。对于特定环境,升级Hadoop可能需要升级其他依赖的软件组件。
以下是与该主题相关的一些JIRA和页面: