Skip to content

Latest commit

 

History

History
184 lines (103 loc) · 21.8 KB

architecture.md

File metadata and controls

184 lines (103 loc) · 21.8 KB

Nature 架构思想

在阅读之前请先阅读README,以了解一些概念和术语。

Nature 的自然观

Nature 是为了简化业务系统的建设而提出的,既要使用简单,又要能够承载复杂的业务。这其实是蛮难的,为此 Nature 借鉴了一下中国古人《易经》的智慧,《易传》有云:“易有太极,是生两仪,两仪生四象,四象生八卦”,这正好满足 Nature 的核心诉求。

之所以将本系统命名为 Nature 也是希望 Nature 像大自然一样可以简单的规则来支撑复杂的世界。

传统系统的问题

单体系统的问题

一般情况下将我们的思想转化为代码需要经过很多的步骤,如:需求调研、设计、编码、测试、部署等,只有这样代码才能“真正懂得”我们的需求,Nature 称这个漫长的过程为决策固化,同时也说明了系统是决策和执行的混合体。所以研发周期都比较长,而且经常要迭代,消耗较多的资源。

可悲的是,这个混合体参杂了太多的技术元素,技术元素对外部来讲是非常难以被感知的,只有功能实现者才知道自己真正做了什么,同时技术逻辑又是非常严密的。这样富于变化的外部需求和不善于变化的结构严密的代码之间就必然形成了尖锐的矛盾

这是传统开发方式所固有的问题,其问题的根源在于定制。标准化在纯技术领域表现的非常好,各种开源组件可以很好的说明这一点。但对于业务领域,在同质化竞争的时代,每个服务提供商都在细节上和对手比拼,这些细节的差异必然导致定制,所以基本上没有可以复用的业务系统。

多体系统的问题

当业务比较复杂时,我们一般会用多个系统来承载业务。系统大多是按业务的垂直领域进行划分的,拿电商来举例,大体上可以分为交易、库房、配送、售后、财务、用户等系统。这样的划分大多与组织机构的划分保持映射关系,具有很好的直观性,也是业界的普遍常识。然而系统规模越大系统间的协作成本越高。这是由决策的联动性造成的,尤其是核心链路上,系统的迭代会变得异常艰难

导致问题的根本原因依然是决策固化,决策的改变不可避免的或多或少的受现有系统的约束,这表现为相关系统不能同步上线,因此我们需要考虑系统平滑过渡兼容性问题,这很容易形成了难以去除的阶段性代码(程序员很善于做加法而不善于做减法),大大增加系统的复杂性。经过长期的迭代后系统就会变得臃肿难以维护,所以几百几千人的开发团队就不足为奇了。虽然我们可以通过良好的设计来规避一些问题,但对于初期快速发展的业务来讲很难预判哪个是好的设计,稍纵即逝的商机也很难让我们一开始就有一个完美的设计,所以这不太现实。

解决问题的方法

要解决这个问题,我们需要先解决需求和技术变化的匹配问题,需求层面我们是无能为力的,我们只有在技术上想办法。首先我们可以做的是打破技术结构的严密性,将模块间的直接相关性变为间接相关性,这样就可以比较容易应对业务的变化了。

接下来我们就需要一个中间人来串联这些模块,这个中间人便是 Nature,Nature 便提供了 Relation 来协调各个模块。既然有了统一的中间人,各个业务模块就需要按照统一的标准与 Nature 来进行通信。协作最重要的无非是传递数据,所以 Nature 又提供了一个 统一的数据表示形式:Meta

MetaRelation 是可输入的数据,而不是传统意义上的代码组成部分,这样 Nature 将数据和数据间的关系都提取到了系统的外部,使之原本封装到代码里的不可见的部分变成了可见的部分,使技术性的变成了非技术性的。这样业务人员对业务的控制能力将显著增强,决策固化的路径将大为缩短,同时技术人员也不需要为驾驭复杂系统而秃顶了。

