软件架构的演进

1、软件架构的发展

软件架构的发展经历了从单体架构、垂直架构、SOA 架构到微服务架构的过程。

1.1、单体架构

Web 应用程序发展的早期,大部分 web 工程师将所有的功能模块打包到一起并放在一个 web 容器中运行,所有功能模块使用同一个数据库。

下图是一个单体架构的电商系统:

优点:

  1. 项目架构简单,前期开发成本低,周期短。小型项目的首选。
  2. 开发效率高,无须考虑跨语言,模块之间交互采用本地方法调用。
  3. 容易部署,运维成本小,直接打包为一个完整的包,拷贝到 web 容器的某个目录下即可运行。
  4. 容易测试:IDE 都是为开发单个应用设计的、容易测试——在本地就可以启动完整的系统。

缺点:

  • 复杂性高:以一个百万行级别的单体应用为例,整个项目包含的模块非常多、模块的边界模糊、 依赖关系不清晰、 代码质量参差不齐、 混乱地堆砌在一起。可想而知整个项目非常复杂。每次修改代码都心惊胆战,甚至添加一个简单的功能,或者修改一个 Bug 都会带来隐含的缺陷。
  • 技术债务:随着时间推移、需求变更和人员更迭,会逐渐形成应用程序的技术债务,并且越积 越多。“ 不坏不修”,这在软件开发中非常常见,在单体应用中这种思想更甚。已使用的系统设计或代码难以被修改,因为应用程序中的其他模块可能会以意料之外的方式使用它。
  • 部署频率低:随着代码的增多,构建和部署的时间也会增加。而在单体应用中,每次功能的变更或缺陷的修复都会导致需要重新部署整个应用。全量部署的方式耗时长、 影响范围大、 风险高,这使得单体应用项目上线部署的频率较低。而部署频率低又导致两次发布之间会有大量的功能变更和缺陷修复,出错率比较高。
  • 可靠性差:某个应用 Bug,例如死循环、内存溢出等,可能会导致整个应用的崩溃。
  • 扩展能力受限:单体应用只能作为一个整体进行扩展,无法根据业务模块的需要进行伸缩。例如,应用中有的模块是计算密集型的,它需要强劲的CPU;有的模块则是 IO 密集型的,需要更大的内存。由于这些模块部署在一起,不得不在硬件的选择上做出妥协。
  • 阻碍技术创新:单体应用往往使用统一的技术平台或方案解决所有的问题,团队中的每个成员 都必须使用相同的开发语言和框架,要想引入新框架或新技术平台会非常困难。

1.2、分布式架构

分布式架构也称为垂直架构。分布式应用是单体架构的并发扩展,它将一个大的系统划分为多个业务模块,业务模块分别部署在不同的服务器上,各个业务模块之间通过接口进行数据交互。数据库也大量采用分布式数据库,如 Redis、ES、solor 等。通过 LVS/Nginx 代理应用,将用户请求均衡的负载到不同的服务器上。

优点:

  1. 通过垂直拆分,每个子系统变成小型系统,功能简单,前期开发成本低,周期短。
  2. 每个子系统可按需伸缩。
  3. 每个子系统可采用不同的技术。
  4. 降低了耦合度:把模块拆分,使用接口通信,降低模块之间的耦合度。
  5. 责任清晰:把项目拆分成若干个子项目,不同的团队负责不同的子项目。
  6. 扩展方便:增加功能时只需要再增加一个子项目,调用其他系统的接口就可以。
  7. 部署方便:可以灵活的进行分布式部署。
  8. 提高代码的复用性:比如 service 层,如果不采用分布式 rest 服务方式架构就会在手机商城、微信商城、pc、android、ios 每个端都要写一个 service 层逻辑,开发量大,难以维护,一起升级,这时候就可以采用分布式 rest 服务方式,公用一个 service 层。

缺点:

  1. 子系统之间存在数据冗余、功能冗余,耦合性高。
  2. 按需伸缩粒度不够,对同一个子系统中的不同的业务无法实现,比如订单管理和用户管理。
  3. 系统之间的交互要使用远程通信,接口开发增大工作量,但是利大于弊。

1.3、面向服务架构(SOA)

SOA 全称为Service-Oriented Architecture,即面向服务的架构。它可以根据需求通过网络对松散耦合的粗粒度应用组件(服务)进行分布式部署、组合和使用。一个服务通常以独立的形式存在于操作系统进程中。

站在功能的角度,把业务逻辑抽象成可复用的服务,通过服务的编排实现业务的快速再生,目的:把原先固有的业务功能转变为通用的业务服务,实现业务逻辑的快速复用。

优点:

  1. 将重复的功能抽取为服务,提高开发效率,提高系统的可重用性、可维护性。
  2. 可以针对不同服务的特点按需伸缩。
  3. 采用 ESB 减少系统中的接口耦合。

缺点:

  1. 系统与服务的界限模糊,会导致抽取的服务的粒度过大,系统与服务之间耦合性高。
  2. 虽然使用了ESB,但是服务的接口协议不固定,种类繁多,不利于系统维护。

1.4、微服务架构

基于 SOA 架构的思想,为了满足移动互联网对大型项目及多客户端的需求,对服务层进行细粒度的拆分,所拆分的每个服务只完成某个特定的业务功能,比如订单服务只实现订单相关的业务,用户服务实现用户管理相关的业务等等,服务的粒度很小,所以称为微服务架构。

微服务可以部署在不同的服务器上,也可以部署在相同的服务器不同的容器上。当应用的故障不会影响到其他应用,单应用的负载也不会影响到其他应用,其代表框架有 Spring cloud、Dubbo 等。

微服务之间采用 RESTful、RPC 等轻量级协议传输。

