cover_image

中通hadoop去CDH的实践之路

QSteven 科技中通
2022年11月08日 10:27

图片

 一、背景

01
快递业务介绍


中通快递创建于2002年5月8日,是一家以快递为核心业务,集跨境、快运、商业、云仓、航空、冷链、金融、智能、兔喜社区生活服务、中快数字营销等生态版块于一体的综合物流服务企业。2021年,中通快递全年业务量达到223亿件,同比增长31.1%。全网服务网点30,400+个,转运中心99个,直接网络合作伙伴5700+个,自有干线运输车辆10,900辆(其中超9000辆为高运力甩挂车),干线运输线路约3700条,网络通达99%以上的区县,乡镇覆盖率超过93%。科技中通大数据中心支撑了公司的业务,现在有了两个IDC,Hadoop集群规模达到了上千台,存储达到了18PB+,线上日活任务数2w+,目前,仍处在快速增长期。

如下图展示了一个快递的生命周期,五个字概括就是收发到派签。首先,客户通过线上或线下的方式和快递员取得联系,填写寄件人等信息,将快递A交给快递员。快递A经过称重、打单、扫描、包装等步骤,由快递员送往发件网点,此过程称为揽收。然后,发件网点的快递员将快递A进行建包、装包、装车,由发件网点发出,发往首转运中心。快递A经首转运中心被运输到末转运中心。快递A到达末转运中心后,快递员根据三段码的解析将快递A递交到收件网点,收件网点对快递A进行拆包和分拣,此过程包括发件和到件。快递A被分拣完,由快递员进行派件,最终快递A被送达到收件客户手里,收件客户完成签收。在快递A整个生命周期内,每个业务流程都会产生大量的数据,我们利用这些数据,可以追踪快递A的轨迹,分析快递A的运送时效,分析快递A的退改签等业务。当然,做上述事情的前提是,我们需要一个稳定的、计算高效的、海量存储的基础大数据平台。

图片
02
 大数据平台介绍


中通大数据平台整个体系如下图所示,整个大数据平台基于Hadoop生态系统建立起来的。总共分为四层,最下面一层是数据源层,该层负责抽取Web日志、系统日志、埋点、业务数据等,这些数据是原始的数据,是整个快递生命周期内产生的各种各样的数据。在数据源之上就是存储层,该层负责存储各式各样的快递数据,有HBase、Alluxio、Hudi、Kudu等存储组件。在存储层之上为计算层,该层提供对快递数据的计算和处理能力,计算组件有离线和实时之分,离线计算包括Hive、Sqoop、SparkSql等,OLAP在线计算包括Presto和ClickHouse,实时计算包括Flink和SparkStreaming。最上层是服务层,该层主要是提供数据服务能力的,主要包括调度系统、元数据系统、任务分析系统、机器学习系统等。整个大数据平台各层相互支持,最终实现了中通的数字化平台,提供一个支持业务和赋能业务的能力。

图片
03
 背景介绍


在整个中通大数据平台中,最核心的是Hadoop基础平台,因为所有的快递数据都是保存在其中,因此,Hadoop的稳定和高效是最核心的。

目前中通Hadoop的使用的CDH社区版,版本为2.6.0-cdh5.12.1,主要存在以下几个问题。

1)在成本方面,cdh开始收费。从2021年1月底,所有的Cloudera都需要付费订阅,才能正常使用,并且收费昂贵,后续的维护和扩展功能都需要付费。如果一个节点按照1万美元收费标准 ,公司有1000多台机器,去CDH能为公司节省1000多万美元的成本,这是非常符合公司一直秉持的降本增效的宗旨。

2)在yarn调度性能方面,cdh版本的yarn调度性能比较低。在每天的凌晨0点到5点之间,是ETL作业的高峰期,这个时间段,作业数量达到了一天的高峰,随着ETL数量增多,yarn的资源调度器效率变低,正常情况下,yarn资源调度器效率是在10毫秒内能够分配一个Container,在业务高峰期,yarn资源调度器效率最快能达到1秒甚至2秒分配一个Container,最终导致的一个结果就是关键的ETL作业大面积出现延迟,影响到了业务部门白天的正常使用。这是业务无法接受的。

