我在传统行业做数字化转型(2)技术篇
在过去的两年时间里,我加入了一家传统行业的企业参与其数字化转型的过程,现在我将我的经历分享出来,本文是第二部分—技术篇,主要会介绍一下我所在的技术团队实践的技术架构和体系,用到了哪些组件,以及一些心得感受。
上一篇:预告篇 - 介绍了数字化转型的背景以及什么是数字化转型
1、简单说说我司是干啥的
记得有位大佬说“一切抛开业务而谈技术的架构,都是耍流氓”,对,他就是玄姐。
玄姐说:架构需要服务于业务,针对不同的业务场景架构设计也会不同,架构设计不必追求高大上,简而美的架构,若能满足业务发展需求,便是好架构。
本来想在业务篇再介绍一下业务,但是发现只谈技术好像不解释一下业务背景,本篇很难说下去。因此,这里我首先简单地介绍一下我司的业务吧。
我司是天府之国本土一家家装公司,这里暂且叫它X公司。家装行业属于大居住领域的一个子域,而大居住领域属于衣食住行的“住”方向上。美好的居住环境是人类永恒的追求,同时也是人类财富的最大载体。尤其是我们这些城市的居民,我们大部分人的时间其实都是在室内度过的,所以X公司的slogan叫做“创造更好的生活,To a better life.”,朝着解决客户家装过程的体验的痛点出发,为客户营造一个更好的家。
X公司的业务包括了三大部分:精装、软装 和 定制柜体。如果有装修过自己家房子的童鞋应该都知道,精装就是基装,也就是铲墙、水电、吊顶、防水、铺砖、卫浴等一些列操作的合集。软装则是在基装的基础上为你的房子增添一下匹配的沙发、床、餐桌、椅子、地毯、灯具,让你可以拎包入住了。定制柜体则是让你的衣柜、鞋柜、吊柜等于你的房子100%的match并且还好看,这一点是标品柜子无法实现的功能,当然这也是一般家装公司和客户的标配选择。
2018年,X公司开始重视信息化、数字化的建设,也就有了2年前我从一家做保险的外企跳槽到X公司的经历。其实,大一点的家装企业早在几年前就已经开始重视数字化建设了,但能够持续投资进行数字化建设的家装企业并不多。这两年里,我和我的同事们从0到1构建了公司数字化平台的雏形和初期的技术架构。
2、总体技术体系与架构
在进入X公司后,我的领导便规划了信息技术中心的目标是“为业务插上体验和效率的数字化翅膀”,体验和效率是所有传统行业在提供服务上的短板,而技术团队需要做的是通过对业务的数字化改造实现公司的数字化转型,从而赶上互联网时代的步伐。
有了目标,那也得有抓手,我的领导选择的是构建一个适合X公司的数字化平台,可以服务公司各个核心业务和支撑业务的运营和协作。
平台化思维也是大多数传统行业进行数字化转型的一个重要思路和方法,平台化意味着协同、公开和共享,是需要站在整个企业的高度去思考和规划的。因此,我的领导们就在前期做了很多这样的思考和规划,交给我们技术团队的就是逐步去实现这个数字化平台。
我们最终选择了如下图所示的技术体系,这也是一个比较通用的具有微服务架构风格的技术体系。
-
在展示层,我们使用到的技术主要是React、Vue 以及 Flutter。React主要用开发业务管理后台系统、Vue主要开发to C/B端的商城、H5以及业务系统,而Flutter主要开发to C/B端的App。
-
接入层使用的是Nginx做反向代理和API网关的负载均衡。
-
网关层使用的是Ocelot(一个基于.NET Core开发的网关开源项目)开发的API网关,用以前端应用的统一接入,它还集成了鉴权、认证、限流等功能。这里区分了内部应用网关(即自己开发的前端应用)以及外部应用网关(即第三方应用 或 未来开放平台对外支持的应用)。
-
聚合服务层也就是我们所说的BFF(Backend For Frontend),是每个具体系统的后端API服务,他们大部分使用的ASP.NET Core开发的WebApi,小部分是使用Golang开发的WebApi(部分同事对Golang比较感兴趣,因此在BFF层的新Api项目做了一些尝试和实践)。所有的BFF都需要带上合法的token才能正常调用。当然,这一层的业务比较少,主要就是调用业务服务层的多个业务服务进行聚合,然后返回给前端应用。
-
业务服务层也就是我们常说的微服务了,像客户服务、订单服务之类的都在这一层次,它们是公司业务能力的整合,也是数字化平台的重要组成部分。
-
支撑组件层是一些通用的基础组件或服务,比如服务注册和发现、日志管理、Job、配置中心、容器平台等等。
-
基础设施层主要是服务器的资源,对于我们来说,计算、存储、网络三大部分的基础设施目前都已经上云了。嗯,我们选择的是阿里云。
-
其实按照目前主流的做法,在支撑组件层和基础设施层之间还有一层平台服务层,容器云平台就应该在这一层,不过我们暂时没有,也就没有考虑。
跟着这个技术体系,到目前为止我们逐步了一个实现如下图所示的总体架构,也有了一点领导当初设想的平台的样子。
在展示层,我们的前端应用目前已经有官网、商城SPA & H5,公众号、小程序、用于设计师设计项目交付的Web系统、用于营销员业务的App、用于工程施工项目管理的App、全业务流程的后端管理系统等,未来如果有可能,还可能会开放自身的接口能力提供给第三方合作伙伴。
在BFF层,我们针对各个前端应用开发了对应的API服务,当然,这一层的API没有多少业务逻辑,主要是做接口调用和数据聚合。而所有的BFF调用中台服务,都是走的另一个API网关,这个API网关是部署在内网的一个专门给BFF调用的网关,目前我们没有给它设置鉴权等功能,单纯地做请求转发。而所有前端应用默认只和BFF通信,因此他们只会走接入网关,必须带合法的token才能访问。
在核心业务服务层,相信大家也都可以看到核心部分就在此,这些微服务是为平台而整合和构建的核心业务服务,它们是在这两年多的开发中逐渐演化抽象出来的,当然里面部分服务尚在开发之中,但已经显现了雏形。而通用的支撑服务则使得业务服务的开发人员不再需要关注非业务部分的代码编写,比如使用Identity Server 4开发的认证和权限中心,使用Hangfire开发的的统一Job中心,能够发送Email、App推送(极光推送)、短信(阿里云短信服务)等消息的通知中心,集成第三方支付的统一支付中心,使用Consul的服务注册中心,使用CAP+RabbitMQ的事件总线等等。
目前,我们所有的微服务之间的通信都是走的REST,使用的WebApiClient这个组件,它类似于Spring Cloud中的Feign,是一个声明式的Http调用组件,非常好用,而且易于做单元测试。当然,目前量还很小,即使不走RPC,也还是可以接受的。以后量大了后,可能会对部分核心业务的使用GRPC。
有了核心业务服务和支撑服务,我不得不想起这其实就对应了所谓的中台。中台的非标准定义就是“企业级能力复用平台”,而客户、内容、订单、设计交付、工程交付等就是X公司的核心业务能力,这些服务面向不断扩张的服务于各个变化场景的前端应用(比如新增一个拼多多的营销渠道应用接入,某个新应用需要使用到客户数据进行分析,某个App又需要看到工程施工的全流程和现场图等等等等)提供可复用的能力。
在日志管理方面,我们主要使用一台独立的阿里云服务器搭建的Exceptionless日志平台,在越来越多的微服务下查看日志变得还是很方便。
在持续集成方面,我们主要使用的是Jenkins+一堆插件搭建的持续集成平台,可以实现某个业务领域相关的项目比如从Web、App(Android)到API的面向多个环境的(DEV、SIT、UAT、STAGE)持续部署到Linux服务器的构建。目前也实现了基于.NET Core的持续集成构建,包括拉取git代码到编译到单元测试(xUnit)再到自动化接口测试(Python编写)的流水线。对于这一块,如果有预算,建议直接上云服务,比如Azure DevOps这种服务平台,可以节省很多时间和精力。
画外音:不得不说,开发之余,为Service编写完善的单元测试还是很有必要的,可以提高check-in的信心,这是部分代码质量的保证啊。
在容器化方面,我们主要使用的是Docker + Compose。一来Compose比较简单易用,可以满足现有的Ops需求;二来Kubernetes基于目前团队的技术和运维水平自建不靠谱,上云服务今年疫情之下公司成本又不允许我们搞;所以,我们目前主要是基于Compose在Jenkins做了一套持续发布的构建任务,包括拉取代码、打镜像再到批量部署一系列的流程。
画外音:原本计划是今年上阿里云ACK服务(K8s服务),但是成本预算和各种限制条件实在不允许,因此考虑到Compose也可以满足未来半年的需求,就没有再继续调研了。毕竟,在满足现有业务的前提下,简单易用,就是符合团队的。
3、一些感想
演进源头:单体 or 微服务 ?
这是一个没有标准答案的问题,很多业界大佬也都对此有各自不同的看法。而我们在一开始就采用了微服务,一是在之前做了一些.NET Core微服务PoC的验证,二是我们没有多少现有的遗留系统便于从0开始演进,最后也是领导的“强烈”要求。
但是,我还是建议,在技术团队的人员水平、技术储备(特别是服务治理和运维水平) 以及 业务发展不明确的初期,选择 模块化的单体 进行演进可能会更好。
模块化的单体架构的项目代表可以参考SimplCommerce 和 ABP,它们都可以实现主程可以按功能拆分成N个平行的小模块,这样每位开发成员都清楚自己负责的模块。毕竟,新人是项目开发中最具破坏力的元凶之一,模块间独立、隔离可以有效的限制他们,避免核心模块或整体污染。最终实现,看起来是微服务,但其实还是一个单体。
SimpleCommerce:https://github.com/simplcommerce/SimplCommerce
ABP的话我不太了解,建议自行查阅相关资料,比如张队,比如梁老板。
在持续的演进过程中,可以将核心模块进行拆分,形成一个独立的微服务进行开发和部署。
推荐大家也可以去看看康威定律,微服务中很多核心理念其实在半个世纪前的这篇康威定律的文章中就被阐述过了,而且这篇文章中的很多论点在软件开发飞速发展的这半个世纪中竟然一再被验证。
用通俗的说法康威定律的第一定律就是:组织形式等同系统设计。当你犹豫不决的时候,不妨去看看它。
服务设计:DDD or 其他 ?
可能大家听说微服务最好的设计方法论是DDD,没错,正是微服务让DDD焕发了第二春,DDD也确实是微服务的最佳实践方法论。
但是,DDD的学习成本较高,技术团队里面需要有一个人是DDD非常熟悉的人,还需要有一个业务专家(这个业务专家可以是业务部门的人,但是,对于传统行业的企业来说,很难培养),对于我们团队来说,不具备这个条件,虽然我们也在努力的学习DDD,但是,你懂的,这个时间对于发展期的企业太宝贵,还是应该将资源重点先投入到业务的在线化上。
因此,我们没有采用DDD,代码层面也是简单的三层架构,因为,所有人都可以快速上手进行开发和维护,没有什么比快速上手更好的了。但是,快速上手节省出来的时间可不能浪费,针对Service的单元测试需要补上和完善,才能够保证CI任务的执行效率。
当然,现在没用DDD,不代表以后不用,可能我的同事们以后就会用DDD了。
基础设施:有预算能上云的尽量上云
对于传统行业企业的信息技术团队,一般来说人员配备即使很齐,但是技术储备都不够完善,大多数都没有大型互联网公司的经历,更别说像我们团队一样没有一个运维/DevOps人员。因此,建议所有的基础设施如服务器资源(比如阿里云ECS)、存储资源(比如阿里云OSS+CDN)、数据库资源(比如阿里云RDS)以及负载均衡(比如阿里云SLB)、容器编排(比如阿里云ACK)等基础服务和平台服务都尽量上云,可以帮助团队减少聚焦点从而把更多的精力留在核心业务的在线化上,也可以减少这些非业务的技术工作占据太多的时间以及生产问题。
当然,上云的前提还是成本预算,有预算的话,尽量选型成熟的云服务。目前我们选择的云服务有:阿里云服务器ECS、阿里云OSS+CDN、阿里云MySql服务RDS、阿里云短信服务、阿里云域名与证书SSL服务、阿里云性能测试服务等。
画外音:当然,有人会说全部用云服务,岂不是不能很好的锻炼自己的技术?但是,你有没有想过自研框架出问题的时候,你会有多崩溃。站在企业级的高度来看,技术是为企业的业务发展服务的,因此需要平衡投入与产出。
遗留系统:干掉可以干掉的,团结干不掉的
对于一个在进行数字化转型的传统行业企业,一般来说都已经经过了初期的信息化建设,有了各种各样的已有系统,有的是买来的,有的是自己开发的。如何在这种前提下,统一规划和逐步实现公司的数字化平台进而实现数字化转型,是需要技术者重点考虑的。
对于X公司来说,已有的系统包括了自己开发的OA、买来的酷家乐设计工具、买来的管家婆ERP等等等等,我们所采用的方针的就是:干掉可以干掉的,团结干不掉的。
举个例子,像对于OA这种自己初期开发的并不完善的系统,它的作用是各个业务部门之间的信息传递和协作,属于核心业务在线化的范畴,我们采取的是逐步干掉它,因为后面平台中的各个新应用系统已经实现了它的功能,而且能更好地让各个业务部门进行协作和共享。
而像对于酷家乐/三维家这种买来的设计工具,我们采取的是努力团结它,因为设计虽然我们的核心业务(比如一般企业的核心业务都是营销、研发/生产、供应链),但是工具这块不是我们的核心业务而且我们也真做不出来这种高效率的设计工具,因此我们需要努力团结它并使用它提供的开放接口和在线设计能力与我们的平台进行集成和整合,为我们的设计师提供统一的设计能力体验。
画外音:业务上的遗留系统尽可能逐步干掉,这样才能统一数据源。当然,前期可以采用数据同步的方式并行跑,但一定要把数据同步到新的统一数据源中。工具上的遗留系统尽可能保持现状,对这种工具的选型也要根据企业自身的情况来选择,比如没有供应链能力的家装企业可能会选择躺平,而自身有供应链能力的家装企业可能会选择酷家乐。当然,酷家乐/三维家和躺平走的模式本来就不同,选择也应当和自己企业的发展阶段和定位来进行匹配。
4、小结
本文介绍了我在X公司的技术体系和架构,以及我们使用的一些组件和实践,都是一些high-level的介绍,没有具体的东西。当然,还有很多不完善的地方以及需要持续演进优化的,但是它目前已经满足了X公司的业务需要和发展要求。此外,本文所分享的内容也存在着很多个人的偏见和愚昧,因为每个人的经历和认知都不同,我只能处在我这个认知前提下说出我想说的内容。
最后,谢谢大家的阅读!