什么是系统架构?
系统架构是系统的一种整体的高层次的结构表示,它确定了系统的基本组织、组件之间的关系、组件与环境的关系,以及指导其设计和发展的原则。随着技术的发展和业务需求的增长,系统架构经历了从简单到复杂、从集中到分布的演变过程。
单体架构(Monolithic Architecture)
- 定义与结构
- 单体架构是最早期的系统架构形式。它将应用程序的所有功能,包括用户界面、业务逻辑、数据访问等都打包在一个单一的代码库中。例如,一个简单的 Web 应用,它的前端 HTML/CSS/JavaScript 代码、后端处理用户请求的业务逻辑代码(如用 Python 的 Flask 或 Java 的 Spring Boot 编写)以及数据库访问代码都在一个项目中。
- 整个应用作为一个独立的单元进行开发、部署和运行。通常部署在一台服务器上,所有的请求都由这个单一的应用实例来处理。
- 优点
- 开发简单:对于小型项目,开发人员可以快速上手。因为所有的功能都在一个代码库中,没有复杂的分布式系统的概念需要考虑,如网络通信、数据一致性等。例如,一个小型的公司内部的员工信息管理系统,只需要实现员工信息的增删改查等基本功能,单体架构可以快速构建完成。
- 易于测试和部署:在部署方面,只需要将整个应用打包并部署到服务器上即可。测试时,也可以作为一个整体进行单元测试和集成测试,不需要考虑多个组件之间的复杂交互。
- 缺点
- 可扩展性差:随着业务的增长,应用的功能和用户量不断增加,单体架构会变得越来越臃肿。例如,当一个电商系统的用户量从几千增长到几十万时,所有的业务逻辑都在一个应用中处理,服务器的资源(如 CPU、内存)会很快达到瓶颈,而且很难通过简单地添加服务器来扩展应用的性能。
- 维护成本高:由于所有的功能代码都耦合在一起,一个小的功能修改可能会影响到其他部分。例如,修改数据库访问层的一个 SQL 查询语句,可能会对上层的业务逻辑产生意想不到的影响,而且由于代码库庞大,定位问题和修复问题的难度也会增加。
垂直架构(Vertical Architecture)
- 定义与结构
- 垂直架构是在单体架构的基础上,按照业务功能进行垂直拆分。例如,对于一个电商系统,可以将其拆分为用户管理模块、商品管理模块、订单管理模块等。每个模块都有自己独立的代码库、数据库(可以是独立的数据库实例,也可以是同一个数据库中的不同表)和服务器。
- 这些模块之间通过接口(如 RESTful API)进行通信。比如,用户管理模块提供用户注册、登录等接口,订单管理模块通过调用这些接口来获取用户信息,完成订单创建等操作。
- 优点
- 提高可维护性:由于每个业务模块是独立的,开发团队可以针对不同的模块进行独立开发、维护和升级。例如,商品管理团队可以专注于商品信息的添加、修改和删除功能的优化,而不用担心会影响到用户管理模块的功能。
- 一定程度的扩展性:每个模块可以根据自己的业务需求独立地进行扩展。例如,订单管理模块如果遇到大量的订单处理请求,可以单独增加服务器来处理订单业务,而不会影响到其他模块的性能。
- 缺点
- 存在重复功能:不同的垂直模块可能会有一些重复的功能,如用户认证和授权功能。每个模块都可能需要实现自己的用户登录和权限检查逻辑,这会导致代码重复,增加开发成本。
- 模块间通信复杂:模块之间通过接口进行通信,如果接口设计不合理或者发生变化,会影响到多个模块之间的交互。例如,用户管理模块修改了用户信息接口的返回数据格式,那么所有调用这个接口的模块(如订单管理模块、客服管理模块等)都需要进行相应的修改。
分布式架构(Distributed Architecture)
- 定义与结构
- 分布式架构进一步将系统的各个功能单元分散到不同的计算机节点上。它包括多个层次,如分布式存储、分布式计算等。在分布式存储方面,数据会被存储在多个存储节点上,通过数据冗余和分布式算法来保证数据的可靠性和可用性。例如,在大数据存储系统中,像 Hadoop 的 HDFS(Hadoop Distributed File System)会将文件分割成多个数据块,存储在不同的节点上。
- 在分布式计算方面,任务会被分解并分配到多个计算节点上进行处理。例如,一个大规模的数据分析任务可以通过分布式计算框架(如 Apache Spark)将计算任务分配到集群中的多个节点上同时进行计算,最后将结果汇总。
- 优点
- 高可扩展性:可以通过添加节点来轻松扩展系统的存储容量和计算能力。例如,一个云计算服务提供商,当用户对存储资源的需求增加时,可以不断添加存储节点来满足需求;当需要处理更多的计算任务时,可以添加计算节点来加速计算过程。
- 高可用性:由于数据和计算任务分布在多个节点上,单个节点的故障不会导致整个系统瘫痪。例如,在一个分布式数据库系统中,如果一个节点出现故障,其他节点可以继续提供服务,并且系统可以通过数据冗余和恢复机制来修复故障节点的数据。
- 缺点
- 系统复杂:分布式系统涉及到多个节点之间的通信、协调和数据一致性等问题。例如,在分布式事务处理中,要保证多个节点上的数据操作要么全部成功,要么全部失败是一个复杂的问题。开发人员需要处理网络延迟、节点故障等多种复杂情况,增加了系统开发和维护的难度。
- 数据一致性挑战:在多个节点存储和更新数据时,很难保证数据的实时一致性。例如,在一个分布式缓存系统中,不同节点上的缓存数据可能会因为更新时间不同而出现不一致的情况,需要采用复杂的缓存一致性策略来解决这个问题。
面向服务的架构(Service - Oriented Architecture,SOA)
- 定义与结构
- 定义:面向服务的架构(SOA)是一种软件设计理念和架构风格,它将应用程序的不同功能单元构建成一个个服务。这些服务是独立的、可复用的软件组件,它们通过明确定义的接口来提供业务功能。这些接口使用标准的通信协议(如 SOAP 或 REST),使得不同的服务可以在不同的操作系统、编程语言和硬件平台上进行交互。例如,在一个金融企业中,账户查询服务、转账服务、理财服务等都是独立的服务,它们可以被不同的渠道(如网上银行、手机银行、客服系统)调用。
- 结构:
- 服务提供者:负责提供具体的服务,包括服务的实现和维护。服务提供者将服务发布到服务注册中心,使其他组件能够发现这些服务。例如,银行的转账服务系统就是一个服务提供者,它实现了转账的业务逻辑,并且通过服务注册中心对外发布其转账服务接口。
- 服务注册中心:类似于一个服务的 “目录”,它存储了服务提供者发布的服务信息,包括服务的名称、接口定义、位置等。其他服务使用者可以在注册中心查找所需的服务。例如,在企业级的服务架构中,服务注册中心会记录各个部门提供的服务,方便其他部门查找和调用。
- 服务使用者:通过查询服务注册中心,发现并调用服务提供者提供的服务来完成自身的业务功能。例如,网上银行系统作为服务使用者,会在服务注册中心查找转账服务,然后调用该服务来为用户完成转账操作。
- 优点
- 服务复用性高:不同的业务系统可以复用相同的服务。例如,在一个大型企业集团中,用户认证服务可以被各个子公司的不同业务系统(如人力资源系统、财务系统、销售系统)复用。这样可以减少重复开发,提高开发效率,并且保证了服务的一致性。如果企业要修改用户认证的规则,只需要在用户认证服务中进行修改,所有使用该服务的系统都能受益。
- 灵活性和适应性强:由于业务功能被封装成独立的服务,可以根据业务需求灵活地组合和编排这些服务。例如,一个电商企业在促销活动期间,可以快速组合商品查询服务、折扣计算服务、订单处理服务等,构建一个新的促销业务流程。而且,当企业业务发生变化或扩展时,如新增业务功能或修改现有业务流程,只需要对相关的服务进行调整或添加新的服务,不会对整个系统造成大规模的影响。
- 跨平台和跨语言集成方便:服务通过标准的通信协议进行交互,使得不同平台(如 Windows、Linux)和不同编程语言(如 Java、Python、.NET)开发的系统能够方便地集成。例如,一个用 Java 开发的后端服务可以通过 REST 接口与一个用 JavaScript 开发的前端应用进行通信,实现数据交互和业务协作。
- 支持分布式开发和部署:各个服务可以由不同的团队独立开发和部署,提高了开发效率和系统的可维护性。例如,在一个大型软件项目中,不同的团队可以分别负责不同服务的开发,如一个团队负责用户管理服务,另一个团队负责产品管理服务。这些团队可以按照自己的进度进行开发、测试和部署,只要保证服务接口的兼容性即可。
- 缺点
- 服务治理复杂:由于服务的数量可能较多,且服务之间相互依赖和交互,需要复杂的服务治理机制。包括服务的版本管理、服务的发现和注册管理、服务的监控和性能优化等。例如,当一个服务的接口发生变化时,需要通知所有使用该服务的服务使用者,并确保它们能够正确地更新和调用新的接口。如果服务治理不当,可能会导致系统的混乱和故障。
- 性能开销:服务之间的通信需要通过网络和接口调用,这会带来一定的性能开销,如网络延迟、消息序列化和反序列化等。与单体架构相比,SOA 架构下的系统在处理大量高频请求时,可能会因为这些性能开销而导致响应速度变慢。例如,在一个对实时性要求很高的交易系统中,频繁的服务调用可能会影响交易的处理速度。
- 安全性挑战:服务的分布式和开放性特点使得安全管理变得复杂。需要考虑服务之间的身份验证、授权、数据加密等安全措施。例如,当外部系统或第三方合作伙伴调用企业内部的服务时,如何确保它们是合法的、经过授权的,并且在数据传输过程中保证数据的安全性是一个重要的问题。
- 系统集成难度初始较高:在构建 SOA 系统的初期,需要对业务进行详细的分析和服务的划分,同时要定义好服务的接口和通信协议。这需要投入大量的时间和精力,并且要求开发人员具有较高的架构设计能力和业务理解能力。如果服务划分不合理或者接口定义不清晰,会给后续的系统集成和开发带来困难。
微服务架构(Microservices Architecture)
- 定义与结构
- 微服务架构是一种将应用分解为一组小型、独立的服务的架构风格。每个微服务都专注于一个特定的业务功能,并且可以独立地进行开发、部署和扩展。例如,在一个电商系统中,有用户微服务负责用户注册、登录和信息管理;产品微服务负责产品信息的维护和查询;订单微服务负责订单的创建、处理和跟踪等。
- 这些微服务之间通过轻量级的通信协议(如 HTTP/REST 或消息队列)进行交互。每个微服务都有自己的数据库(可以是关系型数据库或非关系型数据库),并且可以使用不同的技术栈来实现。例如,用户微服务可以用 Java 编写,数据库采用 MySQL;而产品微服务可以用 Node.js 编写,数据库采用 MongoDB。
- 优点
- 独立开发和部署:每个微服务可以由不同的团队独立开发和部署,提高了开发效率。例如,一个大型的互联网公司可以有多个团队分别负责不同的微服务,这些团队可以按照自己的节奏进行开发、测试和部署,不会相互干扰。
- 技术多样性:不同的微服务可以根据自身的需求选择最合适的技术。比如,对于一个对实时性要求很高的通知微服务,可以采用高性能的 Go 语言和消息队列技术;而对于一个数据分析微服务,可以采用 Python 和数据挖掘库来构建。
- 易于扩展:可以根据业务需求对单个微服务进行扩展。例如,如果订单微服务的业务量突然增加,可以单独对订单微服务进行水平扩展(添加更多的订单微服务实例),而不会影响到其他微服务。
- 缺点
- 服务治理复杂:由于微服务数量众多,需要有效的服务治理机制来管理服务的发现、配置、监控等。例如,在一个包含几十个微服务的系统中,要确保新的微服务能够被其他服务发现并且正确地进行通信是一个复杂的问题,需要引入服务发现工具(如 Consul、Eureka)和配置管理工具(如 Spring Cloud Config)。
- 分布式系统的复杂性:和分布式架构一样,微服务架构也面临着分布式系统的问题,如网络通信、数据一致性等。而且由于微服务之间的交互更加频繁,这些问题可能会更加突出。例如,在多个微服务之间进行事务处理时,要保证数据的一致性比在单体架构中更加困难。
其他重要演变
- 应用和数据分离:随着网站业务的发展,用户访问量增大,数据量也增大,需要将应用和数据分离,形成应用服务器、文件服务器和数据库服务器。
- 缓存数据:为了改善网站性能,使用缓存技术将查询较多或改动不大的数据缓存起来,降低数据库服务器负载压力。
- 应用集群:在网站访问高峰、并发量大的情况下,部署应用服务器集群,利用负载均衡器分散访问流量,提供服务可用性。
- 数据库读写分离:随着数据继续增加,请求数量加大,部署多个数据库进行读写分离。
- 部署CDN节点:使用CDN技术加速用户访问,保证用户从最近的服务器获取数据。
- 分布式数据库:在单表数据规模非常庞大时使用,但更常用的拆分手段是业务分库。
- 使用非关系型数据库:当网站数据足够庞大时,关系型数据库达到瓶颈,需要采用非关系型数据库。
系统架构的演变