导读
“平台迁移那些事”是 eBay CCOE EEE (Engineering Ecosystem and Experience) 团队最新推出的系列文章,本文为总起篇。从 V3 平台的陈旧应用无缝转移到 eBay 最新的 Raptor.io 平台,该项目涉及 eBay 百亿级流量的迁转,并要求在整个迁移过程中不影响任何实时服务,对 eBay 用户保持透明。
01 缘起
身处互联网时代,我们每天都面临着技术的升级换代,以及全新技术的不断涌现。相应地,eBay 内部的开发平台也在不断演化。目前, eBay 就有应用分别存在于三代 Java 开发平台上,平台名字分别为 V3、Raptor、Raptor.io。
首先我们简单介绍下这三代的 Java 开发平台。
V3 Platform - eBay 较老的开发平台,最早开发于 20 年前,当时的操作系统还是 Windows2008(Batch Jobs 跑在 Solaris 机器上),运行着 IBM JDK 1.6,使用 IBM Geronimo Web 服务器。所有代码的开发、打包、编译都是 eBay 自主定义的规范。
Raptor/Raptor.io - Raptor/Raptor.io 是 V3 的下一代平台,操作系统基于 Linux,使用开源的 OpenJDK 和 Tomcat Web 服务器。代码的开发,打包、编译分别基于 Spring/Spring boot、Maven、Git 等开源工具。Raptor.io 相较于 Raptor 更为轻量化,模块化且更好地支持云原生环境。
时至今日,大部分基于 V3 平台的应用都已经被业务团队升级到了 Raptor/Raptor.io 平台。但是也有部分 V3 应用因为年代久远、功能复杂,迟迟不能被顺利迁移到新平台。
“平台迁移那些事”系列文章,将重点分享如何抽丝剥茧,将基于 V3 平台的陈旧应用无缝转移到 eBay 最新的 Raptor.io 平台。项目本身涉及 eBay 百亿级流量的迁转,并要求在整个迁移过程中不影响任何实时服务,对 eBay 用户保持透明。
02 V3 的世界
V3 的存在已经将近 20 年了。在这 20 年中,V3 已经发展到代码近八千万行,每天的流量达到百亿甚至千亿规模。时光流逝,随着新技术和新架构的不断涌现,V3 在开发、编译、打包、部署和容器化等等方面都显得力不从心, 慢慢地成为 eBay 的技术负债。要想平滑地将 V3 平台上的应用迁移到新平台上,就必须先充分了解 V3 的平台组成,所谓知其来路,才能明其去向。
下图非常清晰地描述了 V3 平台的具体框架结构和组成。完整的 V3 环境包括核心类库,业务类库, 五种类型的应用类型,以及相关的开发支持工具。
图 1
显而易见,淘汰V3环境已经成为eBay的当务之急。原因在于,很多老爷车现在即使eBay愿意支付服务费,但开发厂商也已经不再维护,譬如IBM JDK。一旦无法升级,所产生的安全隐患将是eBay这样的大公司绝对不能忽视的。因此需要将IBM JDK 变成 Open JDK,Web服务器由Geronimo变成Tomcat,操作系统由Windows 变成 Ubuntu。基础运行环境的消失,意味着V3应用也失去了生存的土壤,它们必须被迁移到新一代的平台。
03 挑战荆棘之路——从V3到Raptor.io
从V3平台到Raptor/Raptor.io的迁移就像要把一个苹果变成一个梨,都是水果,但是滋味完全不同。这当中有许多的挑战。eBay 数次尝试让业务部门自己把V3的代码重写来消除技术负债。但是收效甚微。因为对于业务部门来说,平台迁移意味着天翻地覆的变化,更因为随着部门成员的更迭,某些V3应用的领域知识早已消失殆尽,迁移应用似乎成为了一项“不可能完成的任务”。下面我们具体罗列6项平台升级中的主要挑战。
3.1 平台核心类库冲突
首当其冲的挑战就是平台核心类库的变化。即使是同样的功能,由于平台不同,实现的方式也不同。这些核心类库在V3 平台是eBay 自己实现的,而Raptor 平台是基于Spring,Raptor.io 平台则是基于Spring Boot。平台变化后,要能保证新的核心类库和V3现有的业务类库能够正常工作。无论是启动顺序,还是核心功能,抑或是接口都需要兼容。不仅是应用需要调整,新平台的核心类库也需要进行代码调整以应对冲突。这就需要拆迁团队和平台团队合作,把核心类库的修改应用到新的平台版本中去。同时拆迁队也要保证迁移的应用V3的核心类库从传递依赖中剥离干净,防止冲突。
3.2 新旧框架适配
下表是不同类型的应用在不同平台下,核心框架的变化。
从上表可以看出,应用的迁移不仅涉及到平台的迁移,也涉及到每种应用类型框架的迁移。拆迁团队不仅要能够处理V3 和Raptor/Raptor.io平台之间的差异,还要能够处理不同代的应用类型框架之间的差异。
3.3 应用功能无人描述
由于这些应用大多产生于10多年前,人员的流动导致这些应用做需要实现的功能已经没有团队成员能够完整描述。
而最大的问题是,代码迁移后如何进行测试,它有哪些测试用例,又有多少种输入组合,这些,均无人知晓。在缺少测试用例、缺少领域知识、系统输入组合不定的情况下,如何保证迁移的质量?更何况在迁移之后,不仅要保证功能正确,还要确保系统稳定、所有的运行指标正常。
3.4 应用特殊配置难以发现
由于多年间归属团队的更替,某个应用有没有特殊配置,有哪些特殊的配置?如果要复制这些配置需要什么团队的合作?这一连串的问题,我们不知道、用户也不知道。如果这些设置会导致系统运行直接失败,那么也比较容易发现。但是有些配置只是影响灾备或者致使性能缓慢降低,这些就很难被发现了。这在后文成功案例的章节中会有介绍。以系统响应变慢为例:
系统变慢(比如cache没有设置),不影响功能。看起来问题不大,但是它意味着吞吐量的下降,会导致雪崩效应或者链式反应。这是系统隐患,必须解决。我们不能放过任何一个可疑的指标变化,必须找出每一个方法变慢的原因。在毫秒级别的差距中找到疑点并确认。
3.5 网络层搬迁难以复制
要是一个应用能够正常工作,光靠代码迁移是不够的。这个应用要连接到上、下游的应用,只有和所有的上下游都能正常通讯,这个应用才能正常工作。我们需要逐个检查才能保证网络层搬迁成功。
应用网络层的搬迁常见检查有防火墙、白名单、证书、https/http支持、安全配置等。以防火墙为例,在eBay就有软件防火墙,硬件防火墙。在新的应用下,原来的硬件防火墙规则都需要迁移到软件防火墙。硬件防火墙的规则堆积了很多年,需要找出哪些是需要复制的,哪些是不需要复制的。即使找到了要复制的规则,也要考虑软件防火墙可以设置三个不同层级的防火墙规则。新的应用需要在哪一层复制原来的规则都是非常复杂的问题。这一部分好在有eBay Altus的依赖发现服务,帮助我们省去了大量的查找工作。在此需要强烈感谢基础架构团队给予我们的大力支持。
3.6 无间断应用导致风控难度高
eBay提供的是24*7无间断的服务。每个应用迁移都只能是实时在线的流量切换。在总流量达到几百亿的规模下,我们要保证线上服务不中断。在流量切换过程中尽早发现问题,在危急关头做出正确的评估,哪些问题可以选择快速修复,哪些问题只能采取立即回撤,这些问题时刻考验着拆迁团队的临场指挥能力,必须依靠平日积累的现场作战经验。
04 策略分析及解决方案——整屋拆迁
所谓兵来将挡,水来土掩。针对以上的各种挑战,V3拆迁团队需要逐个击破,并制定全方位的解决方案。经过缜密的研究,一种称之为”整屋拆迁”(Forklift)的方案浮出水面。
理想情况下,在新的平台上重写一套新的应用是最好的选择。重写不仅满足了新平台的需求,而且对应用团队完全掌握代码的功能、理解新平台的规范、优化以前的实现都有巨大的帮助。但是重写的代价非常昂贵。近八千万行代码的重构,在缺少测试用例的情况下,风险巨大。而且重写不仅意味着这个应用本身的改动,也意味着这个应用的上下游也可能受到影响,所以难度就成倍数增加了。更复杂一点的情况,如果一个调用链上都有应用重写,那么这个依赖链条上的优先级和进度更是难以保证。因此,全部重写对于eBay这样体量的网站来说,是很难实现的。
整屋拆迁的概念就好像是搬家,房子是新的,水电煤是新的。但是格局、房间里的家具,管道和插座都没有变化。 对应到应用迁移,就是不触碰用户的业务代码逻辑,专注于让用户的代码能够跑在新的平台上。这种方法通过分阶段、自动化的方式负责所有应用的迁移。从代码迁移开始,直到旧的环境全部回收,一条龙服务,全程负责。用户只需要负责必要的测试和校验。尤其对于V3 SOA, Trading, Shopping, BES这些后端服务,“整屋拆迁”最大限度地提高了成功率并降低了风险。
经过反复论证,V3拆迁团队即将开始整屋拆迁V3的应用。我们即将从理论探讨纵身一跃,进入真刀真枪的实干阶段。一些闻所未闻的深坑,也在静静地等待挑战者的到来。下一章节,我们将深入探讨迁移期间所遇到的困难和具体实施解决方案。
05 整屋拆迁(Forklift)——“痛并快乐着”
下面这张图说明了整屋拆迁的流程。它分为五个阶段,目标是尽量减少客户工作量, 同时保证安全可靠。
图2
5.1 代码迁移
代码迁移是第一步也是重中之重。工欲善其事,必先利其器。代码迁移工具主要目标是实现代码迁移自动化。工具必须具备的能力是把V3的应用源码自动变成Raptor/Raptor.io 的源码,同时能够让几千个不同类型的应用在核心平台类库、框架变化的情况下,业务代码逻辑不改变、用户不参与源码改动、无缝地进行代码迁移。
那么我们要考虑3个平台(V3/Raptor/Raptor.io),5种框架(SOA/Batch/BES/Trading/Shopping) 的适配,也就是前面提到的“核心类库冲突,不同框架适配”的挑战。这就需要对所有涉及到的知识都有深入的掌握,然后才能处理这些问题。比如V3Batch是eBay自己写的框架,Raptor Batch基于Spring Batch,两个核心框架接口完全不同,如何保证迁移的应用代码逻辑不改变还能正常工作?拆迁团队最终在工具层面解决了这些问题。我们会在本系列的后续文章中详细介绍。
在解决平台和框架挑战的同时,我们也要提高代码迁移效率。这个工具要能提高迁移团队的效率,用更少的人解决更多的问题。在以前的迁移历史中,每种应用都有一个自己的开发工具。这种方式其实在某种程度上造成了资源浪费。例如,当同一个问题发生在核心类库时,在不同类型的应用中错误的表现并不一样。每个工具都有自己的解决办法。这就带来了一些问题:这些知识点不能在多个团队中共享,不同团队的解决方案的质量也参差不齐,不仅浪费时间,关键是相同症结还会重复出现。
为解决这两个问题,代码迁移的工作不再是简单的单打独斗,而是用迁移平台的理念进行一站式迁移。
图3
从图3上看,我们把工具平台分为三层。
前两层是工具自动化处理部分。 底层有两个Platform converter,一个是Raptor 的converter,一个是Raptor.io的converter。这两个platform converter 能够处理平台级别的差异。第二层可以集中处理各种应用框架之间的差异。对于每一个框架差异,都有一个插件来处理。通过底部两层的逻辑处理,对一个应用运行命令后,拆迁平台就生成了初始迁移代码。
第三层是人工处理部分。 在自动产生的代码之上,拆迁队需要解决每个应用特有的问题。到了这个阶段,大部分问题在下面两层已经被解决了。拆迁队所面临的是不论哪种应用类型都存在的问题。对于那些常规重复的, 迁移团队很容易建立知识库。通过人工处理之后,就可以拿到可以运行、测试的代码了。
针对这样的分析,对于下面两层,由于需要对平台和框架有深入的了解,所以由我们的资深成员在工具层面进行开发来解决。对于顶部,面临的问题没有那么大挑战性,主要是由我们的外包同事来承担。这样的策略,充分发挥了每个人的能力。这也是为什么迁移团队只有不到10个人,就能完成所有的V3 应用迁移的原因。
在这一步,特别要强调的是工具要能提供应用拆分的能力。V3的应用是多个项目(project)聚合在一起,在打包的过程中才变成一个独立的应用。这些项目可以来自于同一个团队,也可以属于不同的团队。那么拆迁就有各种需求:
属于同一个团队的应用要求整体拆迁,和V3一样是一个独立应用。
属于不同团队的应用,有需求把各自团队的项目拆走,变成一个个独立应用。
有些没用的项目不需要拆迁。
我们的工具满足了这样的需求,用户满意而归。但是对于后面的流量迁移和就地环境的回收,给拆迁队带来了很多额外的工作量。
5.2 应用校验
校验分为拆迁团队校验和用户校验。当拆迁团队认为迁移的代码没有任何问题后,用户才进行必须要的校验。“应用功能无人描述的挑战” 就对拆迁团队提出了很高的要求:不知道业务逻辑,缺少测试用例,但是要保证测试质量。该怎么做?
为了这个目的,框架团队又开发出了两套流量镜像(Mirror) 工具。基本的思路是:白盒测试很困难,那么我们走黑盒测试。任何一个应用,给定一个输入必定有一个输出。假如能够直接使用V3线上的请求作为拆迁应用的测试输入,拆迁应用的输出和V3应用的输出进行对比,就能够进行测试了。详见下图:
图4
基于这个理念,我们做了基于流量的Traffic Mirror 工具来测试服务应用,和基于事件的 BES Mirror 工具来测试消息应用。解决了下面三个问题:
a. 功能性测试。就是把V3的请求分给拆迁的应用一份,运行同样的方法后,响应发到后台分析服务,通过比较差别来达到测试的目的。
b. 负载测试。把线上的实际最大流量复制到拆迁的应用,可以进行指标监控。可以真实地知道迁移的应用能不能撑起这个流量。
c. 创造测试用例。通过线上的实际输入,我们拿到实际输出,基本上一个测试用例所需要的元素就齐全了。那么可以反向生成这些测试用例,摆脱测试用例缺乏的困境。
5.3 流量迁移
流量迁移是整个拆迁过程中最重要的一环,也就是6大挑战中的”无间断应用导致风控难度高”这一挑战。如果这一步出了问题,直接就是生产问题。我们必须保证安全平稳地进行。因此,下面会多花点笔墨进行介绍。
“在无间断应用导致风控难度高” 的挑战下,流量迁移需要回答两个问题:1. 怎么迁 2. 怎么控制风险。首先我们回答怎么迁移的问题。
1)怎么迁
原本整个应用的流量迁移,是比较容易的。但是由于前文提到的应用拆分,就让流量迁移变得没那么简单了。针对不同的应用拆分场景,我们需要确定拆分模型,确定流量引入策略。
流量迁移模型
eBay的流量迁移需要考虑Software LB 和Hardware LB两条通路的迁移,非常复杂。在后续的文章中会详细说明。本文以Hardware LB流量迁移的四个常见用例来说明。
图5
注:GTM是eBay的DNS服务器
左上 是V3 整个应用都迁移到Rapor 新Pool。这种情况只需要保留相同的CName名称,修改GTM配置将其导入到新的Pool中。
左下 是一个V3应用被拆成2个或更多个服务,每个服务在V3都有独立的CName,并且这些服务的客户端都使用这些CName进行调用,这时候只要单独在GTM 层面迁移每个CName即可。
右上 是一个V3应用拆成多个服务,这些服务在V3他们还是分享同一个CName。在这种情况下,我们可以依据请求路径和请求头来设定LB的路由规则,然后将服务流量分配到相应的Pool中。
右下 是一个deliverable有个前置网关的情况,通常我们有两种选择:
a. 直接把网关的调用地址改成新pool的地址。这种是最干净的。但是这样的改动,流量上去就是100%,没有任何缓冲。通常只适用于流量非常小的Pool。
b. 网关先不改调用地址,还是根据情况按照其他三个情况之一进行迁移。等完全稳定了,再进行调用地址的修改。
生产环境上的流量引入策略
在生产环境,我们需要有渐进地增加流量的迁移,来应对随时可能出现问题并实现回滚。我们将使用1%, 10%, 25%,50%, 75%, 100% 的迁移策略,一步步增加流量的迁移。
2)强化风控
任何人都不能保证线上流量迁移的时候没有一点问题。对于风险第一是预防,第二是控制。预防靠数据,控制靠流程。我们依靠数据和流程这两样武器,硬是闯出了一条安全通道。
预防
风险预防靠数据。道路千万条,安全第一条。在流量迁移中,无数次化险为夷,靠的就是我们坚定地不打折扣地实行数据预防。风险预防主要体现在以下几个方面,在流量迁移的每一个阶段我们都要重复地进行如下工作:
异常对比。
我们收集V3应用的所有异常,同时也收集新的应用在这个阶段的异常,从而进行比对。如果出现V3的清单里所没有的异常,必须进行研究,给出结论。如果发现问题,必须完全解决。
功能验证。 主要依靠:
线上日志
监控系统
状态验证。 我们需要监控这些数据:
内存
CPU利用率
GC Overhead
剩余物理内存
请求耗时对比
负载均衡验证。 流量均衡是保证能够长期稳定运行的一个基础。主要检查:
每个区域的流量
每个机器的流量
迁移的流量百分比是否正常
只有这些步骤完全正常,我们才能进行到下一步。一旦有任何异常,都不能放过。有些应用(比如下文提到的buyingsvc) 有1000多台机器。那么意味着仅仅对这一个应用,我们就要监控1000多台机器的性能指标。同时这又不是一次性工作,流量迁移过程中每一个阶段,都要重复地进行不同区域、不同时间、不同流量下新老应用的数据对比。这就要求拆迁队不仅要有决心,更重要的是要有超人的耐心去承担巨大的工作量。
控制
风险控制靠流程。再严的家门,也不可能完全防住硕鼠。风险不仅要预防,还要控制。真出事了怎么办?谁来解决?根据什么来操作?这就是流程控制的作用。风险控制是一场团队响应时间与错误时间的对决。
准备阶段
拆迁队找到FE团队进行迁移前的沟通,确定目标和方案。同时通知用户,让大家都知道预定计划。
拆迁队发出ticket给FE 团队,描述迁移方案。FE团队收到请求后,根据方案,在FE的工具中设置好配置。
流量迁移
通知产线监控团队后,拆迁队用FE团队的工具自主开始切换预定流量。切换好之后,通知用户。
监控
用户和拆迁队会继续监控流量进入的情况。如果万一有问题,拆迁队可以用FE的工具在一分钟内回滚。如果十分紧急一时还找不到人的情况下,根据协议,用户可以找产线监控团队回滚。
迭代增加流量
流量迁移100%完成后,这个应用迁移就全部完成了。剩下的就需要观察一段时间后,进行旧环境的回收工作。
06 成功案例
这里,我们以buyingsvc 为例,说明整屋拆迁的效果。buyingsvc 是搜索部分一个重要的基础应用。当用户登录eBay,输入关键字进行搜索后,就会调用这个服务。可以说,buyingsvc和用户体验息息相关。它就是在拆迁的应用中作用最大的那个:机器超过 1000台 ,每天的流量超过 110亿 。它的迁移成败是决定性的。如果迁移失败,那就意味着V3迁移的失败。通过我们整屋拆迁的流程,这个应用顺利地完成了拆迁。虽然结果令人满意,但是实际过程并非一帆风顺,拆迁队和所有相关的团队合作,严格遵循流程才能圆满地完成任务。
6.1 结果——系统指标全面提升
对于这么大的流量,我们用了比原来更少的机器,同时机器的配置还降低了一半,却达到了系统性能的全面提升和本地开发体验的改善。
6.2 过程——战斗在踩坑和填坑之间
下面就以我们是如何发现隐藏的配置为例,来说明我们是如何克服搬迁的困难的。
buyingsvc配置到底有多少,无论是对拆迁队还是现有的应用团队都是未知的。如果找不全,就意味着功能的缺失。这个发现的过程需要巨大的努力,需要拆迁队、应用团队、流量控制团队和线上管理团队的信息交互。对于buyingsvc,我们有三个意外的发现,也填补了三个前所未知的“坑”。
1)高效沟通——发现未知的后台调控系统
对于buyingsvc调用的后台架构,左边的图是我们猜想的架构,右边是实际的架构。我们以为后台就是一个集群,但是实际的架构中有个中间件系统,它可以任意把流量切到不同区域的后台,这是一个重要的灾备能力。要让新的应用也有这样的能力,必须在中间件部分对新的应用进行配置,同时需要进行演习来验证配置的正确性。如果不是和线上管理团队的沟通,我们是不可能知道这样的配置的。
猜想的架构
实际的架构
2)性能比较——发现缺失的数据库配置
通过Traffic mirror的数据比对,我们发现buyingsvc的响应时间V3要比Raptor.io平均快10ms。但是所有的功能都正常。我们认为,从理论上看,Raptor.io的整体性能一定比V3好。如果个别的服务响应慢一些是可以接受的,尤其是那些响应时间只有几毫秒的服务。但是所有的服务速度都慢是不正常的,我们需要找到原因。
我们发现在三个区域SLC、LVS、RENO中,RENO的速度比V3快,其他两个区域明显要慢。通过查找代码,发现原来需要在数据库中增加配置,来进行后端匹配。例如,SLC的机器找到SLC的后端。如果没有配置,所有SLC,LVS,RENO的机器都会连到缺省的RENO后端。由于不在一个地点,有网络延时,所以SLC,LVS的速度会变慢。通过增加数据库的配置,Raptor.io就全面比V3的响应速度快了。
3)流量核对——发现丢失的GTM 配置
流量切换,如果比率不准,就是个大问题。如果流量过大,可能会导致当前的容量不够,把新的应用冲垮。如果流量过小,流量的切换设定无法覆盖所有的流量分支,那就会导致最后流量不能100%迁移。
在这个应用中,当我们切换10%流量的时候,进入到Raptor.io应用的流量要比理论的值少很多。左图是拆迁队理解的的模型,把所有属于GTM的CName配置好切换比率,流量就可以按照预想切换。但是实际上,有一些CName没有配置在GTM的管理中,因此这些CName的流量始终还是流向V3。按照这样的配置,即使GTM切到100%,V3还是有流量。这是以前配置的疏漏,需要把这些失落的CName加入到GTM的管理中。这样流量切换就正常了。
图6
07 总结
任何一个V3 的Pool 的消亡都是不容易的,感觉拆迁队真的是殚精极虑。治大国犹如烹小鲜,V3迁移是一个浩大的工程,但是每一个V3的应用的迁移,又都是一个独立成章的故事。我想分享的是,做一个项目,不仅仅是考验技术能力,还有项目的执行能力和团队的纪律性也都是成功的基础。说到做到、风险控制和风险预防,这些道理很简单,难就难在严格的执行,在日复一日的工作中始终做到一丝不苟。
对于拆迁团队,对于每一个应用,都有根据标准模板生成的文档来规范我们的行为,任何人都可以通过这个文档了解我们的工作进度和工作内容。从应用创建到应用流量迁移完成,每一步都有详细的数据和根据这些数据得出的结论,每一步的关键点都有检查结果,每个数据异常都是要刨根问题。任何光鲜成功的背后,其实都是千百次枯燥、无趣的坚守。
依靠严谨的态度,我们挑战了看似不可能完成的任务。不仅提升了技术,同时也锻炼了团队。回顾这一年历程,大家都觉得意义非凡。在后续的系列文章里,我们还会分不同的专题来与大家分享“平台迁移那些事儿”,道一道咱们这支eBay“V3拆迁队”的酸甜苦辣。
本文转载自公众号eBay技术荟(ID:eBayTechRecruiting)。
原文链接:
评论