传统模式下,企业的经营活动会产生大量的业务数据。 财务人员需要根据业务数据,进行会计核算,并输出财务数据。 通过这些财务数据,企业可以进行财务管理、财务分析、业务决策。 但会计核算的工作量非常庞大,大多工作也比较基础、简单,可以被计算机替代。 企业每年在基础的核算工作上会花费大量的人力资源,在更重要的财务管理、财务分析、业务决策上无暇顾及。 为了解决此类问题,财务中台应运而生。
财务中台是业务系统和财务总账系统间的桥梁,通过汇集所有业务数据,进行筛选、核算、转换,自动生成财务数据,并传入财务总账系统,节省大量会计核算的人工成本。 除此之外,财务人员不需要在各个业务系统间来回切换,核对业务数据。 财务中台汇聚了所有财务数据,财务人员可以在统一的工作台上进行数据核对和会计工作,不需要跨多个系统操作。 通过财务中台,可以轻松实现业财一体化,财务人员可以解放生产力,产出更高的价值。
零售整体业务架构分为前台业务、总部中台、企业/业务后台。
前台业务的特点是变化快、差异性大、细节体验、跨平台、多触点。 前台业务帮助商家整合尽可能多的零售渠道进行销售,以满足顾客购物、娱乐和社交的综合体验需求。
总部中台从架构上是串联前台业务和后台业务,基于零售商家的核心经营场景,建立会员、交易、营销、运营、财务、数据等核心功能。 总部中台并不直接为商家和消费者提供应用服务,它的主要职责是汇总所有业务数据,协同各个业务单元,提炼业务的共性需求,支撑前、后台业务的快速发展。 通过总部中台,商家可以跟踪和积累消费者的购物全渠道、全过程的数据,在这个过程中与消费者及时互动,掌握消费者在购买过程中的决策变化,给消费者个性化建议,提升购物体验。 再依靠大数据,对用户做到精准营销、智能推荐商品; 智能化采购更适合销售的产品; 做好财务管理,持续提升资金利用效率。
企业/业务后台包括采购要货、供应链、原材料管控、生产制造、合同管理、加盟代理、财务总账等基础业务。 部分业务可能由商家的ERP系统完成,所以总部中台和ERP系统会做好数据对接,商家的ERP系统仍然可以继续使用。
财务中台属于总部中台的一部分,财务中台通过汇集所有业务数据,进行筛选、核算、转换,自动生成财务数据。 同时,财务中台提炼出财务相关的共性服务,支撑前、后台业务的快速发展,帮助商家做好财务管理、财务分析和业务决策。
财务中台汇集全渠道销售、供应链、资产、营销推广等数据,自动完成会计核算,生成相应的财务数据。 同时,财务中台可以进一步对接企业的财务总账; 为其他系统集成提供标准化的开放能力; 为合作伙伴提供费用对账等服务; 为数据报表提供原始数据,加工出财务报表,为财务分析、业务决策提供有力的支持。
应用架构定义了系统由哪些逻辑模块组成,以及逻辑模块之间的关系,也称之为逻辑架构图。 应用架构起到承上启下的作用,一方面承接业务架构的落地,一方面影响技术选型。
设计应用架构,首先要明确设计的粒度和层次,在不同粒度和层次,关注点是不一样的。 零售业务异常复杂,对于这种复杂业务,尤其要从宏观到微观逐层进行详细的分析和设计,保证整体架构的有序性和一致性。 如果不这样做,很容易让产品技术团队陷入混乱中,进而极大降低团队的沟通和协作效率。
这里可以结合 Simon Brown 提出的 C4 模型来考虑设计元素的粒度和层次。 自上而下,Simon Brown 将整个软件系统分为了四个层次,分别为系统上下文(System Context)、容器(Containers)、组件(Components)以及类(Classes),这些层次的说明如下所示。
系统上下文:是最高的抽象层次,代表了能够提供业务价值的构件。一个系统由多个独立的容器构成。
容器:是指一个在其内部可以执行组件或驻留数据的构件。作为整个系统的一部分,容器通常是可执行文件,但未必是各自独立的进程。
组件:可以想象成一个或多个类组成的逻辑群组。组件通常由多个类在更高层次的约束下组合而成。
类:在一个面向对象的世界里,类是软件系统的最小结构单元。
那么,财务中台系统在上述四个层次分别该如何设计?
首先是系统上下文层次,该层次会重点关注要设计的系统和其他系统之间的关系。 财务中台系统上下文的设计如下图所示。
3.3.2 容器层次设计
其次是容器层次,该层次会将整个系统放大,关注系统内部由哪些容器构成,容器基本等同于限界上下文的概念。 限界上下文的划分是 DDD 战略设计中的一部分,而且是最核心的设计工作,需要在该层次识别出限界上下文,这会对后续微服务架构落地起到关键性作用。
上图为财务中台系统内应用架构图,采用分层架构模式,图里的应用层、领域层、基础设施层和DDD中的概念一致,但它们是容器层次下的分层逻辑,视角是整个系统内。
对于单体系统来说,应用层和领域层逻辑会比较简单,通常会合并为一个微服务部署,内部也不会有非常清晰的限界上下文划分。 但对于企业级系统,业务逻辑非常复杂,内部会划分出众多职责单一、功能完整的限界上下文,以保证系统架构健康、有序地进行演进。
应用层:应用层是很薄的一层,应用层内的服务对应一个具有业务价值的业务用例。它主要负责对领域服务进行组合和编排,负责处理业务用例内的执行顺序以及结果的组装,通过API网关向接入层提供服务。容器级应用层涉及整个系统的逻辑,通常包含多个廉价的限界上下文,它们的内部业务逻辑不会很复杂,但因为直接面向用户,为了应对快速变化的外部需求,应用层变动会非常频繁,它通过领域服务的组合和编排实现业务流程的快速适配上线。例如:上图所示的结算管理是一个应用层限界上下文,它为接入层提供与结算管理相关的应用服务,它通过组合、编排领域层的核算域、结算域、收付域以及其他业务系统的领域服务,来实现自身应用服务能力。
领域层:领域层是很厚的一层,它是业务软件的核心所在,包含了本领域所涉及的领域对象、领域服务以及它们之间的关系,负责表达业务概念、业务状态信息以及业务规则。领域驱动设计提倡富领域模型,即尽量将业务逻辑归属到领域对象上,实在无法归属的部分则以领域服务的形式进行定义。用户的需求经常变化,但变化总是有规律的,用户体验、操作习惯、市场环境以及管理流程的变化,往往会导致界面逻辑、应用逻辑变化,但核心领域逻辑不会有太大变化,所以领域层的业务逻辑通常是共性的、稳定的。容器级领域层涉及整个系统的逻辑,通常包含多个限界上下文,它们为整体系统的微服务拆分提供依据。
基础设施层:它向其他层提供通用的技术能力,例如:分布式通信能力、持久化能力、消息通信能力、任务调度能力等。
再次是组件层次,该层次会将单个容器放大,组件是由一个或多个类组成的逻辑组,共同完成一类职责。 在该层次会关注容器内部是如何分层的,每层包含哪些逻辑组件。
上图为应用层容器架构,同样采用分层架构,包含接口层、应用层、防腐层、基础设施层。
接口层定义了提供给上层使用的服务协议(API),接口层的使用方通常是展现层。
这里的应用层是更细粒度的、容器内的层次,或者说是战术级别的层次,根据复杂度不同,它通常包含一到多个限界上下文的应用服务和业务组件,每个应用服务通过编排其他限界上下文的服务,实现业务场景或业务用例。
防腐层用于和其他限界上下文集成,在防腐层内部,你可以将自己的模型和外部模型进行转换,防止受外部模型污染,进而让内部逻辑不稳定。当外部模型或接口协议发生变化时,只需要修改防腐层逻辑,不会影响到自身业务逻辑。
应用层容器内通常没有领域模型,因此也不需要访问数据库,因为它内部主要是组合、编排的逻辑,如果出现类似领域模型的概念,要分析是不是有部分领域逻辑外泄到应用层,并考虑将领域逻辑下沉到领域层,以保证应用层的职责统一。
上图为领域层容器架构,分为接口层、应用层、领域层、防腐层、基础设施层。
接口层定义了提供给上层使用的服务协议(API),接口层的使用方通常是应用层容器。
应用层通过编排领域层的领域服务、领域模型以及少量外部服务来对外提供服务能力,这里强调少量的外部服务,是因为领域层容器内部的业务逻辑通常是共性的、稳定的,它只会依赖比它更基础、更稳定的服务能力,而且依赖外部服务要尽可能少,这样才能保证容器内部的业务逻辑是共性的、稳定的。
这里的领域层是更细粒度的、容器内的层次,或者说是战术级别的层次。领域层包含各种领域模型,例如:领域实体、聚合根、领域服务、仓储等。仓储作为领域层和基础设施层的连接组件,使得领域层不必过多的关注存储细节。在设计时,将仓储接口放在领域层,而将仓储的具体实现放在基础设施层,领域层通过接口访问数据存储,而不必过多的关注仓储存储数据的细节,这样使得领域层将更多的关注点放在领域逻辑上面。
领域层容器架构最核心的是领域层,它包含核心的业务模型和业务逻辑,它与具体的技术框架无关,只专注于业务本身,领域层是沉淀领域知识的地方,是业务人员和技术人员沟通的基础和桥梁。
3.3.4 类层次设计
最后是类层次,类是系统构建的最小模块,该层次关注组件里具体要设计哪些类,每个类的职责是什么,类与类之间的关系是怎样的,类层次偏细节,这里就不详细展开。
微服务架构,是一种技术架构方式。 它将应用构建成一系列按业务领域划分的、小的自治服务。 微服务被认为是未来的方向,通过将应用和服务分解成更小的、松散耦合的组件,它们可以更加容易升级和扩展。 越来越多的互联网公司使用这种架构来部署自己的系统,有赞也不例外。
微服务架构有很多的好处:
将巨大单体应用拆分为多个微服务来解决复杂性问题。
每个微服务可以由专门的团队来开发维护。
每个微服务可以独立部署、独立扩展。
微服务架构也有很多不足:
微服务架构是分布式架构,会带来分布式架构固有的复杂性。
数据库分区带来的数据一致性问题。
测试一个基于微服务架构的应用系统变得非常麻烦。
微服务架构实际上更多是技术实现和运维部署的范畴,究竟如何拆分微服务,微服务架构给不出答案。 这就要用到应用架构的设计结果,上文中说到容器基本等同于限界上下文的概念,限界上下文的划分对指导微服务拆分有非常重要作用。
一个微服务一般包含一到多个限界上下文,如何界定微服务需要包含几个限界上下文? 一是会根据限界上下文的业务复杂度来判断,如果复杂度非常高,并且由多名开发人员维护,一般会单独部署为一个微服务,独立演进。 二是会根据技术复杂度来判断,比如该业务域存在高并发、高可用、性能要求苛刻的场景,需要采用特殊的技术架构,通常也会考虑单独部署,与其他限界上下文在物理上隔离开。
微服务架构需要遵循逐步演进的原则,多个限界上下文一开始通常部署在一个微服务中,随着业务复杂度和技术复杂度上升,再逐步拆分为多个微服务。 一开始就把微服务拆分得很细,会带来大量分布式架构的固有问题,可能业务还没发展起来,就被分布式的问题搞得焦头烂额。
下面介绍一下财务中台的微服务架构是如何演化。
一开始业务比较简单,为了方便部署维护,如上图所示,所有限界上下文会部署到一个微服务中对外提供服务,但很快会遇到问题,业务越来越复杂,会与其他系统产生依赖关系。 例如: 供应链系统的进销存场景会触发财务中台的核算业务,财务中台需要依赖供应链系统的库存单据进行核算,供应链的某些场景也需要依赖财务中台的能力,进而会产生部署上的循环依赖,当某个项目双方互相依赖时,发布时就出现无法确定发布顺序的难题,强行发布会导致发布期间一段时间内部分功能不可用,不能平滑过渡。
为了解决不能平滑发布的问题,可以将应用层和领域层进行物理隔离,分开部署。 拿供应链系统和财务中台系统举例,从业务定位来看,供应链是财务中台的上游业务,供应链的核心业务逻辑是完全不依赖财务业务的,因此供应链领域层的限界上下文是不会依赖财务中台领域层的限界上下文。 但某些应用场景,供应链的应用层需要编排财务中台的数据给用户展示,或触发财务中台的业务执行,这时,只需要供应链的应用层依赖财务中台的领域层就行。 所以,发布顺序按照1、2、3、4的顺序发布,就不会再出现部署上循环依赖的问题。
随着业务量爆发,不同限界上下文面临的访问量级是不一样的,例如: 核算域需要处理高并发量的业务单据核算,需要解决高并发、高性能等的技术问题,所以核算域会单独分离出来,部署为微服务,这样就可以独立设计和水平扩展。
但有些限界上下文尽量能部署在一起,例如结算域和单据明细域,因为一旦分开部署,会产生分布式事务问题,这会非常棘手,现实场景也遇到过微服务拆分后,分布式事务问题一直没能很好解决,又把微服务合并了。 所以如果不是遇到业务复杂度过高、高可用、高并发、高性能等问题,尽量不要把微服务拆分得很细,防止出现业务未发展起来,反而带来一堆分布式架构固有的复杂性问题。
中台的定义来源于阿里的中台战略(详见《企业IT架构转型之道: 阿里巴巴中台战略思想与架构实战》钟华编著),中台的本质是提炼各个业务线的共性需求,并将这些功能打造成组件化的产品。 前台要做什么业务,需要什么资源可以直接找中台,不需要每次去改动自己的底层,而是在更丰富、灵活的“大中台”基础上获取业务能力支持,让“小前台”更加灵活敏捷,中台架构被认为是未来企业级架构的方向。
中台、DDD 以及微服务属于不同层面的内容,中台架构是一种企业级的架构模式,是从企业全局、整体视角来看的架构全貌。 DDD 是一套处理复杂业务的设计思想,里面的应用层、领域层、应用服务、领域服务和中台里很多概念一脉相承。 微服务是技术实现和部署的范畴,它是落地中台架构的技术工具。 一张图来表达他们之间的关系:
六、总结
本文通过有赞零售财务中台架构的实践,详细介绍了复杂业务系统的架构过程,首先基于整体业务架构,设计出系统的应用架构,应用架构有不同的设计粒度,可以参考 C4 模型从宏观视角到微观视角,逐步开展设计工作。 接着,基于应用架构的限界上下文的划分,可以指导我们进行微服务的拆分,通过对限界上下文复杂度的判断,确定划分为几个微服务较为合适。 最后介绍了中台、DDD 与微服务之间的关系。 通过这篇文章,希望能为开发者在架构设计上提供一些参考价值。 (附上内推邮箱: tangyi@youzan.com,欢迎加入有赞零售团队)
WEB-UI 自动化实践
有赞 Android 崩溃保护的探索及实践
Under the Hood: NaN of JS
有赞零售小票打印跨平台解决方案
-The End-
Vol.205
有赞技术团队
为 442 万商家,150 个行业,330 亿电商交易额
提供技术支持
微商城|零售|美业 | 教育
微信公众号:有赞coder 微博:@有赞技术
技术博客:tech.youzan.com
The bigger the dream,
the more important the team.