3)在namenode rpc性能方面,cdh版本的namenode rpc会发生阻塞。这是由于cdh版本的namenode的block的管理使用的红黑树的数据结构,该结构对于查询表现出良好的性能,但是如果对于大规模的删除blcok操作,比如删除一个大的目录,该红黑树会花很长时间去做重平衡,这会使得namenode阻塞住,无法提供服务,最坏的情况能达到2到3分钟,这种影响随时都会出现,严重影响了业务的使用。

综上来看,去CDH是对于公司来说是很有必要的一项工作。我们调研了同行和业界大厂使用hadoop的情况,从调研的资料来看,大厂都是使用apache hadoop,升级也是基于apache hadoop版本分支进行的,我们为了响应公司降本增效的宗旨,去CDH,转而升级到apache hadoop 2.7.5版本。针对apache hadoop 2.7.5版本,我们做了相关的压测,压测结果表明,yarn调度性能能够控制10毫秒以内。namenode rpc在大规模删除时,不会出现阻塞的现象,这是因为2.7.5在block的管理采用的是链表数据结构,链表的删除性能是很优的。

为了升级到apache hadoop 2.7.5,我们经历了如下挑战:

1)版本跨度大,从cdh 2.6 到 apache 2.7,原因是cdh基于apache2.6开发和合并很多的特性,apache 2.7版本没有这些新特性,需要投入更多的时间和精力测试和排除。

2)平台组件多,目前大数据平台,包括调度系统、元数据、机器学习、查询平台等系统,都依赖于Hadoop, 需要投入更多的精力、人力、时间测试兼容性。

3)客户端多,MapReduce、hive、hbase、alluxio、spark、flink 等作业都是运行在hadoop上,对这些组件都需要进行兼容性测试。

4)作业问题,sqoop、datax、mapreduce、hive、flink、spark等作业运行在不同版本的hadoop时,兼容性问题,classpath和包依赖问题。

总之,2021年我们去除了cloudera manager的依赖,自主研发了一套监控和运维hadoop的程序。2022年,经过不懈的努力,我们完成了apache hadoop 2.7.5的升级。

04
 升级目标


  • hdfs升级的目标

1)升级采用滚动升级,不影响业务的正常运行。

2)有完备的降级方案,当业务出现异常时,支持滚动降级。

3)保证HDFS升级后能够兼容其他组件,不影响其他组件的正常服务。

4)保证数据的安全,无丢失。

  • yarn升级的目标

1)对业务完全透明:升级不影响用户现有任务,不影响用户提交新任务。

2)兼容所有计算框架:升级保证现有计算框架都能准确执行。

3)支持滚动升级/降级:升级有问题,相关服务可以从apache 2.7.5降级到cdh 2.6版本。

05
升级计划


为了顺利地从cdh 5.12.1-2.6.0升级到apache hadoop 2.7.5,我们制定了详细的升级计划,主要分为8个部分:

1)升级方案调研

在该阶段主要是调研业界各大公司对于hadoop的升级方案,吸取其优秀的经验,对于我们制定hadoop升级方案和计划起到一定的指导意义。调研最后我们选择apache hadoop 2.7.5整个版本。

2)基础组件编译

hadoop版本确立后,我们需要对alluxio、fink、hbase、hive、spark、hudi、presto等基础组件进行编译,以确定这些组件能够使用新版本的hadoop进行编译,如果出现编译问题,尽快解决掉。后续这些组件都会基于该版本进行重新发布。

3)hadoop压力测试

由于是升级hadoop,需要对apache hadoop 2.7.5版本的hdfs和yarn相关组件进行性能测试,验证该版本的关键组件的性能是否满足我们的需求,主要包括namenode的性能测试和yarn调度性能测试。

4)定制代码合并

该阶段主要是将我们基于cdh 5.12.1-2.6.0 hadoop定制开发的feture和bug修复,合并到apache hadoop 2.7.5版本。

5)hadoop升级方案制定

该阶段分别针对hdfs升级和yarn升级,进行升级方案的制定和验证,对于升级过程中出现的各种问题进行解决。还包括升级源码的阅读和各种异常异常情况下升级的演练。

6)hadoop升级测试

