简介:本文对过去十年CBU在研发方式和技术架构上的探索做一个简要的回顾总结,以及对未来的展望。
前言
CBU作为集团内最早成立的几个BU之一,有着多年丰富的业务沉淀,而CBU的技术也伴随着业务一起不断地演进和成长着。从PC时代的WebX到如今的Serverless,CBU的研发体系经历了多次变革,在不同的阶段中有着不同的特点。笔者所在的团队近年来一直在负责前台场景研发体系升级相关的工作,在这期间也对过往模式的演变进行了大量的回顾和分析,希望能够通过本文对过去十年中CBU在研发方式和技术架构上的尝试和探索做一个简要的回顾和总结,重新审视我们所走过的路,同时也对未来的方向做一些探讨和展望。
青铜时代(~)
10年前的互联网,移动终端还没有兴起,绝大多数的产品都是为PC用户所服务的。在这种背景下,采用B/S结构是一种毋庸置疑的选择,因此当我们回顾这个时代的技术时,最先能想到的自然是那些和WEB、浏览器关系最密切的关键词:比如WebX、jQuery、Velocity等等。
在这个阶段,业务流量并不巨大,系统的性能瓶颈基本集中在数据库的读写上,大部分的应用仍然采用单体式的架构,从前台页面到后台逻辑都封装在同一个应用中,而在应用内部,往往是采用MVC的分层思想对不同功能的模块进行划分。彼时CBU的前台应用架构也基本是这个思路,页面通过Velocity模板进行开发,后台业务逻辑则封装成应用中单例的Service实现,中间通过一个类似Controller的粘合层进行连接,将后端的数据字段转换成前端模版中所使用的变量:
这种模式的优点是,由于所有的模块都在同一个应用中,非常便于集中管理,当一个开发同学非常熟悉整个应用结构时,他便可以非常快速地完成一整个需求的开发。但缺点也同样明显:随着业务的发展,前台逻辑变得越来越复杂,需求必须要拆解成前后端分离的方式,让专人做专事,而前台代码被耦合在应用中,使得前后端分离开发变得异常困难;除此之外,前台逻辑的变化往往是非常频繁的,如果每次修改一个页面元素都要发布整个应用,不仅研发效率会十分低下,还会影响线上业务的稳定性。
为了解决上述问题,当时CBU的同学们充分利用了Java的动态类加载机制以及Groovy脚本语言,以一种特殊的方式实现了前后端分离开发和快速迭代,这里我们以商品详情场景为例解释一下其机制和原理。
首先,一张页面被拆分成若干个组件,每个组件都会对应一个bundle,这个bundle中包含了前台的vm模板,js代码,以及一个Groovy脚本。在实际研发时,需要先通过一个映射表达式声明该组件所需要消费的后台模型或字段,然后通过Groovy脚本(相当于Controller层)将其转换为vm模板中的变量,接着便可以开发前台的vm模板和js逻辑。开发完毕后,通过一个定制的发布系统,便可以把对应的bundle发布到前台应用中,由应用内部的JVM动态加载Groovy脚本以及vm模板,完成需求功能的上线。下图便是一个使用这套研发体系开发需求的实际例子:
这套研发体系通过JVM动态加载的能力,将面向前台的View层和Controller层逻辑抽离出来,使其能够进行独立开发和动态发布,从而实现了前后台逻辑之间的解耦,提升研发效率。只要后台逻辑没有大的变更,很多需求都可以通过bundle快速开发上线。不过在实际运行时,所有的逻辑仍然是在同一个应用中执行的,这在一定程度上会带来一些安全隐患。除此之外,这套研发体系也是非常定制化的,bundle的发布系统实现非常沉重,并且对应的前台应用有强绑定关系,这就意味着很难将它快速地复制到另一个业务场景中复用(CBU最终只有商品和店铺两个业务落地了类似的模式)。
尽管存在着一定的问题,但即便以现在的眼光来审视,也不得不承认这套研发体系有着非常超前的设计思路。尤其是通过引入bundle这一概念,使业务迭代开发变得十分聚焦。在本文的后续章节中我们会看到这一思路最终将伴随着云原生技术革命,再一次回到我们的视野当中。
蒸汽时代(~)
这一阶段,互联网行业的形态发生了非常巨大的变化。随着智能手机的流行和普及,移动互联网迅速崛起,各种各样的业务都开始向移动端发力。集团发动ALLIN无线的战役,大量的业务和产品需要快速向移动端迁移。同时,随着智能手机市场的不断下沉,加上其“随时随地”都能使用的特性,互联网业务此时所需要应对的流量挑战和PC时代将不再是同一个数量级。
在技术侧我们也能看到与上述现象所匹配的变革。一方面,由于流量的激增和系统复杂度的增加,传统的单体式应用无法再支撑业务的发展,随着Docker这一关键技术的出现,服务端应用的分布式拆分和微服务化成为不可阻挡的趋势。另一方面,由于移动端崛起,前台展示突破了PC键鼠交互以及浏览器能力的限制,用户对于产品体验和交互的要求势必会变得更高,这促使研发人员进一步细分化为负责底层业务逻辑的服务端研发和负责前台展现交互的前端、客户端研发:React的出现敲响了传统WEB技术的丧钟,开发独立APP成为拓展业务的不二选择,前端技术和客户端技术在这一阶段开始飞速发展。
这样的背景下,单体式应用和MVC架构逐渐死去,前后端分离的架构模式和RestfulAPI登上历史舞台,每个细分领域的技术栈都在飞速成长,大型软件的开发流程从此将会面对更加复杂的协作和研发模式。
回到CBU本身,这一阶段技术上最重要的任务就是将原本PC上的业务快速地迁移到无线终端上去,因此成立了专门的无线团队,开始重点打造手机阿里APP。整体思路非常简单明了,原有的业务体系和逻辑保持不变,进行微服务化改造,以RPC形式对外提供核心业务能力;架构上增设无线服务层,面向APP进行业务逻辑的适配和封装,通过集团统一对外网关提供RestfulAPI给客户端及前端开发人员使用。这样就可以在基本不影响已有业务体系的条件下,让APP上的业务快速跑起来。无线服务端在这里所扮演的角色非常类似MVC架构模式中的Controller层:通过RPC与底层基础业务交互,然后叠加面向无线侧的特殊业务逻辑,最终对数据结构进行一定的处理和封装,通过集团对外的无线网关透出给前台客户端使用:
在此模式下,无线服务端和客户端研发人员扮演着十分重要的角色,他们的研发和协作模式将最终决定APP的迭代速度以及质量。接踵而至的新挑战催促着CBU的工程师们对已有的研发体系进行全面的升级,而最终他们给出了十分精彩的答案:轻服务和场景搭建两大技术应运而生,接下来我们会看到,这两者结合所产生的奇妙化学反应,将会给前台场景的研发模式带来一次重大的突破。
轻服务平台
如上文所述,在ALLIN无线的时代,无线服务端的研发同学们需要在已有的基础业务接口上进行大量的改造和封装,为无线APP端提供服务接口。而在微服务架构下,服务端要对外透出接口,一般需要在应用内编写RPC服务,然后通过集团的无线网关将对应的RPC服务暴露成集团APP可以调用的HTTP接口:这种方式下一个服务从开发到上线往往需要数天时间。而为了保证客户端功能的快速迭代,避免业务受到发版节奏的影响,很多简单逻辑往往会被上行至服务端处理,这就对无线服务端的迭代速度和灵活性提出了一个非常高的要求。既有的技术生产力不能满足业务诉求,那就势必要进行创新,于是便诞生了能够支撑快速敏捷开发的轻服务平台,代号为MBOX。以今天的视角来看,这一平台践行的便是当下非常火热的Serverless理念,并为服务端同学提供了FaaS(FunctionasaService,函数即服务)的能力。
MBOX平台依然采用了动态类加载机制来实现代码的热更新,并结合字节码技术提供了一个JVM内的“安全容器”,把Java语言的动态化特性运用到了极致,其架构理念和实现原理如下图所示:
通过配套的研发平台和发布系统,开发者可以将自己编写的一个类动态加载进线上应用的MBOX容器中,并创建一个单例对象;各种常见中间件如RPC和缓存能力,都可以通过注解进行声明注入并使用;而服务一经发布,便可以通过指定的Gateway访问到。这种无需配置、开箱即用、快速上线的轻服务迭代方式,非常适用于当时无线服务端所面对的开发场景:对现有的业务RPC服务进行组合编排,再加上一些面向APP端的简单处理逻辑,使用MBOX便可以在几小时内完成从开发到上线的整个流程,生产力得到了极大的提升。
场景搭建
早在PC时代CBU就已经建设了页面搭建相关的技术产品,而在无线端,这一命题实现起来却要复杂许多。首先,客户端的页面并非像前端一样,由标准的浏览器所承载,iOS和Andorid双端从底层的系统机制到上层的组件实现都完全不同,要想实现统一的页面搭建,势必需要抹平这层差异。其次,场景搭建并不是简单的堆砌组件,还需要考虑每个组件背后的数据源:来自各种应用的服务接口必须和组件解耦,而不能在组件内部通过Native逻辑实现,否则将会导致组件完全丧失复用性,并且使业务迭代更加依赖发版。
为解决上述问题,各端的工程师付出了诸多努力。首先是制定多端差异的抹平和融合方案,该方案从各端组件化渲染方案进行抽象,统一了一套相对抽象、可扩展的协议,包含页面协议、布局协议和组件协议三大部分。页面协议指定了当前页面的基本信息、页面主体结构、埋点信息、渲染方式;布局协议指定了该布局下所有组件的布局方式,同时以布局容器可支持组件abtest、组件分流、组件个性化等投放方式;组件协议细化到组件的基础属性、渲染方式,除此之外,还会定义组件的数据绑定行为、数据请求方式、数据取数方式,从而将组件UI和数据解耦,提升组件复用性和可维护性。
Android、iOS双端分别面向这套标准协议,对端上的多种渲染方案和Native能力进行封装,提供了统一的搭建容器实现,抹平了多端渲染的差异。
在此基础上,前台的开发/运营就可以通过搭建和配置化的方式,构建出前台页面的渲染协议(页面协议+布局协议+组件协议),该协议最终被上行至服务端的“渲染网关”节点,由其来收口所有搭建场景中协议的下发。除了协议下发之外,渲染网关还收口了所有组件的取数逻辑,通过一个通用的数据网关接口来统一前台组件的取数方式,让整个搭建体系变得更加简洁和标准。
构建完整的场景搭建体系是一项浩大的工程,其中包含着无数研发人员的智慧结晶,受限于篇幅本文不再过多展开,想要了解更多的朋友可以参考我们之前的系列文章:
《CBU场景运营建设实践与探索》《CBU端容器标准化方案》
敏捷研发体系
在场景搭建体系中,渲染网关对外封装了统一的取数接口,前台的组件将会通过这个接口直接消费后台的服务端数据源,也就是一套重后端的方案(主要逻辑在服务端实现),因此在实际落地当中,往往需要为每个组件独立开发一个专属的数据源,这些数据源基本是对已有的RPC服务进行简单调用,然后封装一些前台相关的逻辑,因此使用轻服务来解决再合适不过了。于是两者相互结合形成了一套非常敏捷的研发体系:前端开发者开发UI组件,后台开发者通过MBOX编写一个轻服务,快速适配生成数据源,两者通过搭建进行简单的配置化绑定,一个页面就完成了,十分高效。正是这样敏捷的研发体系,帮助CBU快速地开拓了无线战场。
营销会场类页面是应用这一研发体系的典型场景,我们以某行业导购会场为例来体验其研发流程:
在这种研发体系下,前端和客户端研发人员可以专注于开发自己的组件,而服务端研发人员则可以使用轻服务的方式快速为对应组件适配封装对应的数据源接口(或者是编写传统的RPC服务),得益于搭建平台对组件和数据源的标准抽象,双方的研发流程可以互相解耦,让整个研发体验变得更加专注和高效。而采用这种前后端分离的模式之后,各端的技术能力和架构将得到更加聚焦的打磨,因此我们在之后将看到前台组件和后台数据源的研发模式都会出现新的突破。
总之,新的研发体系大大提升了前台场景的研发效能,这离不开背后的两大关键技术突破——场景搭建体系和轻服务平台。而在此之中,又蕴含着无数工程师智慧和汗水的结晶,是他们面对未知时的勇气和坚持探索的热情成就了这些伟大的技术产品,并为CBU研发体系的演进之路立起了一座新的里程碑。
向开拓道路的先驱者们致敬。
摩登时代(~)
故事还在继续。最近两年,移动互联网已经进入下半场,随着时间的推移,既有业务模式演变的越来越复杂,同时也越来越成熟,而在此基础上,又有着诸多新的赛道被开拓,越来越多的竞争对手走上了跑道。我们看到了航母级APP在一次次的打磨和历练中竣工并启航远征,各种新的业务场景像停靠在甲板上的一架架舰载机,随时准备以极快的速度起飞。总的来说,已有业务完成了野蛮生长,逐渐步入需要更多精细化打磨的阶段,而更多新兴的业务场景则需要通过借助既有的沉淀,用比以前更快的速度跑起来。
而在技术侧,职能细分化使得各端的技术栈在过去几年里都得到了相当大的突破:在前台展示方面,无论是前端还是客户端,组件化研发都已经成为基本共识,并且技术方案也高度成熟,甚至出现一些能够根据UI智能还原生成组件的技术。而在后端和运维方面,随着Kubernetes一统容器编排,云原生理念被迅速引爆,大量的底层运维和中间件能力被再一次下沉,以FaaS为代表的Serverless技术手段带来了生产力的极大提升,让上层人员能够更加