Post

架构设计

本文的主要内容来自温昱的著作一线架构师实践指南中的一些论点,加上自己的一些感受

架构的评判

一流的架构是每个程序设计人员为之奋斗而无法具体说出难以达到的境界,因为这本就是一个即主观又非常客观的论断。主观是指在特定的每一个人对待架构完善程度的判断标准不一,而标准的不同就会带来判断上的区别;而客观又是一流的软件或者架构之间又存在非常多的共性特点,我们可以给一流的架构做出这样的定义:简明、灵活而清晰,能够通过创造性的机制解决复杂的问题,这些机制语义丰富,可应用于其他可能完全无关的问题,一流意味着恰当的抽象,意味着通过新的途径,合理利用有限的资源。

概念架构

概念架构是对系统设计的最初构想,不同产品之间的架构差异,其实在概念架构阶段就已经不同了。不同于售前/评估阶段,要在短时间展现用户关心的价值、解决其关心的问题。概念设计的决定性因素是关键需求,一般关键需求可能会有这几个维度:

  • 业务需求:业务目标(系统要达到什么样的目标),工期要求,执行标准
  • 用户级需求:系统辅助完成那些工作,使用方式和质量上的要求(易用性、鲁棒性)
  • 开发级别需求:开发/维护时的质量考虑
  • 非功能性需求:开发效率,性能,安全性和可扩展性

架构的设计要统筹上面各个维度的要求,从业务背景(需求结构化、分析约束影响)、系统规模(分析成本通入)、技术趋势(分析未来发展)、开发团队现状(重要的约束条件),整理出核心需求(业务目标)必做需求(项目愿景)高风险需求(特色差异化竞争)特殊需求,从核心需求推导出概念架构,而其余部分用于验证关键需求推导出来的概念架构设计。

因此,架构设计的核心就是需求的捕获,这个过程是获取知识的过程,从无到有,从少到多,需求采集必须理解用户从事的工作,并了解用户和客户希望软件系统在哪些方面帮助他们,在挖掘和整理知识之上,也需要对捕获到的内容进行系统化和条理化的加工,因为用户提出的需求往往比较分散,特别是在用户无法做到精准细分的场景下,整理和分析出用户的核心关注往往需要通过需求对比来完成。

系统分析,则是进一步提出解决问题的方法,与可行的逻辑方案以满足系统的需求实现预期的目标。其本质就是抽象。而在细化架构中则需要更多关注具体的拆分和逻辑。

概念架构阶段,需要核心关注得就是各种需求,需求来源于业务或者战略发展,找到 Owner ,明确不同维度得需求,是首先要做得事情。架构师在心中要首先明确需求,这个是前提。

分而治之

Divide-and-conquer is usually the best approach for achieving any scalability goal

SOA近年来已经成为企业内部系统构建一个绕不开的话题,关于它的讨论在也非常多,在我看来,整个SOA化的过程,也是社会分工的一个缩影。如果将系统流程比喻做汽车的制造,最初的汽车模型可能很简单,在一个工厂内部就可以完成所有的部件生产和组装工作,甚至可能一个工人即负责部件的生产又同时负责整车的组装,整个管理流程和生产效率都是最高的。但是随着汽车功能越来越多,所需要的部件的生产要求和组装的工序越来越复杂,这个时候如果还是在一个工厂内部完成全部的流程,可能就会遇到如下几种情况:

  • 单一的工人很难掌握所有的工作技能,而身兼数职的人在整个工厂内部几乎完全不可替代,而频繁切换岗位导致其长期处于“工作”-“停顿”-“工作”的切换状态,大量的“停顿”带来整个生产效率的下降
  • 流水线上的作业流程可能会因为某一步骤的堵塞而导致整个工作流程无法进行,而定位和恢复故障需要耗费大量的时间,而这整个过程是无法进行任何生产的
  • 某一个工序改进的时候,可能会导致整个生产线必须全部停工
  • 当发现某一种组装方式成本更低,但是无法和现有的流程兼容的时候,在不改变现有流程的条件下无法进行升级

上面的这些问题,对应到软件系统中分别为

  • 系统规模不断扩大,没有人能掌握所有的逻辑,导致业务承接的断层;
  • 局部的系统故障可能导致关联影响,故障升级导致整个系统无法正常工作;
  • 局部的系统调整,需要整个工程重新进行发布,虽然Hot Deploy技术能够部分解决这个问题,但实际上采用的并不多;
  • 在既有的项目中引入新的技术,会遇到更多的困难

现代管理理论提出的解决方法就是分工

  • 在流水线上每一个工人只负责自己特定的工作,并针对性对其进行训练,使其可以专注在自己的工作领域,代表是是管理学之父泰勒的科学管理强调将每一个劳动过程进行分解和原子化,分离管理和执行职能,并不断优化。
  • 供应商的引入,确定零部件的生产标准,引入多个符合条件的供应商,将产能分散达到抵抗潜在风险的目的。各个供应商在实际上成都生产线中的一个环节的备份,当一个供应商出现产能故障的时候,可以有效减少其带来的影响。
  • 全球化,选择在不同的国家设立不同的分公司或者研究院进行不同的或者针对特定市场的产品设计和研发,最大每个地区的不同竞争优势