该阶段需要从各个系统角度对hadoop升级过程进行演练,如调度平台、查询平台、机器学习、实时计算等,包括hdfs客户端、yarn客户端、mr客户端等兼容性测试,升级过程中各个组件中间状态的测试。当然,这个测试的过程不是直接在线上环境进行,而是完全搭建一套模拟的升级环境,集群的规模比较小,26台机器的环境。6台搭建实时hadoop集群,6台搭建hbase集群,8台搭建离线hadoop集群,6台搭建presto和alluxio集群,每种数据平台系统都是重新搭建的,如调度平台、查询平台、机器学习等。对于模拟环境的数据,都是从线上取一小部分数据进行测试使用。

7)hadoop升级实施

由于我们hadoop集群分为三种类型,hbase集群、实时hadoop集群、离线hadoop集群,每套集群都有环境的差异性,因此,需要针对每套集群分别制定升级方案。并且升级的顺序遵循从风险低到风险高进行,即先升级hbase集群,其次实时hadoop集群,最后离线hadoop集群。因为离线hadoop集群的节点几百台机器,并且业务依赖的多,风险高,环境复杂,所以,先从风险低的hbase集群进行升级,遇到问题可以迅速回退降级,修复问题。

8)hadoop升级复盘

在hadoop过程中,我们遇到了各种各样的问题,问题解决后,都会以wiki形式存档,升级的一些经验,都是以wiki沉淀下来,在整个升级过程中,不断进行小复盘,以此提高认知和经验。最后,整个升级完成后做最终复盘。

二、升级过程

01
 升级方案


hadoop升级的方式有两种,Express和Rolling,Express就是全面停机升级;Rolling是滚动升级,升级期间服务不停止,用户无感知。当然是滚动升级方案最好了,因为离线集群用户非常之多,影响面非常之大。我们采用的是Rolling升级。对于Hadoop的升级,我们采用HDFS和Yarn分开升级的方式,先升级Yarn,再升级HDFS,接下来分别详细地介绍Yarn和HDFS升级方案。



 yarn升级方案
图片

上图是yarn整体的架构图,从该图可以看出,yarn包括resourcemanager、nodemanager等组件,resourcemanager是主节点,nodemanager是从节点。yarn的升级步骤是:先升级resourcemanager,再升级nodemanager,nodemanager采用分批升级的方式,按照5%->25%->50%->75%->100%灰度策略进行升级。如果升级过程出现问题,无法快速解决,进行回滚降级,采用先回滚降级nodemanager,再回滚降级resourcemanager。但是,不可以同时出现cdh 2.6版本的resourcemanager和apache 2.7版本的nodemanager混合部署的情况。在升级yarn的过程中,我们遇到了各种各样的问题,接下来详细地介绍关键的几个问题。

1)apache 2.7.5 resourcemanager与cdh 2.6.0 nodemanager通信出现SASL EOF异常

如下图是apache 2.7.5 resourcemanager的异常堆栈:

图片

该异常发生在apache 2.7.5 resourcemanager为主节点与cdh 2.6.0 nodemanager混合部署的情形,我们提交了一个MR作业,但是作业无法运行,查看相关日志发现报了上图的异常。通过定位相关源码,分析出产生该异常的原因是apache 2.7.5 resourcemanager发送rpc到cdh 2.6.0 nodemanager请求启动container,在建立请求链路时,需要进行sasl认证,cdh 2.6.0 nodemanager反序列化apache 2.7.5 resourcemanager发来的信息时出现错误,造成sasl无法验证通过。针对cdh 2.6.0 nodemanager无法反序列化apache 2.7.5 resourcemanager的发来的信息,经过进一步分析得出,apache 2.7.5 resourcemanager序列化方式是protobuf, 而cdh 2.6.0 nodemanager的反序列化方式为java流,序列化和反序列化方式的不同造成sasl认证失败。

解决方案:

改造cdh 2.6.0 nodemanager,升级为protobuf序列化方式,此种改造较多, 风险较大。

改造apache 2.7.5 resourcemanager,将protobuf序列化方式为java流,改动小,风险低。

故采用第二种,相关的patch有YARN-668,YARN-2615,YARN-2743。

2)container token认证失效异常

