演进式架构

适应度函数

全系统适应度函数与单一适应度函数

适应度函数是一种限制模型。它决定了架构应该拥有或者不应该拥有哪些能力

架构的演进是需要加以限制的演进 否则就变成了无序生长

分类

原子与整体

原子用来验证某一维度 整体用来验证多个维度甚至于整个系统

触发式与持续式

触发式基于某些事件来验证 持续式则如名字那样 使用监控驱动开发(MDD)来监控生产系统指标从而评估系统的健康程度

静态与动态

静态函数得到的值是固定的 动态的则是会依据上下文在一定区间内浮动

自动与手动

处于技术或者非技术原因 某些验证无法自动化

维度

审查

及时审视 确定是否需要新函数、现有的函数会不会过大、是否有更好的方法验证与测量

增量变更

在部署流水线中的适应度函数

在部署流水线中的适应度函数

通过在部署流水线中加的函数 不仅能客观量化结果 也有一致的执行机制

假设驱动开发

架构模式与演进能力

架构模块间的耦合越小 演进能力越强

数据演进

演进式数据库设计

数据库模式变更应无法撤销 取而代之使用的是复式记账 使用新操作来回退旧操作

渐进式变更:

数据库扩展收缩模式

用户ID, 全名 -- 开始状态↓用户ID, 全名, 名, 姓 -- 过渡状态↓用户ID, 名, 姓 -- 结束状态

数据耦合

随着现实世界的演进 若不对数据库模式做出变更 那现有的数据会与过去的仍存在耦合

架构迁移

拆分

定义新的服务边界,根据:

对于共享的模块,在微服务中通过复制代码来进行共享

模式

DDD

  1. 气泡上下文:用防腐层(Anticorruption Layer)隔离开的一个小的限界上下文,遇到一个新的需求时,可以评估这个需求,将它放到气泡上下文中
  2. 自治气泡:有自己的数据库,与遗留系统是弱耦合的,通过数据同步,无论是定时任务、事件拦截、还是CDC,重要的是隔离

构建演进式架构

不可变

可变会使系统变得脆弱

决策可逆

意识到未知

软件总会一直变化 将演进能力贯彻到软件的整个生命周期里

防腐

构建接口来隔离无法受控的第三方接口的变化

可牺牲

随着准备推倒系统重建

依赖管理

陷阱与反模式

围绕某一具体平台技术

抽象泄漏

低代码/4GL

这类工具注定无法完成过于定制化的需求

滥用复用

复用是有代价的 复用性越高 易用性越低

为新而新

组织架构跟软件架构不一致

发布过慢

产品定制

报表

看的太远

遗留系统现代化

遗留系统: 仍在使用过时技术但至关重要的系统

现代化的价值:

  1. 数据资产
  2. 蕴含的丰富业务知识

遗留系统的认知负载:

遗留系统改造的难点:

遗留系统的增量演进:

  1. 代码增量:先把代码复制出来一份,在复制的代码处进行重构。等重构完毕,再通过某种开关,来控制新旧代码的切换
  2. 架构增量:架构演进

四个现代化

  1. 代码现代化:[重构](/软件工程/软件设计/代码质量/代码重构.html)提升代码质量,增强可测试性,为了对遗留系统进行测试,要在不修改其代码的情况下进行测试,此时可以通过代码的接缝来进行测试:可以被修改的状态、可以操控的行为、以及代码模块本身暴露的接口,通过对这些对象操控来进行测试验证
  2. 架构现代化:进行更合理的规划,清晰明确各模块组件职责及边界
  3. DevOps现代化:自动化手段降低开发运维成本
  4. 团队结构现代化:更合理的团队结构使得演进更容易