以此对应的,有一定规模的企业,在进行内部系统划分和构建的时候,都会按照服务或者功能对业务流程进行边界划分,从而形成一个个规模较小的子系统,子系统和子系统之间通过直接调用或者消息中间件实现通信。在单个子系统中,我们则更倾向设计能够自治的系统autonomous systems,在保持接口稳定的前提下,每一个系统能够独立演进迭代,在需求变化频繁的场景下能够做到更快速地响应需求,而独立出来的服务也通过对外接口或者数据规约为整个架构体系内的其他系统或者外部系统提供统一的服务。

无论对SOA的概念做出如何解释,分而治之始终是其最核心的一点。实施SOA的两个难点,一个在于管理/逻辑上如何进行系统的切分也就是系统边界的划分;一个是技术上如何构建自治的系统,保证子系统之间能够协同工作,并在分布式的系统带来的管理和维护代价上取得平衡。

如何切分子系统(模块),以及子系统之间的协作流程就是细化架构的主要责任,也是实施SOA系统的关键。

在进行软件细化架构设计的时候,大部分会优先考虑如何进行开发的问题,如果是使用水平优先的方式,那么我们需要预先把所有的功能都进行定义,然后再逐步铺开进行开发;如果为了能够更好地利用交互,及时得到用户的反馈,那么我们会选择垂直优先的这种方式,采用垂直优先策略我们需要把垂直相关的系统功能跟架构支持先定义好,保证可以在这个基础上实现一个较小但是完整的系统功能。

因此在常见的分层,架构之上,我们还会构建出对应的分区规则。分区构建在分层之内,其粒度比分层更小。一般一个具体的垂直功能只跟一个分层中具体的某一个分区有关系。垂直划分的模式更接近目前比较流行的微服务的概念,通过将开发团队和团队目标分割成为彼此较为独立的服务,便于快速迭代和敏捷开发。定义好分层跟分区试点进行迭代开发的关键。

解耦和分离

如何通过关注点分离来达到系统中的一部分发生了改变,不会影响其他部分的目标?

首先可以通过职责划分来分离关注点,面向对象设计的关键所在就是职责的识别和分配,每个功能的完成都是通过一系列职责组成的协作链条完成的,当不同职责被合理分离之后,为了实现新的功能,只需构建新的协作链条,而需求变更也往往只会影响到少数职责的定义和实现。

其次,可以利用软件系统各部分的通用性不同,进行关注点分离,不同的通用程度意味着变化的可能性不同,将通用性不同的部分分离,有利于通用部分的重用,也便于对专用部分修改。

为什么要进行模块的划分,其实是为了解决更复杂的问题。分是手段,和是目的,不能合在一起,支持更高层次功能的模块,又有何用呢。

架构的设计又是不断迭代的一个过程,罗马不是一天建成的,需求,对架构的驱动作用是伴随的架构师不断设计中间成果,不断质疑中间成果,不断调整完善,细化中间成果的过程逐渐展开的。

先考虑结构功能的划分手段,是上面所用分成的细化分区的引入机制的提取,然后让切分出的职责协作起来,验证能够完成功能,这个工作可以借助时序图图完成。

此时,结构和行为各方面进行一定的设计,就应该开始质疑自己的设计

架构师要从两个角度

  • 质疑功能方面,特殊的功能能支持吗?
  • 质量方面,耦合性重用性,性能等怎么样?

通过这种不断迭代更新的过程,将设计不断的深入。

逻辑架构的设计应该使用,结构设计和行为设计相分离。使用灰盒包图,关注核心系统中的关键类。从而更明白地说明子系统之间的协作关系。

architecture

架构的权衡

除去逻辑架构上面的设计,物理架构主要围绕物理节点,网络,软件单元,数据单元等进行,需要同时艰苦高性能,次序可用,可伸缩以及经济性和技术可实现性等,实际上架构的决策都取决于平衡的选择。

从思维要点层面,开销与争用是核心,正是通过降低开销避免争用来实现高性能高伸缩性的目标。

如何进行开发与架构设计的权衡,在架构设计中重视开发框架视图,让开发人员看到他关心的,程序单元源代码,目录结构等概念。架构设计不可高来高去,能支持并行的详细设计,是架构设计进行到什么程度的标志。

避免高来高去,应该更多地给出对关键功能细化的指导设计,而非给出没有判断标准的定性描述,这种信息的传递是无效的。程序员应该参与到架构的设计中,不可以将高层次的概念架构等同于开发架构,而应该逐步细化到可以执行并行开发。做到高屋建瓴。

This post is licensed under CC BY 4.0 by the author.