优点:

  • 易于开发和维护:一个微服务只会关注一个特定的业务功能,所以它业务清晰、代码量较少。开发和维护单个微服务相对简单。而整个应用是由若干个微服务构建而成的,所以整个应用也会被维持在一个可控状态。
  • 单个微服务启动较快:单个微服务代码量较少,所以启动会比较快。
  • 局部修改容易部署:单体应用只要有修改,就得重新部署整个应用,微服务解决了这样的问题。一般来说,对某个微服务进行修改,只需要重新部署这个服务即可。
  • 技术栈不受限:在微服务架构中,可以结合项目业务及团队的特点,合理地选择技术栈。例如某些服务可使用关系型数据库 MySQL;某些微服务有图形计算的需求,可以使用 Neo4j;甚至可根据需要,部分微服务使用 Java 开发,部分微服务使用 Node.js 开发。

缺点:

  • 运维要求较高:更多的服务意味着更多的运维投入。在单体架构中,只需要保证一个应用的正常运行。而在微服务中,需要保证几十甚至几百个服务服务的正常运行与协作,这给运维带来了很大的挑战。
  • 分布式固有的复杂性:使用微服务构建的是分布式系统。对于一个分布式系统,系统容错、网络延迟、分布式事务等都会带来巨大的挑战。
  • 接口调整成本高:微服务之间通过接口进行通信。如果修改某一个微服务的 API,可能所有使用了该接口的微服务都需要做调整。
  • 重复劳动:很多服务可能都会使用到相同的功能,而这个功能并没有达到分解为一个微服务的程度,这个时候,可能各个服务都会开发这一功能,从而导致代码重复。尽管可以使用共享库来解决这个问题(例如可以将这个功能封装成公共组件,需要该功能的微服务引用该组件),但共享库在多语言环境下就不一定行得通了。

2、主流的微服务框架

2.1、Dubbo

2.1.1、Dubbo 概述

Dubbo 致力于提供高性能和透明化的远程服务调用方案和SOA服务治理方案。Dubbo 也是采用了 Spring 的配置方式,对应用没用 API 没有侵入。

2.1.2、Dubbo 的核心功能

  • 面向接口的高性能RPC调用
  • 智能负载均衡
  • 服务的自动注册与发现
  • 高度的可扩展
  • 运行期流量调度
  • 可视化的服务治理与运维

2.2、Spring Cloud

2.2.1、Spring Cloud 概述

Spring Cloud 是基于 Spring boot 的一个快速开发微服务的框架。它提供了开发微服务所需的一些常见组件。

  • 服务发现(Spring Cloud 通过 DiscoveryClient 接口实现类,让服务中心发现服务)
  • 断路器(底层服务出现故障可能导致用户级联故障,Spring Cloud 采用断路器机制解决问题。电路关闭,不进行通信,电路打开进行通信)
  • 智能路由(路由功能是微服务的一部分,比如 /api/user 转发到到 user 服务,/api/shop 转发到到 shop 服务)
  • 微代理(统一代理控制请求入口,弱化各个微服务被客户端记忆功能)
  • 控制总线(利用分布式消息将服务和服务实例连接在一起,用于在一个集群中传播状态的变化)
  • 一次性令牌(使用一次就失效)
  • 全局锁(在并发时全局锁定资源)
  • 领导选举(基于 Zookeeper,Redis,Hazelcast,Consul 实现的领导选举的抽象和实现)
  • 配置管理(Spring Cloud 利用配置中心统一管理配置)
  • 分布式会话(Spring Cloud 微服务项目中,使用 Redis 实现简单高效的session 共享)
  • 集群状态(集群的健康状态)

Spring Clou 使得构建大型系统变得非常容易和低成本。小型项目可以采用SpringBoot 进行架构,当需要升级到微服务架构时,可以使用 Spring Cloud 方便地对其进行升级。

2.2.2、Spring Cloud 核心功能

  • 分布式、版本化配置
  • 服务注册与发现
  • 路由
  • 负载均衡
  • 断路器
  • 分布式消息传递

3、服务网络(Service Mesh) 框架 lstio

3.1、lstio 概述

lstio 将流量管理添加到微服务中,提供了连接、安全、管理和监控微服务的方案。

3.2、lstio 核心功能

  • 流量管理
  • 安全
  • 监控功能
  • 平台无关性

4、比较 Dubbo、Spring Cloud 和 lstio

对比项 Dubbo Spring Cloud lstio
学习曲线 一般 平滑,有大量成熟的实例 资料较少
开发效率
集成性 Jar包依赖的问题多 基于Spring Boot,更加便于业务落地 目前只在Kubernets上支持比较好
文档 齐全 英文文档齐全 齐全
支持言语 Java、Node.js等 Java、Kotlin、Groovy 与语言无关
开源社区 活跃度低 活跃度高 活跃度高
客户端负载均衡 Ribbon Envoy
批量任务 Spring Bathc

so:Spring Cloud 是 Spring 家庭产品,一直保持着更新和完善。Spring Cloud 的一站式解决方案对于资金和技术实力有限的中小型互联网公司来说是极佳的选择。Spring Cloud 在现阶段或未来较长时间内是最为稳妥的微服务框架。

总结

对于技术而言,太过刻意最求新鲜的技术其实没有太大的意义,只要你使用的技术能够实现你的需求且满足后期维护迭代升级即可,另一方面而言,新的技术其实都是为了满足不同的应用场景而出现的,就像一个软件有生命周期一个技术的活力也与应用场景的生命周期息息相关,了解技术的发展过程才能知其所以然。

看书,看源码,看官网文档,然后去使用,是掌握一项技术的最好捷径。

Reference


软件架构的演进
https://flepeng.github.io/架构-软件架构的演进/
作者
Lepeng
发布于
2023年2月1日
许可协议