https://yq.aliyun.com/articles/746515
阿里妹导读:
DataWorks是阿里巴巴自主研发,支撑阿里巴巴经济体99%数据业务建设和治理,每天数万名数据开发和算法开发工程师在使用。
从2010年起步到目前的版本,经历了多次技术变革和架构升级,也遗留了大量的历史包袱。技术的创新和业务的发展,相辅相成但也互为掣肘。存在需求接入慢,代码牵一发而动全身,环境复杂等问题,沉疴已久。历次迭代均未从根基上升级DataWorks,仅仅是一些性能提升、工程结构的优化,减少了重复代码等,并未促成根本性的技术革命。
本文将探讨如何通过当前大热的微服务架构,来改变DataWorks平台的现实问题,从繁杂的工程中探索出一条切实可行的技术架构变革之路
**一、痛点
**
让我们先来谈谈DataWorks当前遇到了哪些痛点,这些痛点是倒逼着我们进行技术变革的源动力。
1.1 沉重的历史包袱
首先要提的就是历史原因遗留的各种问题,DataWorks历史上多个版本同步开发,前后端技术栈多次变革,应用一旦上线就很难废弃,一个对外暴露的api,很可能是5年前开发的,但依然有业务在依赖,通常情况下连这些古老业务的负责人都找不到了。当我们的服务正常运行的时候,无人搭理,一旦下线,则可能不知道从哪儿跳出几个用户前来投诉。页面上的功能同样如此,有时候只是过去不知道哪位同学开发中引入的一个bug,但也因为我们的用户基数庞大,而变成了真理。历史上曾经出现过的隐藏的很深且用户寥寥的功能点都有自己的忠实拥趸,一旦被我们的开发不小心忽视而做丢了,就会迎来投诉和工单,所以DataWorks平台不愧是千锤百炼磨练出来的大数据开发平台的标杆,朴素的界面之下隐藏了无数细致入微的功能点。如果想重造这么一个被阿里巴巴经济体无数数据开发工程师验证(折磨)过的数据开发平台,都要好好考虑一下这十年来我们的平台到底经历过了什么。
1.2 复杂的软硬件环境
DataWorks面临的运行环境放眼整个阿里巴巴经济体都是及其罕见的复杂,为了混合云(即专有云)这种私有独立且封闭的环境,三合一版本之后我们必须放弃依赖弹内成熟的中间件体系,只能寻找那些同样在三个环境下都存在的技术来支撑。也因此,很多在某个环境下缺失的依赖,如果我们无法用开关的方式搞定,或者我们判断其复杂度不高,就会通过自研或者去依赖一些开源的体系来解决问题。而公有云上各种网络环境的问题几乎都要靠人肉去排查,从每天居高不下的答疑量上就能看到我们受环境问题的影响是多么耗费人力。除此以外,前不久中美贸易战带来的影响也传递给了DataWorks平台,运行环境需要匹配国产芯片,我们的进程不但要运行在X86指令集上,同样也要能运行在基于ARM指令集的国产芯片上。同时为了满足部分中小企业用户的购买欲求,敏捷化也是我们需要去裁剪设计的。
DataWorks平台虽然庞大且复杂,但在种种更加复杂的软硬件环境下,也同样需要能够做到灵活轻便,便于随时随地的拆散组合轻装上阵,以满足不同业务场景下用户的期望。因为挑剔的用户一贯希望用最少的钱购买到最合适的解决方案,DataWorks的竞争力显然也要从灵活且具备演变能力上寻找未来。
1.3 牵一发而动全身
工程之间的复杂关联一直是传统SOA(Service Oriented Architecture:面向服务架构)发展到一定规模后的噩梦,无论最初的设计是多么合理,多么领域清晰,一旦经历需求的积累,规模的扩张,人员的交替,都将逐步或多或少的面临着边界模糊的问题。最典型的例子就是单体服务之间的RESTful类型的API,往往这些API的Schema只能增加元素而不能减少,因为被依赖者并不知道有多少其他服务正在依赖这个接口,也许某一天某个服务从沉睡已久的服务器中被唤醒,结果发现你的API的Schema变了,那么一定会把你喊回来修回原来的样子。前后端分离架构下,这类问题更加突出,所以有的前端同学为了减少schema变动带来的影响,干脆让后端透传一个大字符串,即使里面夹带了私货,也不会使得页面莫名崩溃。DataWorks平台也正在经历着这一过程,发展到一定规模后,每个功能的改动都要小心翼翼,生怕对其他模块造成未知的影响,或者有时候我们需要把大量时间投入在调研清楚改动带来的影响上,就算这样严防死守,也依然可能有漏网之鱼,最后功亏一篑,一个故障单就可能把为之付出的努力付之一炬。
1.4 需求变更和频繁发布
除了工程架构上的问题,同样存在问题的还有众多开发者在合作方面产生的问题,gitlab帮我们解决了版本之间的代码冲突问题,但并不能解决产品发布周期上的冲突。当多个需求都要对外发布上线,尤其在混合云,需要按月为周期产出大版本,我们一边要快速上线新feature,一边还要按照类似瀑布模型的方式将这些功能打包进专有云版本。弹内、公有云、混合云的发布节奏截然不同,众多feature按照不同的节奏要出现在不同的版本迭代中,过去的熔断机制,更加剧了大家在窗口期集中发布而产生的风险。在SOA中的一个单体服务上,N个开发者开发的M个feature,按照什么样的间隔组合发布上线,使得发布的节奏既不过于频繁,也不会因为发布频次太少而使得版本跨度太大。如果这M个feature之间又存在依赖关系,则进一步放大了发布频次增减之间的矛盾。
1.5 国际化带来的问题
国际化的问题向来不简单,时区、夏令时、语言、习惯、本地化图标等等,对于DataWorks这样一个遍布全球20个region的平台来说,这里面的水深的很。我们团队在国际化方面沉淀很多积累,并且将这些优秀的经验对外开源:https://github.com/alibaba/react-intl-universal。
1.6 依赖耦合
基于SpringBoot的Starter,我们提升了代码的复用率,且对于Starter的精心设计,确保同学们自研踩过的坑不需要反复由不同的同学来踩。但是这毕竟是不同工程中的共同依赖,当这些Starter暗藏bug的时候,凡是使用到这些依赖的工程都将受其影响,甚至某位同学不小心在修改某个依赖甚广的Starter的时候写进了bug,就有可能触发系统雪崩。
1.7 笨拙的灰度机制
我们知道搜索引擎在不同的算法中寻找最优解的方法,是将这些算法灌装到不同的桶里,然后引流通过这些算法桶,通过各种指标的对比,将其中最优的算法挑选出来。这是一种基于架构设计的灰度机制,并不需要人为干预流量的导向,从入口处进来的不同搜索自然而然的就流过了不同的算法桶,随着海量的访问,最优解必然得以显现。但是目前的SOA架构下灰度往往依赖于提前设计好的开关,DataWorks便是如此,当我们需要验证某个功能是否存在问题,传统的办法是找到前端同学,让前端设计一下开关机制,筛选一部分用户进入到新设计的功能里面,经过一段时间的试跑和调整,逐步把问题解决掉,同时对用户的影响也可以控制在比较小的范围。但这显然不是一个可以反复的,随意的,自然而然的灰度机制。人为的干预,为灰度而耗费的设计开发,使得一次灰度的成本居高不下,有些时候我们的同学甚至因为想避免麻烦,而忽视做灰度验证。当我们想通过灰度来验证的功能非常的局部,或者用户无关,工作空间无关的时候,或者我们压根不知道哪些用户会使用到某些功能的时候,灰度机制也会在传统架构下失效,即使我们想去设计,也无从下手。
对于SOA下单体服务来说,灰度无法借助于架构的设计,但是DataWorks平台下底层调度服务Alisa的Gateway集群由于机器数量庞大,也可以实现基于架构设计的灰度机制,几百台Gateway中,我们可以取出一小部分,部署待验证的新版本,任务下发后通过不同版本的比对,寻找潜在问题。但这并非DataWorks平台后端的常态,几乎所有单体服务并没有部署到这么多机器中,因此这也几乎是大多数SOA的状态,都面临着不能基于架构设计,而要基于人为干预的灰度机制。
1.8 外部关联服务的不确定性
外部关联服务复杂多变,且不可靠不稳定,随时会宕机或者网络中断,甚至是外部服务升级忘了通知我们,从而导致故障频繁。这一点对于数据集成这样一个在几十种引擎,数千个数据库实例中搬运数据的应用来说尤其深有体会。为了应对外界服务的不确定性,我们将有众多依赖的自身应用设计的鲁棒性特别优异,然而这会增加我们自身代码的逻辑复杂度,偶然出现的问题也会被代码的鲁棒性掩盖,问题如果不及时处理,就会逐步积累,当所有出现故障的条件凑齐之后,一次性爆发一个P1级别的大故障。
1.9 紧缺的前端
DataWorks研发平台还面临着前端人手不足的问题,这是富交互产品的研发团队都面临的共通问题。前端受制于交互的不同,样式的迥异,业务的区别,以及研发同学各自对业务理解上的差异,以至于能够复用的前端组件极其有限。在浩如烟海的前端类库、组件、样式中,能够实现成本转移的寥寥可数。在前后端分离,基于主流前端框架的设计模式下,相较于历史上的前后端一体设计体系下的用户体验是有提升的,然而这都是基于前端开发同学辛勤的劳作,一点点的调整样式和交互换来的成果,这里从来没有捷径可走,而我们只能寄期望于能够复用前端开发同学的研发成果,让每一次设计都不要成为只使用一次的劳动。
**二、合作与竞争
**
DataWorks研发平台众多功能涵盖了数据开发工程师的日常工作,用户在我们的平台上长年累月的伏案工作,对一些功能点的设计有自己的切身体感,而这些体感是我们平台的研发感受不到的。PD和我们的UED去收集需求去使用去亲自感受,然而毕竟不是专职于数据开发本身,因此很难体会到数据开发工程师长期使用后的那种细微的挫败感。再到细分的垂直业务市场,不同行业下如何使用我们平台,差异更是有天渊之别。面向金融,银行,政府,大型国企,互联网公司,传统企业,民营,教育,等等,他们的用法都是完全不同的,有的行业甚至就不知道拿到DataWorks平台后该做什么。用户的需求千差万别,用户的心智也处于不同阶段。
因此,在我们无暇一一顾及的领域,前方的交付团队或者公司,使用DataWorks平台应用到具体的行业中,然后再将行业的专属需求带回给我们的PD进行分析。我们平台本身也会开放一些Api给予前方团队包装成产品提供给特定领域的客户,帮助客户解决实际问题。
新的产品规划还在不断制订之中,引擎团队设计好自己的产品也需要在DataWorks平台上降低用户的上手难度,如果永远只是DataWorks平台的开发同学按照排期逐步完成这些接入和订制需求,平台注定难以持续发展壮大。因此,从前后端架构层面,从无数的合作和竞争场景出发,都迫切需要我们进行一次针对自身的技术革命,彻底从SOA中解放生产劳动力,引入更多的用户侧的研发力量,帮助平台向更健全的方向发展。
**三、架构的变革
**
任何一种技术的变革都是循序渐进的,这和Spring之父Rod Johnson秉持的理念是一致的。他提出了“轮子理论”,也即“不要重复发明轮子”,这是西方国家的一句谚语,原话是:Don't Reinvent the Wheel。除此之外,通过长期的实践后他在著作中总结阐明了循证架构的思想,即“没有最好的架构,只有最合适的架构”。这是架构界进化理论的雏形,意味着我们的架构要不断的演进去配合多变的业务需求。
传统的SOA下,服务趋向于稳定和集中,单体服务之间是平等的,或者至少在共通的结构上是类似的,服务与服务之间通过网络通信进行依赖。SOA下每个单体服务可能是多个开发者围绕着进行合作开发,因此替换任何一个单体服务都是一件伤筋动骨的事情,当有大的技术栈的变革,例如从WebX 3.0升级到SpringMVC,从SpringMVC升级到SpringBoot,人力成本消耗都是巨大的,升级周期动辄以年为单位,更不用说假设我们想用Go语言或者Python的Django框架来替换J2EE体系下已经设计好的web服务,这几乎是不可能完成的任务。也意味着当我们进入了这个技术体系,就很难再从这套体系中脱身,更无从谈起架构的演变和进化。
在传统SOA下,提升工程效率的手段是极致的代码复用,凡是可复用的代码,都抽取到二方包中设计成类库让不同的单体服务依赖调用。虽然配置越来越复杂了,但的确减少了“重复发明轮子”的事情。
还有一个办法,是如我在2015年时候尝试新的架构设计时候采取的方法,即:能抽象成二方包的抽象,不能抽象的通过自动化代码生成工具自动生成。一套演练成熟的SOA架构工程,从目录结构到配置组装都几乎是稳定不变的,即使有变化,也都是按照MVC三层架构进行微调,因此我们可以把一些无法抽象的,或者包含了复杂逻辑,需要灵活调整的代码通过自动化代码生成工具来生成,并且尽可能冗余代码的功能,让开发者从生成的工程代码中尽量做减法或者根据业务逻辑只修改最少量的代码,从而提升了工程的整洁度和开发效率。
除了代码的复用,还有服务的复用,我们设计了一些中心化的单体服务,用于将复杂逻辑或启动较慢或需要缓存,等等这样一些功能封装在这些核心服务中,进一步减少围绕中心服务的其他应用的体量和复杂度,当然这也可能会引入单点可靠性的问题,但要确保核心服务的稳定可靠,在一定规模的服务体量下并非难事。
即便如此,SOA在效率上的提升依然是有限的,初期工程建立的快速高效并不代表长期业务开发后还能维持这样的效率持续发展。前文描述的痛点逐步展现且缺乏行之有效的解决办法,开发者由于整齐划一的使用同一套技术栈甚至同一套工程目录树结构,虽然在协同的时候更加默契,但也消灭了前沿技术在团队内的赛马机制。研发同学在一套逐渐古老落后的框架下研究怎么压榨出最后的效率和性能,但往往忽视了也许换个框架换个技术栈甚至换个语言,就会带来质变。因此,当基于谷歌的K8S体系成长的生态圈逐步成熟之后,遵循“没有最好的架构,只有最合适的架构”的思想,我们开始思考如何将DataWorks的技术方向转向灵活多变的微服务架构。
3.1 微服务架构
提到微服务,理所当然要和云原生关联,所谓云原生(Cloud Native),包含了如下三点:
1)DevOps
开发和运维不再是分开的两个团队,而是你中有我,我中有你的一个团队。
2)持续交付
持续交付的意思就是在不影响用户使用服务的前提下频繁把新功能发布给用户使用。
3)容器化
容器化的好处在于运维的时候不需要再关心每个服务所使用的技术栈,每个服务都被无差别地封装在容器里,可以被无差别地管理和维护。
满足上述三点的云原生环境,对于微服务来说天然适配。当一个产品发展到一定规模,且具备了足够体量,拥有数量众多的子产品,以至于交互和依赖关系日益复杂,则微服务架构将为这样的产品下的工程群带来显然易见的好处。本文不对微服务的基本概念和泛泛的常规做法做详细介绍,网上此类文章汗牛充栋,这里仅推荐两本不错的书《微服务设计》(前几章概念讲解还可以,后面部分一般)和《微服务架构设计模式》,前者适合初步了解,后者适合进阶。本文仅讨论DataWorks在新的架构下的做法,从实践中得真知。
对于DataWorks研发平台下众多产品应用来说,微服务架构方向的改造也许不是能破解所有问题的万能钥匙,但一定是当前开发模式所遭受的病痛的解药。
★ 3.1.1 认清自身
DataWorks研发平台属于典型的PaaS应用,当然也有数据服务这样的产品做到了SaaS层。传统SOA遇到的痛点,以及将来我们要对客户开放的定制化能力,需要借助微服务架构来应对,逐步将研发重心从PaaS移向SaaS。
当我们采用基于K8S容器化的微服务架构之后,开发者可以在我们自主研发的微服务平台中集成DataWorks平台开放出来的基础OpenAPI,也可以集成外部应用的API,在微服务中进行数据整合和业务逻辑的编写,最终暴露出一系列在平台前端可访问的API,供前端功能模块使用。在这个过程中,我们可以顺便化解前文提到的一些痛点。
★ 3.1.2 解决痛点
以历史包袱为例,我们可以逐步将年久失修的,陈旧的SOA单体服务中包含的功能进行替换,将这个快变质的大饼切割成一个个低耦合的小饼,实现逐步的更替,而非采用长周期的一次性整体替换。陈旧的工程不必再去发展更新,仅维持基本的运行,避免了整体替换带来的周期长,故障多,回滚困难的问题。而且我们可以很方便的通过金丝雀发布来验证新上的“小饼”是否成功替代了“变质大饼”中一小部分模块的功能,通过蓝绿部署将有问题的小饼快速及时的撤下,也可以做到通过ABTest来验证哪块小饼的性能更好、设计更合理。
再以个性化需求为例,当我们开放了和DataWorks业务耦合的微服务平台,具备自研能力的业务团队(如数据/报表开发团队)就可以借助微服务的设计,快速的将自己的需求设计到我们DataWorks平台后端,同时前端页面我们也会留出“自留地”(下文描述的插件化)供业务团队自行设计开发。引擎的接入同样可以参照此模式进行,DataWorks下一部分模块的接入可以更加的傻瓜化,比如检查器,比如功能强大的自定义节点等,用户根据文档经过简单的开发后就可以快速自主接入使用,但对于更加订制的功能,例如当前ADB引擎正在DataWorks平台上进行的可视化建表部分的设计,由于复杂度很高,因此必须通过微服务对接前端插槽(下文描述)来进行开发,从而实现复杂业务逻辑的自主自助接入。
再来描述一下基于架构的灰度机制,在微服务架构下,可以轻松的实现蓝绿部署,金丝雀发布和ABTest,我们的微服务设计应该是尽量面向领域的(当然不太可能做到100%的面向领域),高内聚低耦合依然是单个微服务的设计宗旨。我们可以发布多个版本的微服务用来测试某个领域的问题是否得到某方面的改善,也可以发布多个完全基于不同框架甚至是不同语言设计的微服务,来验证某个领域内谁是最优解。借助于基于架构的灰度机制,基于云原生,这一切都将非常高效且可靠,即使出现问题,也可以快速撤下有问题的微服务,避免扩大影响。
还有其他一些痛点,不一一描述基于微服务架构的解法,比如牵一发而动全身的问题,在DataWorks平台全面构建到微服务架构上之后,这个问题自然就会消失。每个同学都可以分管多个面向领域的足够小的微服务,当某个接口需要重新设计,不必立即替换老的接口,而可以将这个接口下对应的微服务低成本的重新设计,等待流量切换到新的微服务后,再逐步下线旧版本微服务。再比如SpringBoot下由Starter引入的耦合性,到了微服务框架下,将会通过服务发现来解耦,不再需要通过代码层面的依赖来耦合关联。
★ 3.1.3 循证架构
再回过头来讲讲本文还没提及的一块内容,我们的微服务到底是什么?微服务当然不是一定要以微小为特征,它还是一个SOA,只不过会更加轻量级更加面向领域。以机器人工厂为例,该产品有一个功能是让用户配置一些意图跳转到用户自己设计的应答逻辑中,这部分正在拥抱微服务架构,完成上线后,用户可以根据输入来设计自己的应答微服务,且语言无关。这样做还可以避免用户的微服务在设计不良的情况下崩溃,不至于影响到其他正在运行的微服务,机器人工厂的这个场景也可以设计成FaaS,用户只需要编写函数就可以完成自己的应答逻辑,且按访问量来计量使用情况。
DataWorks团队设计的微服务平台,充分拥抱了现在大热的Service Mesh,即服务网格,通过Mesh将一部分工作封装在前置的微服务里,这些系统级微服务与开发者设计的微服务运行在同一个pod里,使得开发者设计的微服务更加简单,Mesh更像是Spring框架下的HandlerInterceptor或者Filter,面向AOP编程的开发者擅长在工程里开发拦截器和过滤器,到了集成了Service Mesh的微服务框架下,可以方便的使用系统级微服务替代一部分传统拦截器的工作。比如登陆跳转、权限控制、服务发现,比如限流、监控、日志聚合等等。
让业务专注于业务本身,避免诸如登录配置、日志配置等对工程开发的干扰,同时我们还设计了不同语言的DMF(DataWorks MicroService FrameWork)框架群,帮助开发者快速上手微服务的开发。“没有最好的架构,只有最合适的架构”,将来我们也会开放DMF的开发设计,让更多业务方贡献自己的“最合适的微服务框架”。为了更好的支持和我们业务强相关的DevOps,我们开发了DataWorks微服务平台(DMSP:DataWorks MicroService Platform),用于管控微服务的部署和发布,以及服务治理等其他运维工作。
3.2 前端的体系配合
前面提到的插件化指的是我们前端团队设计的XStudio插件化方案,插件结合后端微服务,成为一套整体的解决方案,DataWorks平台的前端团队希望基于此,尝试探索出一套提升前端研发效率的方法论。XStudio插件化基于 single-spa 和 qiankun框架实现。该框架提供了多实例模式,插槽机制和可视化插件编排等重要特性,进一步提升了插件开发的效率。整套插件化的示意图如下:
前端同学在基于XStudio插件化设计的页面上,留好插槽,插槽里面可以是一个按钮,也可以是其他任意类型的组件,这个组件后面绑定一个微服务,我们可以将插槽里面的内容连同后端的微服务一并替换,实现页面功能的快速组装,从而实现一次开发的多处使用。同时,插槽里的内容也可以由业务开发团队来提供,那么业务开发团队也只需要自行设计前后端一体的这样一个插件来放置到前端插槽里,实现个性化需求的订制开发。
在传统的插件化设计里,开发者们要么提供一个遵循某种接口协议的二方包、要么提供一系列遵循某种协议的API再由SOA架构向前端输出。这带来的问题要么是对SOA服务有侵入,要么影响了SOA服务整体的安全性和稳定性问题,要么受限于编程语言、要么毫无灵活性,而微服务&插件化完美的解决了这类问题。
对于需要占用更多页面空间的设计,我们可以将大片区域设置成可替换组件,比如上图的编辑器部分,让用户自行替换掉这片区域的页面内容,跟后端一个或者多个微服务关联起来嵌入到DataWorks的前端页面中,方便业务团队实现更复杂的自定义业务逻辑。当前ADB的可视化建表部分的设计正是遵循了这套方案,由ADB引擎团队自行开发接入DataWorks平台中。
同时,前端体系中还有重要的一环是受访的数据监控和报警,我们设计了各种维度的报表和指标监控,无论是自己的业务还是外部业务团队写进来的组件,不用多写一行代码,都可以通过“自动化全量埋点技术”,观察和了解组件的使用情况。
3.3 插件的运行
当前我们已经将部分前端基于XStudio架构的组件与后端微服务配合起来实现了插件化封装,比较优秀的如Terminal,DWEditor,目录树,检查器等插件。以Terminal为例,该插件设计完成后,插入到不同的Studio中对接不同的引擎,并且可以根据用户的使用情况自动拉起或者销毁容器实例,从而节省运行资源。
Terminal插件接入到多个引擎,无论是前端还是后端的微服务都不用针对引擎进行额外的开发,从而实现开发效率的提升。插件化的封装设计,不仅可以节约开发资源,而且可以实现多个应用集中使用一套微服务的目的,而弹性编排和自动扩缩容机制保证了服务的性能,同时不至于浪费机器资源。
此外,基于微服务架构,我们还可以构建SaaS的一些实现,例如FaaS、BaaS(Backend as a Service),以及BFF(Backend For Frontend)。以BFF为例,移动端的DataWorks应用BFF后,可以减少移动端H5页面的网络消耗,将后端多个微服务提供的接口通过Gateway组装后提供给移动端,实现微服务的聚合。如果通过BFF做了SSR(Server Side Render:页面同构,相当于在服务器端直接渲染成html输出到浏览器),则可以进一步降低移动端的渲染性能消耗。
★ 3.3.1 DataWorks微服务平台
前后端一体基于DataWorks业务的插件化,也是我们坚持要自研设计开发DataWorks微服务平台(DMSP:DataWorks MicroService Platform)的重要原因。DMSP打通了前端组件的发布和后端微服务的绑定关联,通过Swagger这样的技术手段成功使得前后端在部署后可以迅速成为一个业务插件。让团队的前后端都可以在DMSP里面实现DevOps,以持续交付的方式源源不断的将新功能发布给客户。
尤其值得说明的是,DMSP同样是针对三大环境的,即弹内、公有云和混合云,插件开发完成后,我们要通过DMSP持续交付到公有云多达20个region的环境中,还要能够实现微服务在专有云的统一打包部署。并且,DMSP还要让开发插件的同学尽量对复杂的外界部署环境无感。
未来我们期望整个DataWorks平台的大部分页面内容都基于插件化设计,从而解决前文痛点里面提到的问题:“灵活轻便,便于随时随地的拆散组合轻装上阵”。架构驱动的不仅仅是开发模式,而且势必还将影响到整个产品的蓝海。
**四、构造生态
**
构造生态的重要前提是要有竞争,要有优胜劣汰,构造生态的同时就是在构造可以演变,可以适用进化论的技术体系。作为“循证架构”的升华,微服务架构显然在进化方面更胜一筹,循证架构是一种自上而下用进废退的技术演进路线,而微服务架构则是一种自下而上优胜劣汰的技术演进路线。容器化实现了语言无关,框架无关,每个微服务都被无差别地封装在容器里,从而可以针对一个功能开发出多种微服务,类似算法桶的优选机制,从这些完成同一个功能的微服务中挑选出最优解。在理想情况下,无需上层架构师的主动干预,应用就可以在一段时间的进化后自组装成最佳的实践。当然这只是理论上的情形,我们身处的现实世界受很多外界因素的干扰,实际情况下,受限于开发者的技术素养、外界依赖的参差不齐,甚至是受限于KPI的导向,都将使得这种理想下的最佳实践无法达成,但微服务架构给予了我们可以通过团队的协作和努力,从而无限接近理论中的最终解的能力。
在微服务架构下,前文提到的垂直业务的定制开发也将成为一种可能性,面向行业的交付团队可以利用DataWorks平台提供的插件化能力,为客户订制完全适配行业特征的智能研发平台。进而在DataWorks研发平台上营造一个有活力的创新生态圈,为客户提供更加丰富多彩的选择。架构将驱动整个生态圈的优胜劣汰,从而不断向更有竞争力的方向进化。
我们DataWorks研发团队也寄期望于在这套架构之上,实现弹内弹外的共赢模式的合作,推动云智能事业群下的产品形成合力。
**五、前后端组合拳
**
所谓架构,不仅是技术上的事情,同时也要对人力的分配组织提供整套的指导方案。在应用了微服务架构之后,DataWorks研发团队的职责显然不能仅仅局限于日常的需求开发,作为微服务架构的倡导者,在推进架构的同时我也对团队的前后端职责进行了思考。首先前后端需要拉出一个框架小组,通过指导前端组件和后端微服务的设计来影响整个架构的进化,团队内需要有关注面向领域设计的研讨,分析每个插件是否是领域性的,同时需要有把关的同学,审核第二方(弹内非本团队的开发者)和第三方(弹外的交付团队或者来自客户的行业开发者)提交的插件设计,防止不良应用破坏体系构建。
同时,微服务架构由于语言无关性,还抹平了一些技术上的鸿沟,前端同学很多擅长nodejs,也可以在微服务的设计中一展身手,更使前后端在技术上的交流和沟通会更加有默契。我们的产品线中还有一个特殊的产品:AppStudio,专职于WebIDE的研发工作,将来无论是数据服务提供的数据出口,还是FaaS里的函数,还是微服务本身的开发,都可以与AppStudio结合,由用户自主开发,可以完全不用脱离DataWorks全域大数据平台,就从数据开发到报表设计,再通过微服务编写业务逻辑,达成数据输出的目标,一站式完成用户的订制需求。
上图是未来的团队职责分工的一个构思,前后端研发同学在这套组织架构下,打出一套组合拳,直击痛点问题,帮助用户攻克技术难关,实现生态的繁荣昌盛。
**六、展望未来
**
技术和架构的未来是什么样子的?在我的理想中,软件工程的研发技术应该是一个没有止境和边界,且越来越智能化的领域。DataWorks的产品中已经有很多开始向智能化的方向前进,比如基于VSCode应用了Markov算法的智能编程插件。研发团队的未来很大程度上取决于体系的架构,我们应该鼓励创新,鼓励对技术前沿和边界的探索,不应该人为的制造太多规约从而限制了思考的天马行空。如果有一天,智能化编程终于开始替代人工开发,那么通过改变架构的设计,研发人员也一定可以在新的架构中寻找到新的职责。
世界是变化的,也是有规律的,我们的技术愿景应当是为这个变化的世界构建出成熟且不断进化的工程体系。面向未来,拥抱变化,为了无法计算的价值!欢迎识别下方二维码,了解团队信息,加入飞天大数据交流群和DataWorks产品进行交流!