什么是软件架构
关于软件架构的定义主要分为两大派别:决策派和组成派
决策派:
- 架构是一系列重要决策的集合,包括软件的组织,构成系统的结构要素及其接口的选择,元素在协作中表现的行为
- 软件架构即一系列重要的设计决策,这些决策上的失误可能最终导致软件项目的失败.
组成派:
- 软件系统的架构将系统定义为计算组件及组件之间的交互:连接和约束.
- 软件架构是一组具有特定形式的架构元素,包括:负责完成数据加工的处理元素,作为被加工的信息的元素,及用于将不同部分组合在一起的连接元素
- 软件架构是以组件,组件相互之间的关系,组件与环境之间的关系所描述的软件系统的基本组织结构,以及指导其设计与演化的原理.
软件架构的演化
单体架构
- 单体应用的全部功能被集成在一起作为一个单一的单元
- 单体架构更多地作为应用的部署架构,即只要它部署在同一台(虚拟)机器上,运行于同一个进程中,而无论应用内部如何模块化,服务化或分层.
分层架构
- 关注点分离原则
- 软件系统的组件被分成多个互相不重叠的层次,每一层都有着特定的职能,仅处理本层的逻辑,并不关心其他层的实现.(只能从上向下逐层访问,不能逆向或跨层访问)
- 表现层
- 业务层
- 持久层
- 数据层
- 分层架构模式特点
- 结构简单
- 易于组织开发
- 便于独立测试,维护
- 不易实现持续发布,部署
- 性能代价高
- 可扩展性差
面向服务架构
-
面向服务架构(SOA)
是一个分布式组件集合,这些组件为其他组件提供服务,或者消费其他组件所提供的服务,而无需感知其他组件的实现细节
-
企业服务总线(ESB)
为服务间的相互调用提供支持环境,路由服务间的消息,并对消息和数据进行必要的转换.
-
服务编排引擎(Orchestration Engine)
可以根据预先定义的脚本对服务消费者与服务提供者之间的交互进行指挥.
面向服务架构的优点
- 服务自身高内聚,服务间松耦合,最小化开发维护中的相互影响
- 良好的互操作性,符合开放标准
- 模组化,高重用性
- 服务动态识别,注册,调用
面向服务架构的缺点
- 系统复杂性提高
- 难以测试验证
- 各独立服务的演化不可控
- 中间件易成为性能瓶颈
面向服务架构实现原则
- 服务解耦:服务之间的关系最小化,只是互相知道接口
- 服务契约:服务按照描述文档所定义的服务契约行事
- 服务封装:除了服务契约所描述的内容,服务将对外部隐藏实现逻辑
- 服务重用:将逻辑分布在不同的服务中,以提高服务的重用性
- 服务组合:一组服务可以协调工作,组合起来形成定制组合业务需求
- 服务自治:服务对所封装的逻辑具有控制权
- 服务无状态:服务将一个活动所需保存的资讯最小化
构建云原生应用程序(SaaS)的12要素
- 1.基准代码:一份基准代码,多份部署.基准代码和应用之间总是保持一一对应的关系.所有部署的基准代码相同,但每份部署可以使用其不同版本.
- 2.依赖:显示声明依赖关系.应用程序一定通过依赖清单,确切地声明所有依赖项.
- 3.配置:在环境中存储配置.将应用的配置存储于环境变量中.环境变量可以非常方便地在不同的部署间做修改,却不动一行代码
- 4.后端服务:把后端服务当做附加资源.应用不会区别对待本地或第三方服务.对应用程序而言,两种都是附加资源.
- 5.构建,发布,运行:严格区分构建,发布,运行这三个步骤.
- 6.进程:以一个或多个无状态进程运行应用.应用的进程必须无状态且无共享.
- 7.端口绑定:通过端口绑定提供服务.应用完全自我加载而不依赖任何网络服务器就可以创建一个面向网络的服务.
- 8.并发:通过进程模型进行扩展.开发人员可以运用这个模型去设计应用架构,将不同工作分配给不同的进程类型.
- 9.易处理:快速启动和优雅终止可以最大化健壮性.应用的进程是可支配的,意思是说它们可以瞬间开启或停止.
- 10.开发环境与线上环境等价:尽可能保持开发,预发布,线上环境相同.应用想要做到持续部署就必须缩小本地 与线上差异.
- 11.日志:把日志当做事件流.应用本身考虑存储自己的输出流,不应该试图去写或者管理日志文件.
- 12.管理进程:后台管理任务当做一次性进程运行.一次性管理进程应该和正常的常驻进程使用相同的环境.
微服务架构风格
什么是微服务架构
- 微服务架构风格是一种将一个单一应用程序开发为一组小型服务的方法,每个服务运行在自己的进程中,服务间通信采用轻量级通信机制,这些服务围绕业务能力构建并可通过自动部署机制独立部署.
- 微服务架构本质上仍然是一种分布式架构,也是面向服务架构的一种扩展.
微服务架构的特点
1.通过服务组件化
- 组件是一个可以独立替换或升级的软件单元,微服务架构实现组件化的方式是分解成服务.
- 服务是一种进程外的组件,它通过web服务请求或远程过程调用(RPC)机制通信.
- 使用服务作为组件的主要原因是服务是可独立部署.
- 使用服务作为组件产生更加明确的组件发布接口.
2.围绕业务能力组织
- 传统软件系统开发管理通常聚焦在技术层面,导致UI团队,服务逻辑团队,数据库团队等的划分,将始终伴随跨团队的沟通,交接和预算审批等.
- 微服务采用围绕业务能力的划分方法来组织服务,实现在服务的业务领域内的宽栈实现,其团队都是跨职能的包括全方位开发技能,如用户体验,数据库,项目管理等.
- 微服务采用产品开发模式,非项目模式,开发团队负责软件的整个产品周期,持续关注软件如何帮助用户提升业务能力,实现价值交付.
3.内聚和解耦
- 基于微服务构建的系统目标是尽可能的解耦和尽可能的内聚,它们拥有各自的领域逻辑.
- 当系统被划分成分离的服务时,可利用领域驱动设计的理念,把一个复杂域划分成多个限界上下文,并且映射出它们之间的关系.
- 服务和上下文边界的确定有助于澄清和强化分离,实现解耦.
4.去中心化
- 去中心化治理,在构建微服务时可以有服务自己的技术栈选择.
- 服务之间只需要约定接口,而无需关注彼此的内部实现;
- 同样,运维只需要知道服务的部署规范.
- 去中心化数据存储,微服务更倾向于让每个服务管理自己的数据库,或者同一数据库技术的不同实例,或完全不同的数据库系统.
- 去中心化数据管理,对跨微服务的数据来说,去中心化负责对管理升级带来困难,微服务架构强调服务间的无事务协作,需要权衡更大一致性的业务损失与修复错误的代价.
5.基础设施自动化
- 随着基础设施的自动化,特别是云和Web Services等技术的发展,已经降低了构建,部署和运维微服务的操作复杂度.
6.服务设计
- 高可用性
- 任何服务调用都可能因为服务提供者不可用而失败,客户端必须尽可能有效的应对这种失效
- 为每个单独的服务设置完善的监控和日志记录,有助于对于快速发现不良突发行为而尽早修复
- 变更与演化
- 把组件放在服务中,只需重新部署修改的服务,可以在更细粒度上实现频繁,快速的发布.
- 服务的划分上,系统中很少变更的部分应该和正在经历频繁改动的部分放在不同的服务里
微服务架构与传统架构比较
优势 | 劣势 | |
---|---|---|
单体 | 1.人所众知:传统工具,应用和脚本都是这种结构 2.IDE友好:Eclipse,IntelliJ等开发工具多 3.便于共享:单个归档文件包含所有功能,便于共享 4.易于测试:单体应用部署后,服务或特性即可展现,没有额外的依赖,测试可以立即开始 5.容易部署:只需将当个归档文件复制到单个目录下 | 1.不够灵活:任何细修改需要将整个页面重新构建部署,这降低了团队的灵活性和功能交付频率. 2.妨碍持续交付:单体应用比较大时,构建时间较长,不利于频繁部署,阻碍持续交付. 3.受技术栈限制:必须使用同一语言/工具,存储及消息,无法根据具体的场景做出其他选择. 4.技术债务:不坏不修,系统代码难以修改,耦合性高. |
SOA | 1.服务重用性:通过编排基本服务用于不同的场景 2.易维护性:单个服务的规模变小,维护相对容易 3.高可用性:使用消息机制和异步机制,提高了可靠性. 4.高扩展和高可用:分布式系统的特性 5.软件质量提升:单个服务的复杂度降低 6.平台无关:可以集成不同的系统 7.提升效率:服务重用,降低复杂度,提升了开发效率 | 1.过分使用ESB:使得系统集成过于复杂 2.使用基于SOAP协议的WS:使得通信的额外开销很大 3.使用形式化的方式管理:增加了服务管理的复杂度 4.需要使用可靠的ESB:初始投资比较高 |
微服务 | 1.简单:单个服务简单,只关注一个业务功能. 2.团队独立性:每个微服务可以由不同的团队独立开发 3.松耦合:微服务是松耦合的 4.平台无关:微服务可以使用不同的语言和工具开发 5.通信协议轻量级:使用REST或者RPC进行服务间通信. | 1.运维成本高 2.分布式系统的复杂性 3.异步,消息与并行方式使得系统的开发门槛增加 4.分布式系统的复杂性也会让系统的测试变得复杂. |
微服务架构的核心模式
核心模式即针对采用微服务系统在特定场景下的特定问题,所使用的成熟架构解决方案集合
1.服务注册与发现
服务消费者获取服务提供者的机制,实现两者之间的解耦
- 微服务启动时将自己的地址等信息注册到服务发现组件
- 服务消费者可以从服务发现组件中查询服务提供者的网络地址和调用接口.
- 各个微服务与服务发现组件使用一定机制通信,如长时间无法通信即注销该实例
- 微服务数量,地址,接口等发生变化时,重新注册到服务发现组件,无需人工修改
2.API网关
- 微服务架构的应用客户端如何访问各项服务?
- 微服务提供的是细粒度API,客户端需要同多项服务进行交互.
- 不同客户端需要不同的数据
- 不同客户端的性能要求有区别
- 服务实例数量和位置会发生动态变化
- 服务划分方式会随时间的推移而改变
- API网关作为全部客户端的单一入口点,可以针对不同客户端提供出不同的API
- 确保客户端不必关心应用程序的微服务拆分方式
- 确保客户端不受服务实例位置的影响
- 为每套客户端提供最优API
- 降低请求往返次数
- 将从客户端调用多项服务的逻辑转换为从API网关处调用,以简化整个客户端
3.熔断器
- 微服务之间难免存在依赖关系,同时相互之间通过网络进行通信,一旦任何服务或网络出现问题会引起请求失败,并可能导致级联故障,将不可用在系统中逐渐放大.
- 熔断器模式
- 可以防止程序不断地尝试执行可能会失败的操作;
- 可以使程序能够诊断错误是否已经修正,进而再次尝试调用操作
- 熔断器的实现:
- 闭合状态:对程序的请求能够直接引起方法的调用
- 断开状态:对程序的请求会立即返回错误响应
- 半断开状态:允许对程序的一定数量的请求可以调用服务,如调用成功,可认为之前导致调用失败的错误已经修正,熔断器切换到闭合状态;如调用失败,则认为问题仍然存在,熔断器切回到断开状态.
微服务架构的实现
下图中包含了几乎全部DevOps所需要的技术和工具
微服务技术选型(轻量级)
- 开发服务:Spring Boot
- 封装服务:Docker
- 部署服务:Jenkins
- 注册服务:ZooKeeper
- 调用服务:Node.js
总结
软件架构的演化
- 单体->分层->面向服务->微服务
微服务架构的特点
- 服务颗粒化:服务粒度由业务功能决定,服务间尽可能解耦
- 责任单一化:单一职责原则,服务内尽可能内聚
- 运行隔离化:服务运行在各自进程中,互不影响
- 管理自动化:对服务提供自动化部署与监控预警能力
微服务架构的挑战
- 运维要求高:微服务数量多,部署与监控的要求高
- 发布复杂度:部署环境多样化,网络性能,系统容错,分布式事务挑战
- 部署依赖强:服务间相互调用关系复杂,存在部署顺序依赖
- 通讯成本高:跨进程调用比进程内调用消耗更多的资源