如下图是cdh 2.6.0 nodemanager的异常堆栈:

图片

该异常发生在apache 2.7.5 resourcemanager为主节点与cdh 2.6.0 nodemanager混合部署的情形,我们提交了一个MR作业,但是作业执行失败,查看相关日志发现报了上图的异常。通过定位相关源码,分析出产生该异常的原因是apache 2.7.5  resourcemanager发送rpc到cdh 2.6.0 nodemanager请求启动container,  nodemanager需要进行container token验证。但是apache 2.7.5 reosucemanager在序列化ContainerTokenIdentifier时,多序列化一个字段logAggregationContext,而cdh 2.6.0 nodemanager反序列化时,没有反序列该字段,然后加密ContainerTokenIdentifier字节流进行token验证时,因为缺少logAggregationContext字段,使得apache 2.7.5 reosucemanager加密token与cdh 2.6.0 nodemanager加密token得到的字符串不一致,导致container token验证无法通过,最终导致任务失败。

解决方案:

改造apache 2.7.5 reosucemanager,将ContainerTokenIdentifier关于logAggregationContext该字段序列化和反序列化去除,但是存在未知风险,后续yarn升级完成,还需要再次添加该字段停机维护,不可取。

改造cdh 2.6.0 resourcemanager和nodemanager,在ContainerTokenIdentifier在序列化和反序列化增加logAggregationContext字段,但是需要停机重新维护,不可取。                   

改造cdh 2.6.0  nodemanager,将nodemanager关于ContainerTokenIdentifier验证逻辑去除,可以滚动维护nodemanager, 可取。

故采用方案

3)apache 2.7.5 nodemanager无法解析cdh 2.6.0 nodemanager保存的作业

如下图是apache 2.7.5  nodemanager的异常堆栈:

图片

该异常发生在cdh 2.6.0 nodemanager升级为apache 2.7.5 nodemanager的情形,apache 2.7.5 nodemanager对于cdh 2.6.0 nodemanager保存的正在运行的MR作业无法恢复运行,造成apache 2.7.5 nodemanager启动失败,查看相关日志发现报了上图的异常。通过定位相关源码,分析出产生该异常的原因是:cdh 2.6.0 nodemanager将作业持久化到本地level db中,持久化ContainerTokenIdentifier时,缺少序列化logAggregationContext字段。然后将nodemanger升级到apache 2.7.5 nodemanager时,进行作业恢复,将ContainerTokenIdentifier反序列化时,由于序列化信息中没有logAggregationContext字段,反序列化出错,造成apache 2.7.5 nodemanager无法启动。

解决方案:

改造apache 2.7.5 nodemanager,将ContainerTokenIdentifier关于logAggregationContext该字段序列化和反序列化去除,但是存在未知风险,后续升级完成,再次添加该字段需要停机维护,不可取。

改造cdh 2.6.0 resourcemanager和nodemanager,在ContainerTokenIdentifier在序列化和反序列化增加logAggregationContext字段,但是需要停机重新维护,不可取。

改造apche 2.7.5 nodemanager ,将ContainerTokenIdentifier关于logAggregationContext该字段反序列化的逻辑加入try catch,捕获异常不处理,使得其余字段正常反序列化,兼容cdh 2.6.0 nodemanager持久化的作业,可取。

故采用方案

4)spark streaming作业由于黑名单机制退出的问题

该类问题发生在apache 2.7.5 resourcemanager和cdh 2.6.0 nodemanager混合部署,两个apache 2.7.5 resourcemanager进行ha切换的情形下,spark streaming作业发生退出。从退出的spark streaming作业异常诊断得到的异常信息:attempt recovered after RM restart Due to executor failures all available nodes are blacklisted。通过定位源码分析得出,spark 3.0的黑名单判断逻辑存在bug,使得spark streaming作业的am退出,导致spark streaming作业退出,造成实时作业失败。

针对该bug本身,黑名单判断逻辑如下代码:

图片

其中,numClusterNodes表示apache 2.7.5 resourcemanager响应am的当前hadoop集群可用的nodemanager数量, currentBlacklistedYarnNodes表示当前作业失败汇集的nodemanager集合。