策略

  1. 退休:评估完工作量、使用情况和业务价值之后,选择完全停止使用的一种策略
  2. 维持原样:对于尚可满足使用的遗留系统,保持系统当前的状态不做任何修改或更新
  3. 封装:将遗留系统中的数据或者功能封装成 API,供外部调用
  4. 替换运行平台:只需要对代码做少量更改,以适配新的平台。这样,只通过较小的成本就可以降低基础设施的成本,并提高性能
  5. 基础设施迁移:完全不需要修改代码,而只需要迁移部署的环境
  6. 重构:不改变系统外部行为的前提下,对代码或架构进行调整、优化,以偿还拖欠已久的技术债务、改善非功能需求、提升系统健康度。
  7. 重写:对应用程序的某个组件或某个服务的重新设计或重写或彻底淘汰应用程序的所有组件,去构建或购买新的软件

持续集成

遗留系统加入持续集成流水线,由于历史原因,没有单元测试,在现代化早期可以裁剪掉单元测试,只要初步引入工具链,简单的静态代码扫描,就是一种进步

服务架构演进

Unix的分布式设计哲学保持接口与实现的简单性,比系统的任何其他属性,包括准确性、一致性和完整性,都来得更加重要。

传统架构 -> 分布式架构 -> SOA(Service-Oriented Architecture)架构 -> 微服务架构

原始分布式时代

上世纪7 80年代 当时计算机硬件局促的运算处理能力,已直接妨碍到了在单台计算机上信息系统软件能够达到的最大规模。为突破硬件算力的限制,各个高校、研究机构、软硬件厂商开始分头探索,寻找使用多台计算机共同协作来支撑同一套软件系统运行的可行方案

这个时代提出了RPC的雏形以及日后分布式文系统的最早实现AFS

“调用远程方法”与“调用本地方法”尽管只是两字之差,但若要同时兼顾到简单、透明、性能、正确、鲁棒、一致的话,两者的复杂度就完全不可同日而语

某个功能能够进行分布式,并不意味着它就应该进行分布式,强行追求透明的分布式操作,只会自寻苦果

这个时间段过后的一端时间 摩尔定律的黄金时代 计算机的算力不断提升 在日后的一端时间 单体软件架构还是主流

单体系统时代

在微服务盛行的这段日子 单体系统好像总是以反派身份登场 但对于小型系统 不论是开发 测试 部署,单体系统都有着不可比拟的优越性

乍一看单体架构的缺点似乎会是不可拆分 难以扩展 无法继续支撑越来越大的软件规模

但几乎所有的单体系统都会进行分层拆分:

分层架构

单体系统的缺陷在于拆分之后的隔离与自治能力上的欠缺,所有的代码都会运行在同一进程空间之内

传统的架构,分为三层架构 web控制层、业务逻辑层、数据库访问层

一旦发生问题 问题就会扩散到整个系统,并且如果想要发布新版本 维护也是一个难题

为了允许程序出错,为了获得隔离、自治的能力,为了可以技术异构等目标,是继为了性能与算力之后,让程序再次选择分布式的理由

SOA时代

2020118135845

202011814010

SOA是集成的思想,使用ESB集成现有的老系统,是解决服务孤岛打通链条,是无奈之举

SOA的终极目标是希望总结出一套自上而下的软件研发方法论,所以SOA本身有着许多规范,但正是由于过于严格的规范定义带来过度的复杂性

微服务时代

轻量级 围绕业务 异构 自动化

在微服务的早期 它还是被作为SOA的一种补充手段

微服务追求的是更加自由的架构风格,摒弃了几乎所有SOA里可以抛弃的约束和规定

后微服务时代

从软件层面独力应对微服务架构问题,发展到软、硬一体,合力应对架构问题的时代

这里的硬件指的更多是诸如容器 虚拟化技术等为主的基础设施

为了解决在硬件上的服务治理粒度过粗的问题,这个时代完成了第二次进化,也就是服务网格的引入,到目前为止,服务网格还算是个新概念,仍然还在发展

另外一条路-Serverless

如果说微服务架构是分布式系统这条路的极致,那无服务架构,也许就是“不分布式”的云端系统这条路的起点

无服务的无状态特征天生就不适合做某些事,或许在某些场景下,它会做的更好,但长期来看,还是为以服务架构为主