写点什么

架构误区系列 11:无聊的架构归一

作者:agnostic
  • 2023-01-21
    上海
  • 本文字数:3165 字

    阅读完需:约 10 分钟

本期的架构误区系列说一个大一点的话题,是首席架构和 CTO 层面需要关心的话题。在大厂的同学可能会时不时被迫加入各种架构归一的运动中,对现有的架构进行所谓的“治理”。讲道理,这种所谓的运动式口号式的架构归一真的有作用么?正确的架构治理应该怎么做呢?


首先,我们分析一下是不是应该有所谓归一的架构。

从静态的看,同样一类的问题,解决思路的不同,以及问题细分方向的不同,会带来不同的架构设计。比如同样都是消息中间件,我们是关注吞吐量,还是关注发送和接收的可靠性,或者需要一些优先级、定时消息等额外的特性,这些都会让我们的消息中间件架构的设计或选型有所区别。比如在应用架构上,同样都是一个用户管理的模块,支付平台的用户管理、电商平台的用户管理、或者内部系统的用户管理,架构设计的侧重点都会有差异:支付平台的用户管理重点可能在用户的信息真实性的验证;电商平台的用户管理可能更需要对用户特性的分析和用户画像;内部系统的用户管理更关注的是和 HR 等系统的数据同步和自动化能力。所以,在架构上我们会不断的重新设计,也就是会重复重复造轮子,来应对不同的业务问题。对于不同问题方向进行的重复造轮子,或者造一个更优秀的架构,这个是合理的。

从动态来看,我们的架构是要解决实际的问题的。而实际的问题不会是一成不变的,随着历史的发展,我们需要解决的问题会有一定的变换。所以,映射到架构设计,也需要随着问题的变化进行相应的进化。比如,随着团队的变大,我们可能需要对一个应用进行垂直的拆分。随着业务量的增大,我们需要引入适合高并发的架构设计,比如数据库分片,比如异步化(消息队列)。随着合规环境的变化,我们需要对数据进行隔离,需要对数据的对外露出引入流程和权限管控,甚至我们可能需要对交互链路进行重新设计满足合规本地化的诉求。

还是从动态看,我们架构面临的技术生态也在不停的变化。不停的有新的技术产生,旧的技术被淘汰。由于生态的影响,我们也需要对我们的架构进行不停的重构。 比如云计算的出现,基础设计会从裸金属框架转变为云和容器,我们需要去适应这个生态,去适应云原生,去适应 serverless,在架构设计上,可能需要对数据存储和计算进行分离去适应 serverless,需要对应用架构进行调整从而适应云环境。同时,比如流程引擎的出现,我们在内部系统中大量的流畅审批类的功能往往需要去适应,去引入和适配流程引擎,从而在架构上带来更强的稳定性、更大的灵活性和更好的用户体验。

总之,从静态看,我们需要差异化的架构来解决不同细分方向的问题;从动态看,由于业务诉求和技术生态的持续变化,架构必然会随之进行不断的调整,调整就意味着不同架构版本之间的迭代和并存。

另外,从进化论的观点,通过行政命令强行将现有的架构往一个由人选出来的统一架构上去归一,就好比在不同的变异个体之间用人为的方式而不是自然选择的方式去进行评判,这个结果可想而知是灾难性的。


所以,事实已经证明了并不存在绝对统一的架构,同时用人为的方式强行做架构归一是一个不可取的方式。那么我们对于架构治理到底应该遵循怎样的原则呢?

要回答这个问题,首先我们需要知道架构治理要解决的问题,也就是我们日常所遇到的架构上的痛点。

这里我们不讨论和能力相关的问题,也不讨论中间件相关的问题,重点聚焦在应用架构部分。应用架构最常见,大家也最熟悉,同时也最不成熟、痛点最多。

首先,我们应该明白,根据康威定律,一个应用系统的架构其实就是这个系统背后团队关系的映射。我们做架构,其实就是在做子系统之间职责的划分和协作关系的确定,同时也是明确团队之间的职责分工和沟通协作关系。

通过模块化和分层的方式,将一个大的问题域拆分成不同的子域,并确定各个子域之间的职责和边界。如果大家的职责不清晰,往往会造成各个子域团队之间的相互踩脚,影响效率的同时,也影响交付产物的质量。

同时,子域之间有分工同时也会有协作,如果子域之间的协作不好,同样会影响交付的效率和质量。子域之间的协作,归根到底是子系统之间的契约所决定的,落到文字和架构上的契约清晰与否,直接决定了两个子域团队之间沟通的顺畅程度。