当resourcemanager ha发生切换的瞬间,hadoop集群还没有获取到任何nodemanager心跳,此时resourcemanager响应给am的nodemanager数量为0, 而currentBlacklistedYarnNodes也恰好为0,currentBlacklistedYarnNodes.size >= numClusterNodes条件成立,isAllNodeBlacklisted为true,导致am抛出异常,实时作业退出。

解决方案:

针对黑名单判断逻辑存在的bug,从apache spark官网找到相关的patch SPARK-29683。然后使用该patch修复spark,但是需要重启上百个spark streaming实时作业,不可取。

改造apache 2.7.5 resourcemanager,当am向apache 2.7.5 resourcemanager请求资源时,如果resourcemanager还没有收到任务nodemanager请求时,此时模拟响应am当前hadoop集群可用的nodemanager数量为1,从而规避掉黑名单的判断机制,可取。

故采用方案





hdfs升级方案
图片

上图是hdfs整体的架构图,从该图可以看出,hdfs包括namenode、zkfc、journalnode、datanode等组件,namenode是主节点,datanode是从节点,journalnode是为了保证两个namenode数据同步的,zkfc是为了保证namenode的failover。hdfs的升级步骤:先升级namenode,其次升级journalnode,然后,分批滚动升级datanode,按照5%->25%->50%->75%->100%灰度策略进行升级。如果升级过程出现问题,无法快速解决,进行回滚降级,采用先回滚降级datanode,再回滚降级journalnode和namenode。不可以出现cdh 2.6.0 namenode和apache 2.7.5 datanode混合部署的情况。对于hdfs的回滚, 有两种回退方式:Rollback 和 RollingDowngrade,Rollback 会把软件版本连同数据状态回退到升级前的那一刻 ,会造成数据丢失;RollingDowngrade 只回退软件版本,数据不受影响。我们回退降级的宗旨不允许数据丢失,因此,我们选择 RollingDowngrade 回退方案。在hdfs升级过程中,我们遇到了各种各样的问题,接下来详细地介绍关键的几个问题。

1)DatanodeProtocol.proto通信协议不兼容的问题

namenode从cdh 2.6.0升级到apache 2.7.5,由于DatanodeProtocol.proto通信协议不兼容,导致Datanode report无法进行。如下代码比较:

图片

可以看到apache 2.7.5版本没有 fullBlockReportLeaseId和rollingUpgradeStatusV2这两个字段。产生这个问题原因在于cdh 2.6.0合并了HDFS-7923和HDFS-9426,而apache 2.7.5没有这些commit。

解决方案:

改造apache 2.7.5的DatanodeProtocol.proto,加入fullBlockReportLeaseId和rollingUpgradeStatusV2这两个字段,为了兼容cdh 2.6.0的datanode的block上报。然后,DatanodeProtocolServerSideTranslatorPB.java需要对fullBlockReportLeaseId设置一个大于0的值,因为cdh 2.6.0的datanode会根据该字段值判断是否进行block汇报。如下图是对DatanodeProtocolServerSideTranslatorPB.java改造点。

图片

cdh 2.6.0的datanode根据namenode返回字段fullBlockReportLeaseId的值决定是否向namenode进行block汇报,具体block汇报的逻辑在类BPServiceActor.java中,如下图给出了具体的判断逻辑代码。

图片

2)升级到2.7.5 namenode响应慢

出现此类问题是在升级实时hadoop,namenode从cdh 2.6.0升级到apache 2.7.5,且成为主节点时,此时2.7的nn的RpcQueueTimeAvgTime(rpc平均排队时间)指标延迟高,如下图,持续20分钟都是大于我们设定的阈值200ms, 正常情况下在200ms以内,此指标表明,nn的处理速度慢,响应的时间也就变长了。

图片

排查namenode相关日志和查看apache 2.7.5 hadoop的block全量汇报这块代码分析得到,2.7.5 namenode 和 2.6.0 datanode混合部署时,会使得2.6.0 datanode的每次心跳都在全量汇报给2.7.5 namenode,使得namenode的压力过大,处理速度慢,响应时间变长。

解决方案:改动cdh 2.6.0 hadoop代码增加判断,使得cdh 2.6 datanode第一次启动时只一次block全量汇报,后续的block全量汇报通过定时程序触发。

