软件架构是什么
定义:软件架构由一组元素(组件)和元素之间的关系构成。
架构意义:它让软件开发更加高效,同时软件具有较好的可测性、可部署性、可扩展性、可维护性,而这些都属于软件的质量属性,因此架构可让软件质量更好。
卡耐基梅隆大学工程研究所Len Bass及其同事对软件架构定义:
计算机系统的软件架构是构建这个系统所需的一组结构,包括软件元素、它们之间的关系以及两者的属性。
软件架构分解
为什么架构如此重要
应用程序两个层面需求
功能性需求
这个需求描述的是应用程序具体要实现的业务
非功能性需求
非功能性需求也被称为质量需求,简称能力(软件能力)。
一系列非功能性需求决定了应用程序运行时的质量,如:可靠性、可扩展性。同时决定了开发阶段质量,如:可维护性、可测试性、可扩展性、可部署性。为应用程序选择的不同架构,则决定了这些质量属性。
架构的重要性在于它帮助应用满足了非功能性(质量属性)需求(如:开发效率、可靠性、可扩展性、可维护性、可测试性、可部署性等)
建筑架构:中国徽式建筑、福建土楼、维多利亚式等
定义:架构风格确定了可以在该架构实例中所使用的元素和元素间关系的描述表,以及将元素和元素间关系如何组合的一组约束。
不同的架构风格,元素可能不一样,进而元素间的关系也会不一样,因此它们的组合方式就会不一样。
分层式架构风格
分层架构每层只能依赖于其紧邻的下一层或其下面的任何层
表现层:包含外部API和用户界面
业务逻辑层:包含业务逻辑
数据持久层:实现与数据库的交互逻辑
分层式架构风格的弊端:
单个表现层:它无法展现应用程序可能不仅仅由单个系统调用的事实。
单一数据化持久层:它无法展现应用程序可能与多个数据库进行交互的事实。
将业务逻辑层定义为依赖于数据持久化层:理论上,这样的依赖性会妨碍你在没有数据库的情况下测试业务逻辑。
六边形架构风格
六边形架构选择以业务逻辑为中心的方式组织逻辑视图
如上 六边形架构示例,由业务逻辑和一个或多个外部系统通信的适配器组成。业务逻辑具有一个或多个端口,处理来自外部系统请求的入站适配器调用入站端口,出站适配器实现出站端口,并调用外部系统。
六边形架构有一个或多个入站适配器(分层的表现层)、一个或多个出站适配器(分层的持久化层),此架构的关键特性和优点是不依赖于适配器,相反各种适配器都依赖于业务逻辑。
业务逻辑:业务逻辑一般可以是服务(或模块),也可以是由多个服务一起组合而成。
入站端口:在Java中端口对应的是业务逻辑公开的API
出站端口:业务逻辑调用外部系统(如:其他微服务、消息服务等)
入站适配器:调用入站端口处理外部请求。实例如:一个实例Spring MVC Controller
实现了一组REST接口;另一实例是订阅消息的消息代理客户端
。多个入站适配器可以调用相同的入站端口。
出站适配器:实现了出站端口,通过调用外部服务或系统来处理业务逻辑。一个实例是实现访问数据库的操作的数据库访问对象(DAO类),另一个实例是调用远程服务的代理类,第三个实例是发送消息的代理类
本人理解:
- SpringMVC的Controller类对应入站适配器,而我们定义的Controller类里的每个方法相当于入站端口;消订阅消息的客户端类相当于入站适配器,而对各种消息操作方法(消费消息方法)好比入站端口。
- 数据库操作类如Mapper、Repository、DAO类等为出站适配器,而类里对数据库的操作方法对应出站端口;Springboot Feign对应出站适配器,类里对远程的访问方法对应出站端口。
六边形架构风格的一个重要好处是它将业务逻辑和适配器中包含的表示层逻辑和数据访问层逻辑隔离开来,从而对他们不产生依赖关系。
微服务架构风格
一种架构风格,由一组实现视图(组件元素)组成。它的组件是服务,连接器是使这些服务能够协作的通信协议。每个服务又有自己的逻辑架构视图,通常也是六边形架构。
微服务架构模式:将应用程序构建为松耦合、可独立部署的一组服务。松耦合是微服务架构的关键约束,服务之间必须是松耦合关系。
什么是服务
服务是一个单一的,可独立部署的软件组件,它实现了一些有用的功能。
服务具有API,封装了服务内部逻辑实现,为客户端提供对功能的访问。有两种类型操作:命令
和查询
。API由命令、查询和事件组成。外部系统无法绕过API直接访问服务内部。
每个服务都有自己的架构,一般典型的是六边形架构。
服务具有API
且可独立部署
。
服务的松耦合
共享类库的角色
一些可能会更改公共通用的功能应尽可能的作为服务来实现,而不是共享数据库(共享库则在每个其他服务里都会有重复功能代码)
可以使用共享库来实现不太可能改变的功能。如:在每个服务中实现一个Money类(货币转换等固定功能)没有意义,可单独创建一个通用库供所有服务使用。
微服务架构的目标
将精心设计的服务定义为能够由小团队开发的服务,并且交付时间最短,与其他团队协作最少。
微服务架构把应用程序通过一些小的、松耦合的服务组织在一起,这样的架构提升了开发阶段的效率,特别是可维护性、可测试性和可部署性,让软件开发的速度更快。
定义应用程序架构三步法
第一步:将应用程序需求提炼为关键请求(定义系统操作,即:系统要做的事情)
第二步:确定如何拆解服务
两种拆解策略:1. 按业务能力拆解 2. 围绕领域驱动设计的子域拆解
第三步:确定每个服务的API
抽象领域模型 -> 系统操作 ->
定义系统操作起点是应用程序需求,包括用户故事及相关用户场景
定义系统操作分两步
第一步:创建由关键类组成的抽象领域模型(分析用户故事中频繁出现的名词
,此为标准技术
)
第二步:确定系统操作(分析用户故事中的动词
)
创建抽象领域模型一些标准技术,分析用户故事中频繁出现的名词
(本人理解为:发出系统操作的对象或被操作对象)。
系统操作还并非是系统的API
识别系统指令的切入点是分析用户故事中的动词
(本人理解:对系统对象发出的系统指令)
两种类型操作
命令型:创建、更新和删除数据的系统操作
查询型:查询和读取数据的系统操作
抽象领域模型和系统操作回答类这个应用做什么。系统操作通过领域模型的方式描述,每个重大系统操作都对应着架构层面的一个重大场景。
模式:根据业务能力进行服务拆分
定义与业务能力相对应的服务(识别业务能力 -> 业务能力到服务)
识别业务能力
系统的业务能力可理解为这个系统是做什么。
业务能力可以分为“顶级业务能力
”和“子能力
”,每个业务能力可以被认为是一个服务,可以理解为大业务下还可以分为多个小业务(大系统拆分成多个微服务)
业务能力到服务
将每个业务能力或业务能力组映射到不同的服务
按业务能力拆分出现问题:
- 过多的进程通信导致特定分解效率低下,导致必须把一些服务组合一起(
拆的过细
)- 服务可能会在复杂性方面增长到值得将其拆分成多个服务(
拆分不够彻底
)
模式:根据子域进行服务拆分
根据DDD的子域服务(领域 -> 子域)
DDD两个重要概念:子域
和限界上下文
领域驱动为每一个子域定义单独的领域模型。子域是领域的一部分,领域是DDD中用来描述应用程序问题域的一个术语(子域的定义结果和跟业务能力非常接近)
限界上下文:DDD领域模型的边界(限界上下文包括实现这个模型的代码集合)
使用微服务架构时,通过DDD定于应用程序领域的子域,然后将子域对应为一个微服务,这样就完成了微服务的设计工作。
上图:FTGO应用程序所有功能使用DDD组成一个领域,领域中划分子域,子域分别映射到不同的微服务,每个微服务有自己的领域模型。
单一职责原则(SRP)
改变一个类应该只有一个理由。
微服务架构中SRP:每个服务应是内聚的、设计小、仅仅含有单一职责。这样服务方便维护和扩展,稳定性强。
闭包原则(CCP)
在包中包含的所有类应该是对同类的变化的一个集合。也就是说,如果对包做出修改,需要调整的类应该都在这个包之内,对其他包没有影响。(如:两个类的修改必须耦合先后发生,则应该将它们放在同一包下)
微服务架构中CCP:把因同样的原因(类似需求)发生变更的服务放在一个组件,当需求发生变化,一个变更可能只会影响一个团队和一个服务,使得变更和部署更容易。
指导原则总结:服务业务尽量内聚单一,需求的变更影响的服务应尽量少。
网络延迟
同步进程间通信导致可用性降低
在服务之间维持数据一致性
获取一致的数据视图
不同服务数据库不同,查询返回的数据结果因网络或异常等原因可能会不一样
上帝类阻碍了拆分
本人理解:上帝类指的是维护了太多业务功能的类,也可以是一个类包含了N多属性
服务API:服务的操作和事件。操作(更新查询)和事件使得服务可与其他服务协作。
把系统操作分给对应的服务
梳理系统的各种操作,并把这些操作分配给不同的服务(如:创建订单、更新订单、撤销订单分配给订单服务)。
确定支持服务操作所需要的API
服务被分配操作后,确定支持这些操作所需要的API(接口)(如:创建订单提供createOrder接口)
什么是软件架构?
软件架构是组成软件系统的一组结构,它由软件元素和它们之间的关系及属性组成。
架构为什么重要?
实现软件的非质量属性(可维护性、可测性、可扩展性、可部署性等)
微服务架构是什么?
微服务架构是一种架构风格,可将应用程序构建为松耦合、可独立部署的一组服务
微服务本质?
可为外界提供资源、独立部署、独立维护、易扩展的软件元素
如何定义微服务?
(1)服务拆分方式:根据业务能力进行拆分;根据子域进行服务拆分
(2)其他拆分指导原则:单一职责原则(SRP)、闭包原则(CCP)
(3)微服务拆分难点
(4)定义API