有了这个分析,结合日常的开发经验,我们可以很清楚的知道,在应用架构上,最大的痛点是不清晰,包括子系统边界的不清晰、子系统之间的沟通协作契约的不明确。这个通过一些日常架构工作中的例子大家就比较有体感:

  • 一个业务方案,不清楚是应该走 A-B-C-D 的链路,还是走 A-B-D 跳过 C,或者走 A-E-D 用 E 替换 B-C。

  • 每一个需求,都需要引入中台的同学进行分析,来确定是否可以复用现有能力,还是需要修改甚至新建能力。

  • 一个功能,两个相邻的子域经常会打架,每次都需要域架构师来决定这个功能放在哪个域,搞不好还要总架构师来拉架。

  • 各子域配合实现一个业务诉求,往往有那么一两个子域改造量特别大,成为项目的瓶颈。

  • 下游域总是抱怨上游域需求老变,每次在过程中总是改需求;上游域又一直抱怨下游域能力太弱,这个不支持那个要改造。


那么,要解决这个架构不清晰的问题,我们要做什么样的工作呢?目标其实很明确,既然痛点在不清晰,那么我们只要想办法让架构清晰起来就可以了。

我们上面分析了,架构不清晰主要体现在边界的不清晰和契约的不清晰。

一个子域的边界,说白了就是这个子域能力的覆盖范围。要让边界清晰,首先就需要将各域的能力说清楚。能力在系统上的体现无非就是服务,就是要说清楚一个域提供的服务在功能性和非功能性上的范围,包括能做什么不能做什么,TPS、RT 分别多大,可用率是多少,应急的 SOP 是什么。一个域服务的职能范围,往往也和会这个域的关键领域模型有联系。所以,要明确一个子域的能力边界,就是要说清楚这个子域的领域模型和服务模型。

服务模型,其实就是服务契约。如果知道了能提供什么服务,不能提供什么服务,那契约是否就清楚了,双方的沟通是不是就没有问题了?其实不然,在传统的架构中,契约往往指的是服务端契约,就是服务提供方在自己的视角,说清楚服务中每个字段的含义。服务使用方往往看不懂这个契约,因为双方的语言很有可能是有 gap 的。所以,要做到清晰的沟通,定义明确的契约,就需要引入消费方驱动型契约的概念。不是消费方来定义契约,契约的定义方还是服务提供者。但是,服务提供者要从消费方的角度来对契约进行明确。也就是服务提供方要明确契约的使用场景,并体现在字段的定义上。消费方可以通过这份契约很清楚的知道服务提供的能力对应到自己的需求的适配程度。具体可以参见 Martin Fowler 的文章:《Consumer-Driven Contracts: A Service Evolution Pattern》

总结一下,要解决架构不清晰的问题,我们要在三个方面进行提升:

  1. 明确定义子域的领域模型。

  2. 在清晰的领域模型的基础上,明确定义本域提供的服务能力,包括功能性和非功能性两方面。

  3. 对于反映服务能力的服务契约,需要引入客户端驱动契约的方式,将契约的场景明确清楚。


在做到这三点的基础上,我们采用分层和自然选择的方式对架构进行演进。

首先,各域特别是下层的域将自己的能力通过领域模型、服务契约对外进行暴露。上层根据自身业务需求对不同的能力进行选择:复用、驱动下游升级或者直接外采或自建。上游对于下游有选择权。

同时,如果下游定义的服务和产品有竞争力,那复用比例会相对较大;或者上游提出的升级需求能很快的满足,下游的服务能力会不断进化适应业务的发展。这就是优胜。如果下游提供的能力和业务需求没啥适配度,或者下游能力升级老费劲了,上游选择外采或自建的比例就会加大。这个就是劣汰。上游自建通俗的说就是重复造轮子如果搞的好,也可以拆分成一个域来替代被淘汰的子域。这个就是进化。

通过这个自然选择机制,会动态的形成架构螺旋式的演进,逐步沉淀具有竞争力的架构。


所以,没有所谓的架构归一,更不存在行政命令驱动的运动式归一。我们更需要的是清晰的架构边界和契约的定义,以及架构上的自然选择机制。


发布于: 刚刚阅读数: 2
用户头像

agnostic

关注

常识、KISS、高可用、合规架构、架构治理 2019-02-14 加入

二十年架构经验,互联网金融专业架构师。Open Group Master Certified Architect

评论

发布
暂无评论
架构误区系列11:无聊的架构归一_架构治理_agnostic_InfoQ写作社区