在BPServiceActor.java中进行改造,改造点如下图所示,使其能够按照固定频率进行全量的block汇报。

图片

3)namenode无法从apache 2.7.5降级到cdh 2.6.0

出现这类问题主要是由于namenode升级后,namenode layoutVersion发生了变化,如果从apache 2.7.5 namenode降级到cdh 2.6.0后,导致fsimage和editlog数据不兼容。如下图堆栈异常:

图片

namenode的layoutVersion从-60变为-63,这是由于HDFS增加了新特性,layoutVersion就会发生变化。查看apache  2.7.5 hadoop的NameNodeLayoutVersion代码如下:

图片

apache 2.7.5相比于cdh 2.6.0新增了TRUNCATE,APPEND_NEW_BLOCK,QUOTA_BY_STORAGE_TYPE三个特性,我们对新增的三个新特性进行评估,结合业务场景分析,公司内部暂时没有使用TRUNCATE和QUOTA_BY_STORAGE_TYPE功能。对于APPEND_NEW_BLOCK,经过我们验证,hudi运行在apache 2.7.5 hadoop环境下使用到了该特性,由于hudi业务还处在实验探索阶段,和业务沟通,在离线hdfs升级的时候,可以停掉,hdfs升级完毕后,再开启hudi相关的业务。从上面分析来看,可以理解为apache 2.7.5相比于cdh 2.6.0新增的三个特性,我们公司的业务都没有使用到,因此,fsimage和editlog的数据格式的不同点就是多了一个layoutVersion等于-63的标签,数据内容是完全一致的。基于这个结论,我们为了支持namenode从apache 2.7.5降级到cdh 2.6.0,我们针对cdh 2.6.0 hadoop进行了改造,去除了cdh 2.6.0 hadoop对于layoutVersion的所有校验。具体涉及到了类有StorageInfo,EditLogFileInputStream,FSImageUtil,NameNodeLayoutVersion,FSImage。
02
 升级测试


为了保证hadoop升级顺利地进行,我们需要对升级每个过程,进行充分的测试和故障演练,一旦出现故障,要有相应的预案,对于无法快速解决的问题,进行快速回滚降级。如果回滚降级失败,采取最极端的方式,就是所有的hadoop服务组件全面停止,然后启动老版本的服务。

针对yarn升级的过程,存在以下三种情况中间状态:

1)2.6版本resourcemanager和2.7版本resourcemanager共存的情况。

2)2.7版本resourcemanager和2.6版本nodemanager共存的情况

3)2.7版本resourcemanager和2.7版本nodemanager共存的情况

对于上述三种情况,我们设计了yarn升级过程的测试案例。

针对hdfs升级过程,存在以下四种情况中间状态:

1)2.6版本namenode和2.7版本namenode共存的情况。

2)2.7版本namenode和2.6版本journalnode共存的情况。

3)2.7版本namenode和2.6版本datanode共存的情况。

4)2.7版本namnode和2.7版本datanode共存的情况。

对于上述四种情况,我们设计hdfs升级过程的测试案例。

如下图所示,我们给出了hadoop升级过程的总体测试案例。图中JN为journalnode简写,NN为namenode简写,DN为datanode简写,RM为resourcemanager简写,NM为nodemanager简写。

图片

三、 展望

2022年我们完成了公司8套hadoop集群的升级,Hadoop升级过程漫长,但是收获颇多。目前公司的最大离线hadoop集群1000多台机器,yarn的调度性能还需要持续优化。同时,我们还需要在保证hadoop稳定性、安全性、性能、成本等方面进行持续发力,探索调优,为公司各个业务部门提供更加高效的存储和调度性能,达到公司提倡的降本增效的目的。

图片

RECOMMEND

往期干货
中通科技代码覆盖率应用实践(三)

•中通IM测试实践

浅谈zto大数据计算与业务系统的融合

•中通数据架构治理

欢迎各位技术大佬向本公众号积极投稿,提升经验分享、信息互通的技术交流氛围,共同解决技术难题、共同进步!(投稿咨询请联系科技与信息中心品牌管理部 徐蕊)

图片

继续滑动看下一个
科技中通
向上滑动看下一个