MetaRelation 被称为设计时,也称之为决策数据。有了MetaRelation我们就可以对传统的业务系统做手术了,将所有的决策取出并放在一起,将剩下的放在一起,形成两个独立的集合。如果 Nature 是太极的话,那么这两个集合便是两仪。这样原先分散的决策就可以形成有机的整体:决策集中化。这对于多体系统尤其有用,不用考虑彼此的牵绊而导致的各种问题。决策被从业务系统取出后,原有的业务系统将失去灵魂!这将导致传统开发方式全面彻底的失效

规则和方法定好了必须有人来玩,Nature 称之为 ExecutorExecutor 的实质是完成 Relation 中 关联数据的转换,大多数情况下Executor必须由您来自行实现,大多数情况下是传统系统中被剥离了灵魂的剩下的“散乱”的部分,请放心这个实现已经非常简单了,它们的职责非常单一,因为复杂的业务耦合已经由 Relation 来承担了。Executor 也被称之为运行时。

Nature的设计时运行时拥有完全支配能力Meta 用于限定运行时生成什么样的instance。而 InstanceMeta 在特定时间、特定场景下生成的特定数据。MetaInstance 的关系相当于编程语言中的 ClassObjectRelation 则指定了运行时的规则,也就是说Nature 的**MetaRelation是整个业务系统的指挥中心**。

Meta, Relation, ExecutorInstance 都是抽象、简洁、规范和统一的形式,所以可以承载众多的不同业务诉求。这像不像《易经》中的四象?

Nature的时空观

上面主要以问题导向的方式来说明 Nature 是如何解决问题的。接下来我们将说明一下 Nature 的其它设计理念。

决策为执行提供了运行空间以及空间转换的规则。空间是需要支撑的,对于一个几何体来讲,其支撑物就是点、线、面;注意“面”是隐含的,点和线画完了,面自然就出来了,面出来了体也就跟着出来了。对于 Nature 来讲 Meta 就是点,代表了业务对象;Relation 就是线,代表了业务对象之间的关系。注意:Nature “明确”定义了“面”,它隐含在具有层次结构的 Meta#key里,用于表示业务领域。 所有的领域构成了完整的业务体系。这样 Nature 只需要 MetaRelation 两个元素就可以描述繁杂的业务实体,以及实体之间的关系,少了不行,多了也没必要,这就是 Nature 的空间观。

我们再来说说 Nature 的时间观,时间表示运转、秩序、不可变更的历史和演进:

  • 运转:只有运转起来的结构(空间)才能行施功能,而 Relation 则是运转的发动机!因为Relation 是标准的,用于保障运转的机制便可内建于 Nature 之中,如幂等、重试、异常处理等,这意味着普通的程序员就可以做出可靠、稳定的系统
  • 秩序:秩序必须集中制定,然后大家共同遵守。Relation 定义了 Executor 必须执行的业务规则,最重要的就是上下游 Meta。这样先后秩序就有了,也就意味着 Executor 只做好自己就可以了,使其逻辑大为简化。
  • 不可变更的历史:决策的每次变化都会用版本来记录,既表达了对历史的尊重,又可以使得未完成的业务得以继续。 Instance本身就代表着历史, 其一旦生成将永不可篡改,即便是状态数据,其每一次变更都可以进行回溯(也是基于版本号)。
  • 演进:Nature 打破了决策固化,使得决策和执行可以各自独立演进,不仅如此,Nature 让决策本身更简洁、更精确、更规范;让执行职责更单一、更轻量。这些都会让业务的演进更轻松。

Nature 运行机制的数学表达

Nature 的运行机制可以用一个数学公式来表达 :

 y=f(f(f(...f(x)...)))

其意义为:每个Relation都可以表示成y=f(x),上游Relation的输出可以作为下游Relation的输入。其中x,y都是Meta,而 f 则是ExecutorExecutor可以看做是传统意义上的接口,接口在传统开发方式中具有举足轻重的地位,是功能间协作的桥梁,但Relation将接口的重要性弱化了,这样可以有几个好处:

去功能化

传统的接口是一种功能导向的产物,功能是用来实现目标的,所以功能是现象级的,你得经过分析才知道它要干什么,甚至有时候不知道它在干什么,或者为什么这么干。Nature 是面向目标的,目标是一个点,功能是一条线,所以目标要简单明了的多。

对于一个 y=f(x) 来讲目标就是 y 而作为 Executor 的 f 只是一个功能占位符,所以我们可以简化为

x -> y

也就是 Relation, 这样 Nature 将传统系统本末倒置的功能与目标的从属关系进行了正位,使其有了“自然”的表达。有了这个表达将带来下面几个重要意义:

  • 我们可以更专注于目标,并使得目标简练,直观,可视。
  • 目标得以实现标准化并摆脱决策固化的掣肘。
  • 目标的标准化带动 Executor 的标准化。

去中心化

我们上面说过,上游Relation的输出可以作为下游Relation的输入。这是一种串行的流式处理方式,在运行时可以一个接一个的自主流转并生成相应的Instance。这期间不需要某一个或某几个点来进行任何的流程控制,也就是说系统的行为是下游自由发挥的,是不受控制的,是去中心化的。

去中心化在一个大型系统里意义是非凡的。主要体现在以下几个方面

  • 效率:去中心化,意味着减少了控制链路的长度,意味着用更短的时间更少的资源就能完成任务。意味着可以并发和水平扩展能力而不用担心挤独木桥。
  • 自适应:在确保完成任务的前提下,因为控制的去除,就有了更多实现方式的可能性,不用担心过多的管制和约束。

一对一

Relation只允许一个输入对应一个输出,既一对一,这种做法借鉴于关系数据库,除了形式简单外还有以下几方面作用。

  • 强制业务间解耦。一对多,多对一等各种复杂关系可以用一对一来表达,这样控制形式的多样性就消除了,也就容易统一了,这就为不需要编码的基于简单配置的流程设计提供了基础。
  • 高阶功能更容易达成。每个一对一都是简单的,所以我们可以快速的构建出很多的功能体,当它们通过 Nature 聚合在一起时就像《失控》中描述的蜂群、蚁群那样“涌现”出一种高阶能力。
  • 一对一可以让 Nature 更容易赋能。因为Executor形式简单、统一,我们就很容易在Executor上施加切面技术,如并发、幂等、重试等,从而大幅度降低 Executor 开发的技术复杂度,使开发者能够更好的将精力聚焦到业务本身上。

Nature 运转机制的哲学意义

这里我们讲一下控制选择的区别:控制是对他人的控制,选择是对自己的选择与他人无关。

控制

控制是实现目标所采取的手段和方法。我们的系统大多是基于控制的,代码控制一切,无论是框架、设计模式、组件都是一种控制,包括 Nature,这是编程这个行业诞生以来天经地义的一件事情。从这一点来讲系统就是一个目标和功能的聚合体,两者不可分离,这是决策固化的一个明证

控制的点越多控制起来越困难,虽然我们可以通过分层来减少控制的复杂度,但却增加了反馈路径的长度。这是大型分布式系统需要直面的艰难抉择,参与者越多,控制逻辑越复杂,直至出现瓶颈

Nature 只对规则进行控制,并不对业务本身进行控制,而且 Nature 的规则非常的简单,非常的少,这就保证了 Nature 处理的的高效性。Nature 里最重要的一个规则就是 Relation ,它是拒绝控制的,取而代之的是 Relation 要求所有的业务参与者都基于下面要介绍的选择自发组织流程。从这个层面来讲 Nature 可极大的压缩业务控制相关的开发成本。

选择

选择与控制相反,它是自下而上的,就像一条河一样,上游是无法控制下游的流向的。Relation 的形式决定了它不允许对业务流程进行控制,只允许选择。Relation不只是选择上游,他还选择Executor,这样就可以实现“功能”随意替换。

