Skip to content

6.3 系统垂直划分

服务划分的目的是垂直分解复杂性,垂直是指在某一层内的垂直。也就是说,在不同层垂直划分的粒度可能并不相同。

垂直分层

图片来源:https://www.eecs.yorku.ca/course_archive/2010-11/F/3213/CSE3213_03_LayeredArchitecture_F2010.pdf

在很多系统的垂直划分时最大的误区是穿透了分层,想象一下我们有一套自己的通讯协议,这套通讯设备同时具备了应用层、网络层、传输层、数据链路层,那么这套通讯协议就很难被归纳到 TCP/IP 协议簇中了。

垂直划分的权责问题

实际上水平分层比垂直分层要简单很多,因为我们很容易根据工作的性质识别到他们边界。比如,网关、业务服务、数据库中间件,很容易就知道他们的分层关系。

我们怎么找到垂直划分的边界呢?

技术类的垂直划分实际上比较简单的,比如接入层,我如果有两种物联网设备接入协议,我们很容易将其根据协议类型划分开。这是因为计算机科学家在这些领域有充分的解决方案。

但是业务服务的垂直划分就非常麻烦了,特别是没有经历过沉淀的创新类软件系统。以企业通讯软件为例,企业通讯录、群组、用户这几个概念若即若离,无论是划分开、还是合并到一起都会有不少的麻烦,有时候甚至没有完美(或者有些架构师称作干净)的解决方案。

我们会发现,垂直划分和水平划分的特点可以被归纳出来,这便于我们对系统进行设计。

特点例子
水平划分性质具有明显的不同领域层、网关
垂直划分性质类似但是职责范围不同用户服务、会议服务

下面这张图为互联网收银系统的分层架构,水平的方向使用了同样的背景色,他们的性质基本类似。假设这个系统是非常理想的方式设计,接入层为不同的网络接入方式,它取决于应用场景,它的垂直划分非常容易。

但是对于应用层来说,如何清晰地界定那些属于应用,需要对产品设计有非常深刻的理解,以及和产品经理达成共识。对于领域层来说,如何找出相对独立的能力单元也不是那么容易(当我们把领域逻辑和应用逻辑分开后,领域层的垂直划分相对简单一些)。

完整示例

那么对于业务相关的服务来说,我们有什么线索可以进行垂直划分吗?对于应用层的服务来说,我们可以以使用该应用的业务主体来划分。比如在餐饮系统中,我们可能会有下面几个主体使用该系统:终端用户(店员)、商户、系统管理员、第三方 API调用者,在应用和服务分离部分我们已经详细讨论过这类问题,应用层的划分比较容易。

那么领域层呢?领域层的微服务之间大部分情况下是平等的。由于领域服务和系统状态(有自己的数据库)相关性比较强,这些状态可以通过模型(实体)来表达。这也是为什么我们通常说的微服务划分,实际上是说的领域微服务,它们的划分和上下文划分可以意义对应。所以领域服务的划分,是根据系统所处理的客体来划分的(这是为什么我们划分领域服务需要先找模型,因为模型一般是作为客体出现),这是一个比较好的线索。

这里总结下应用层和领域层的划分线索的区别,以及辨析权责关系:

划分线索权责职责
应用层参考业务主体为线索来划分访问领域层、基础设施层的服务能力,无权修改系统状态的编排领域层,为业务主体提供个性场景
领域层参考业务客体(领域模型)的分类来划分修改系统状态的能力,无权干涉应用场景提供上下文内对系统状态的管理职责

当权责关系被定义清楚后,开发团队在开发时能减少沟通的成本,但是并不意味着应用层和领域层的鸿沟可以忽略。对于规模非常大的系统来说,让领域层持有所有的系统状态会变得过重,也可以考虑让应用层持有一些局部的领域逻辑。

比如在餐饮系统中,收银机应用中可能会有一些临时数据,这些数据不需要被运营管理后台和商户后台所管理,为了灵活性考虑增加局部的状态,承载方式可以是数据库或者 Redis 等。

架构是供需关系

垂直方向的划分,供需关系也是一个非常重要的线索。

在几年前,我经历了一次红蓝项目。所谓红蓝项目就是类似于军事演习中,为了训练自己的军队,虚拟了一个敌人,通过给虚拟的敌人配置不同的火力来检验自己的战斗力。

但是红蓝的软件项目有点不同,软件项目的红蓝是指业务方提出了需求,不同的研发团队都接了这个任务,最后由公司的高层评估哪一个团队研发的成果更能胜出。往往残酷的是,输掉的团队会被解散到其他团队中,甚至整体裁掉。

当然,实际工作中这种情况发生的更加隐晦。一个公司的研发团队不仅仅面临着其他研发团队的竞争,实际上还有市面上成熟的产品、外包团队等外部的竞争对手。

对于架构师来说,不得不认清的一个现实是,软件开发是一个供需关系,无论发生在公司内部还是外部。供需关系的双方不仅仅局限在研发团队和业务团队两个主体之间,还发生在研发团队和另一个研发团队之间。

当一个服务的 API 频繁被其他团队需要时,这个团队就自然的不会过多的参与终端业务开发了,而是忙着给其他的研发团队提供通用能力。如果公司内部具有 API 调用结算机制,或者提供能力给内部团队也算作一种考核,供需关系就变得更加清晰起来。

这是因为当系统变得极其巨大的时候,系统不再是规划出来的了,是根据供需关系生长出来的,这种效应在越大的公司越明显。这会给我们一个错觉,大型公司感觉非常不专业,时时刻刻都在做无用工,每年规划了几十、上百个系统,然后存活下来的寥寥无几。

反而是创业公司看起来更稳,细致的规划,灵活的调整,而不是像大公司这样大动干戈。于是很多架构师和程序员会有一个疑问,为什么公司不进行细致的规划呢?

如果一线的程序员多和 CTO、架构师们聊聊天的话,会发现一个事实,CTO 们也不是三头六臂将所有事情都规划的妥妥帖帖,因为系统的复杂性必然会超出人的宏观规划能力。

成功的企业解决这些问题背后的方法极其简单粗暴——试错。架构的一切出发点是有业务需求,而且这些业务需求是真实的"生意"才行,当业务部门愿意拿出预算进行研发时,供需关系就产生了。

在一个公司整体的层面上,CTO 更像是一个裁判,他需要有敏锐的眼光找到最适合的人来承接,以及宏观上需要什么,而不是规划、指导怎么研发。对大厂来说,浪费不过是计划之内的事情,这样看来重复建设是为了自然选择。

CTO 别无选择。架构设计,其实也是一种对业务的抽象,如果业务始终在变化,用一套"灵活"的框架满足"无限"变化,是一件不可能的事情,唯一的方法就是淘汰。

Released under the MIT License.