因为上游不去控制,下游也没有必要将信息反馈到上游,成为真正高效的流,这点对多级反馈尤其有意义。所以选择既提升了性能,又给了下游充分的灵活性,这对业务的扩展、调整非常的重要!

对业务迭代的影响

现在普遍倡导:“小步快跑,快速迭代,持续交付”,这是为了降低业务变化与技术僵化所带来的不确定性而采取的措施。然而要达到这个效果是有条件的,除去自动化部署、DevOps和云基础设施等外围依赖,还要看你项目群的整体结构是否已经稳定。也就是说这种持续交付一般局限于小范围的调整,要想实现跨系统的快速迭代还是比较困难的,但这却是我们最迫切需要的的!

这是由控制的局限性导致的:控制要求掌控所有的参与者。当我们需要改变一些东西的时候,控制端必须审视和调整所以相关的参与者。对于一个个体而言,要想对其控制,必须对其所控制的资源进行某种形式的占有,控制的能力和范围与资源占有程度是紧密相关的。而占有是具有侵入性的,而侵入是有成本的,这对大型分布式系统来讲是非常不利的。

这里举一个支付和发货的例子:当支付状态为“已支付”则生成出库申请单,如果没有支付完成则不动作。通常情况下我们会在支付逻辑里使用if控制语句,这就是控制!现在我们要做业务调整:将发货的依赖由支付系统改为订单系统。这样支付系统和订单系统的逻辑都要修改;另外还需要考虑两个系统的平滑过渡问题,这个可是个高风险,高耗时,且具有副作用的高难度操作。所以你可以看到虽然是一个小小的决策改变,控制所带来的代价有多高!

我们再来看看选择,Nature 用选择引导流程而不是控制流程,所以流程控制里没有if。就上面的例子来讲,支付完成不主动触发任何动作,而是下游生成出库申请单时触发的,你只需要定义一个“支付状态=已支付->出库申请单”的 Relation 就可以了。当决策变为订单状态驱动时,我们只需将 Relation 改为:“订单状态=已支付->出库申请单”及修改对应的 Executor 即可。由此可以看出选择可以做到按需修改,这是控制所难以企及的。

Nature 是适合快速迭代的,它不存在系统间的边界墙问题,这是 Nature 的选择特性所赋予的。选择只要对方存在就可以,不需要侵入,所以不需要额外的成本,既选择比控制对环境的要求要低很多。同时因为没有控制,你不会遇到复杂的逻辑问题,诸如分支、循环、跳转等;因为没有控制,系统的演进成本将会非常低廉,业务模块间的链路能方便的重组并容易找到最优路径;因为没有控制,各种各样的业务模块可以自由的试错和扩展,以灵活的方式去匹配业务发展的需要。

生态与法则

在一个生态系统里没有一个至高无上的主可以控制所有的一切,每一个物种都在选择中适应,这样才有了生物的生机勃勃,这正是目前传统系统所欠缺的。传统系统之所以死气沉沉,低效,就是因为自上而下的控制,类似于公司业务的层层汇报、层层审批,当控制的链路非常长非常广时,由控制导致的内耗将十分突出

虽然 Nature 不强调控制,但 Nature 用什么来维持秩序呢?那就是法则。没有控制并不代表着没有法则,控制有着明确的目的性,而法则没有目的性。地球之所以围绕太阳转,不是太阳有意控制地球,而是万有引力法则在发挥作用。自然界的生态系统也是一样的,春夏秋冬、寒暑易节、昼夜轮回维系着自然生态的平衡。Nature 的法则就是选择,就是 Relation,Nature 所有的代码几乎都是围绕着这一法则来组织的。

选择所实现的无形控制

Demo 中 涉及到网购和统计相关的示例,这些示例说明了 Nature 如何简化这些业务的实现。在这里不做具体展开,这里只想说明一下选择机制如何有效支撑系统的运行秩序。为了简单起见,所表达的内容可能与Demo中的不完全一致,还请谅解。

上文中我们说到选择是下游对上游的选择,这就揭示了一种思考方式:逆向思维,既我们要达到目的需要什么。拿网购来讲,需要从流程的终点来倒推。用户若想拿到商品需要配送员送,交接数据为签收单,于是我们定义第一个Meta。然后我们再倒推,配送员需要和库房交接出库单才能拿到商品进行配送,出库单是我们的第二个Meta于是我们有了第一个Relation : 出库单->签收单。

以此类推我们可以定义出类似于下面的Relation

出库单->签收单
订单->出库单

这里有个很重要的点需要说一下,从出库单到签收单如何调度的,是自己公司配送还是第三方配送这里并不关心,RelationExecutor想用哪个就用哪个。既Relation只关心结果,并不关心如何做。当然如果您有自己的物流团队,并想跟踪物流状态,可以从出库单建一个分支目标就可以了。下面会讲到分支。

这样一个简单但完整的设计时便出来了。而这个设计不用写代码就实现了对运行时的控制。

出库单->签收单 在设计时是一对一的关系,在运行时产出的Instance也是一对一的,既一张真实的出库单会对应一张真实的签收单。这在 Nature 里是最为常规的控制。其它控制方式都是由这种常规方式支撑的,如接下来要讲的分流。

设计时的分流的形式是不同的下游拥有同样的上游,就像河流分叉一样。如上面的出库单还可以驱动库存状态,Relation 如下:

出库单->签收单
出库单->库存状态

在此种情形下,出库单不需要知道有多少个下游,但Nature 会知道,因此Nature 需要在幕后分别执行每个RelationExecutor

注意这里的“出库单->库存状态”,这个在设计时是一对一的,但在运行时却有可能是多对一的。举例说明一下,假设在运行时我们有两个出库单,出库单A包括2个手机,出库单B包括3个手机,但却只能有一个手机的库存状态,所以在这个示例里就有了两个出库单实例分别对应同一个库存状态的不同版本的实例数据。(有关状态数据及状态的并发控制请看 Nature 技术特性

那么有没有运行时是一对多的呢?这里有个例子:订单->支付单。这在设计时是一对一的,但在运行时是可以一对多的。假设用户第一张卡里的钱不够支付订单,这时候就会有多次支付的情形存在了,既一个订单实例对应多笔支付实例。

那么在设计时有没有多对一的情形呢?答案是有的,Relation定义如下:

出库单->库存状态
入库单->库存状态

现在我们来看,设计时的一对多、多对一,运行时的一对多,多对一,可以随意搭配组合,这就在理论层面形成了完整的闭环。这样Relation就可以支撑非常复杂的业务。但对于使用者来讲基本上不用关心流程控制问题,使用者只需要做出合理的选择,大自然(Nature)便会在法则(Relation)下无形中操控一切。

标准化

Nature 打破了面向功能的传统开发模式,其简化的形式在降低成本的同时也为我们带来了标准化的可能:

其中之一是决策的标准化,传统方式下决策固化使得决策十分个性,只有定制的系统才能表达。而 Nature 的决策是标准化的数据,我们只需配置,无需编码便可被执行系统理解。然而 Nature 并不局限于形式的标准化,它更大的意义决策行为的标准化,相对于传统方式 Nature 可以大幅度减少执行层面的考虑,直面决策的最终产物——数据。

其二就是执行标准化,因为业务间的耦合被斩断,各个业务执行单元就非常的独立,这些执行单元统一由 Nature 来调度,这必然统一了接口形式,自然就标准化了。

其三是数据规范和纯化。传统模式下,我们可能有数十上百个数据库成百上千的数据表,这些数据表是临时数据、业务定义,业务控制、技术数据、业务数据等的大杂烩。但 Nature 只有三个数据表与业务相关:Meta 用于业务定义, Relation 用于业务控制,Instance用于业务数据。这会很大程度上减少不必要的数据存储,减少数据的冗余,当然我们可能需要一个大型的分布式数据库,如 Tidb