在软件开发过程中,软件架构模式是实现高质量、可扩展系统的关键。本文将介绍一些常见的软件架构模式,分析其优缺点和适用场景,从而帮助大家在实际项目中做出更明智的架构选择(注意以下的架构模式相互之间并不一定互斥,只是从不同的维度来划分的)。
1. 单体机构
单体架构,是一种最常见的架构方式,如其名,是指将整个应用程序作为一个单独的、不可分割的整体进行设计和开发。在这种架构下,所有的功能模块、数据库、第三方服务等都被整合在一个单一的代码库中,共同构成一个庞大的应用程序。
1.1. 优点
- 开发简单:单体架构拥有单一的代码库和开发环境,这使得项目易于理解和维护,开发简单迅速。
- 调试测试容易:由于整个应用程序在同一个环境下运行,因此调试和测试过程相对容易。
- 易于部署:单体架构可以实现集中部署,当一个应用程序整体打包并部署到服务器时,操作相对简单。
- 性能较好:由于所有应用程序都运行在同一个进程中,没有组件间的复杂交互和通信,单体架构通常比分布式系统具有更高的性能。
1.2. 缺点
随着应用规模的急速增长,很多优点可能就变成了缺点。
- 系统复杂程度高:随着功能的增加,代码库变得庞大和复杂,导致开发人员难以理解整个系统,进而影响代码的质量和维护性。
- 开发速度慢:由于需要编译、构建和测试整个项目,每次更改代码都会消耗大量时间,增加了开发成本。
- 难以扩展:单体应用难以根据不同模块的需求进行针对性的扩展,往往需要整体扩展,导致资源利用效率低下。
- 容错性差:整个系统作为一个进程运行,任何部分的故障都可能影响整个系统的稳定性,导致宕机。
1.3. 适用场景
- 小型应用:单体架构模式简单直接,易于理解和开发,适用于小型应用或刚刚开始的项目。
- 初创公司的初创项目:单体架构可以快速试错,系统模块之间的调用是进程内的通信,因此整体性能表现好,适合初创公司以解决问题、快速铺开市场、节约成本为主要目标。
- 内部管理系统:对于一些非核心、流量不大的内部管理系统,单体架构足以满足使用需求,且开发和维护成本相对较低。
2. 分布式应用架构
分布式架构将庞大复杂的系统拆分为多个独立的组件(业务模块),不同组件可以独立部署和扩展,每个组件可以处理自己的任务,并通过消息传递或远程调用与其他组件进行通信,协同完成一个特定目标任务。(微服务架构也属于分布式应用架构)即将系统拆分成不同组件,独立部署,通过网络通信协同完成任务的架构都属于分布式架构。
这里顺带说下集群架构,集群是指在几个服务器上部署相同的应用程序来分担客户端的请求,它是同一个系统部署在不同的服务器上,好比 多个人一起做同样的事。分布式是指多个系统协同合作完成一个特定任务的系统,它是不同的系统部署在不同的服务器上,服务器之间相互调用,好比 多个人一起做不同的事。
如下(完整服务=商品服务+订单服务+支付服务):
而分布式架构为了容错,可以单个类型组件部署多个形成集群效应。
2.1. 优点
- 耦合度低:系统按不同业务模块来拆分开,使用接口通信,降低模块之间的耦合度。
- 扩展性好:各个模块责任清晰,修改方便,增加功能时只需要再增加一个子项目,调用其他系统的接口就可以。某个模块性能不足时,可以扩展部署多个节点,以满足不断增长的业务需求。
- 部署方便:模块独立,便于独立开发部署
- 高可靠性:可以通过多个节点共同工作,即使某些节点发生故障,整个系统仍然可以继续运行。
- 成本优势:因为可以分布式部署,在遇到性能问题时,可以横向扩展即部署多个一般硬件性能的节点,而不用只能纵向扩展昂贵的单机。
2.2. 缺点
- 数据一致性:在分布式环境下,保证数据的一致性、完整性和实时性通常要比单体架构更加复杂和挑战性。特别是分布式事务的问题。
- 系统间网络通信开销:模块间的网络通信会带来额外的开发和维护成本,同时也需要解决网络延迟或网络故障时如何正确的反应。
- 运维复杂:由于系统被拆分成多个服务,每个服务都需要进行配置、部署、监控和日志处理,增加了运维成本。故障发生时也会更加难以排查。
2.3. 适用场景
- 业务复杂数据量大:中大型项目通常伴随着复杂的业务逻辑和大数据处理,单体架构已经无法支撑需求,分布式应用能够提供足够的计算能力和灵活性。
- 高并发:在高并发场景下,系统有些环节就需要提升性能,而分布式应用恰好可以快速独立的扩展某个组件来满足需求。
- 分布式计算和存储:面对海量数据的计算,分布式计算性能远超单机,比如spark、flink等都是如今大数据计算的主流引擎。而对于海量数据的存储和查询,单机也无法解决,而hdfs/hbase、doris等则很好的满足需求。
3. 微服务架构
微服务就是通过将一个大型、复杂的应用解构为一系列小巧、简单的服务,每一个服务都可以独立于其他的进行部署和扩展,组合形成一个强大的系统整体。和传统单体服务的思想恰好相反。
传统单体=拆分多个微服务(微服务模块+暴露Http API接口)
这里有必要再和常说的SOA进行下比较,很多人人云亦云说SOA已过时微服务才是未来,这其实是没认识清楚而已。很多时候我们不要去公式化的定义一个架构,更重要的应该是理解该架构的思想,是为了解决什么问题而被提出来的。
SOA诞生的背景就是存在过于庞大、复杂、异构的企业级系统,这类系统的典型特征就是很多系统已经发展多年,采用不同的企业级技术,有的是内部开发的,有的是外部购买的,无法完全推倒重来或进行大规模的优化和重构,因为成本和影响太大。而上层应用又需要和这些系统交互,这时就需要SOA来兼容这些已存在的系统,旨在标准化所有服务之间相互交流和集成的方式,总结起来就是基于遗留系统已有可复用的能力,分层组装的方式来构建上层业务应用。对于SOA来说,重点不是ESB总线引擎,而是SOA参考架构思想。SOA架构思想里面虽然也有遗留系统的适配和集成,但是更加重要的是从传统的竖向应用构建思路转变为横向分层构建思路,同时抽取和识别可重用服务,通过服务组装来满足上层业务应用。而微服务更加适合于快速、轻量级、基于Web的互联网系统,这类系统业务变化快,需要快速尝试、快速交付;同时基本都是基于Web,虽然开发技术可能差异很大(例如,Java、C++、.NET等),但对外接口基本都是提供HTTP RESTful风格的接口。两者的共同点就是都提出服务化组件的概念。
3.1. 优点
- 易于扩展:微服务架构将应用程序划分为多个独立的服务单元,每个服务单元都可以独立部署和运行。这使得应用程序的扩展和升级更加方便,只需要对需要扩展或升级的服务单元进行修改,而不必对整个应用程序进行重构。
- 快速迭代和部署:微服务允许更快的开发周期和部署,促进敏捷性、创新和更快的上市时间。
- 故障隔离和弹性:促进故障隔离,确保系统的整体弹性。
- 技术栈灵活:每个服务单元都可以使用不同的编程语言、框架和技术栈来实现,这使得开发人员可以使用自己熟悉的技术栈,从而提高开发效率和代码质量。
- 可测试性强:每个服务单元都可以独立进行测试,有助于提高代码质量和系统的稳定性。
3.2. 缺点
- 运维难度高:当服务个数增多时,需要保证几十甚至几百个服务服务的正常运行与协作,这给运维带来了很大的挑战。
- 数据一致性:数据的一致性、完整性一直是分布式系统架构的一个挑战点。
- 网络问题:需要考虑网络异常对系统稳定性和正确性的影响。
3.3. 适用场景
- 复杂业务解构:对于业务逻辑复杂,模块众多的大型项目,微服务能够提供更清晰的业务边界和更容易管理的结构。
- 高效的开发迭代:微服务架构能够支持敏捷开发和持续集成/持续部署(CI/CD),从而实现快速迭代和优化。
- 多团队协作:适用于多团队协作的开发环境,每个团队可以独立开发和管理自己的微服务。
4. 插件架构
插件架构是一种将软件系统划分为核心组件和一系列可插拔插件的架构模式。
核心组件负责提供软件运行所需的基本功能,而各种功能扩展或特定于应用的功能则通过插件来实现,插件可以根据需求进行动态加载和卸载。
这些插件可以独立于核心组件进行开发、测试和部署,使得整个系统在保持稳定性的同时,能够方便地进行功能扩展和定制。
4.1. 优点
- 易于扩展:不用实现核心组件,扩展插件容易,考虑的东西更少。为第三方开发者提供了良好的接口,使得他们可以开发自己的插件来丰富软件功能,形成一个繁荣的应用生态。
- 功能隔离:插件之间没有关系,修改升级插件不怕对其他插件有影响。
- 可定制性高:根据个性化的需求需要什么插件,直接开发即可。
- 维护性好:插件是动态可插拔的,部署维护简单。
4.2. 缺点
- 核心组件扩展性差:核心组件不容易做成分布式的,在升级方面得要考虑和所有插件的兼容性问题
- 核心组件的开发难度高:核心组件的开发难度比较大,核心组件和插件模块之间的交互和通信需要精心设计,以确保系统的稳定性和可靠性。
4.3. 适用场景
- idea(集成开发环境):如Eclipse、IntelliJ IDEA等IDE都采用了插件架构,允许用户根据需要安装或卸载各种开发工具插件。
- 浏览器:现代浏览器如Chrome、Firefox等都支持插件(如扩展程序、脚本等),为用户提供丰富的浏览体验。
- 游戏引擎:如Unity、Unreal Engine等游戏引擎,通过插件架构支持开发者快速集成各种游戏功能。
- Datax:阿里的数据同步工具就是使用的插件架构。
5. 分层架构
分层架构将软件分成若干个水平层,每一层都有清晰的角色和分工,不需要知道其他层的细节。层与层之间通过接口通信。虽然没有明确约定,软件一定要分成多少层,但是四层的结构最常见:展现层、业务层、持久层和数据库层。
5.1. 优点
- 清晰易懂:分层架构使系统的结构和功能更加清晰,降低系统设计和开发的难度。
- 可维护性好:分层架构将系统划分为独立的层,每层负责特定的功能,当修改某层的代码时,耦合度降低,减少对其他层的影响。
- 可重用性:每一层都可以独立于其他层进行重用,简化复杂系统的开发,促进代码和设计的重用。
- 容易测试:每一层都可以独立测试,其他层的接口通过模拟解决。
5.2. 缺点
- 性能损耗:分层架构可能导致性能上的损耗。由于数据需要在不同层之间进行传递和处理,这可能会增加数据传输的开销和延迟。特别是在处理大量数据时,这种性能损耗可能更加明显。
- 容易引发过度分层设计:对于小程序应用不太适合
5.3. 适用场景
- web应用:最经典的应用场景。在Web开发中,MVC(Model-View-Controller)分层结构是一种常见的软件开发方法。它将应用程序划分为模型层、视图层和控制器层,使得每层可以专注于处理特定的任务,提高了Web应用的可维护性和可扩展性。
- 网络协议栈:例如TCP/IP协议栈,它明确分为物理层、网络层、传输层和应用层,每层处理特定的通信任务。这种分层设计使得每层可以独立地处理其任务,提高了网络协议的可扩展性和可维护性。
- 企业级应用:企业级应用通常需要处理复杂的业务逻辑和大量的数据交互。分层架构可以将这些功能划分为不同的层次,如表现层、业务逻辑层和数据访问层,使得每层专注于自己的功能实现,提高了系统的灵活性和可维护性。
- 需要快速构建的新应用程序:对于需要快速构建的应用程序,分层架构可以帮助开发者快速划分任务,定义清晰的接口和交互方式,从而加速开发进程。
6. 客户端-服务端架构(CS架构)
CS架构将软件划分为客户端和服务器两部分,客户端负责向服务器发送请求,并接收服务器返回的响应。服务器则负责处理客户端的请求,并返回相应的结果。
6.1. 优点
- 性能好:CS架构能够充分发挥客户端PC的处理能力,很多工作可以在客户端处理后再提交给服务器,因此客户端响应速度快
- 安全性高:CS架构一般面向相对固定的用户群,程序更加注重流程,可以对权限进行多层次校验,提供更安全的存取模式,对信息安全的控制能力很强。因此,高度机密的信息系统采用C/S结构适宜。
- 可扩展性、可靠性高:客户端和服务器可以分别独立地进行升级和扩展,提高了系统的可扩展性。同时,客户端和服务器可以独立运行,当一个出现故障时,不会影响到整个系统的稳定性。
- 灵活性高:CS架构可以根据不同的应用需求选择不同的客户端,可以充分满足客户自身的个性化要求。
6.2. 缺点
- 开发维护成本高:因为涉及客户端种类较多,在升级时要考虑兼容性
6.3. 适用场景
- 大型网络应用程序:CS架构常用于构建如Web应用程序、电子邮件系统、数据库管理系统等大型网络应用程序。在这些场景中,客户端和服务器之间的明确分工使得系统能够高效地处理大量用户请求和数据。
- 企业内部应用:在企业内部网络中,CS架构被广泛应用于各种业务应用,如企业资源规划(ERP)、客户关系管理(CRM)等。这些应用通常需要处理大量的业务逻辑和数据操作,CS架构的分工明确和可扩展性使得它们成为理想的选择。
- 实时性要求较高的场景:对于需要实时响应的场景,如在线游戏、实时监控系统等,CS架构能够提供较低的延迟和较高的交互性,确保用户获得流畅的体验。
- 多平台支持:由于CS架构的客户端独立于服务器,可以灵活地设计和开发不同平台的客户端应用,如桌面应用程序、移动应用程序等。这使得CS架构适用于需要跨平台支持的场景。
7. 管道和过滤器架构
管道过滤器架构是一种基于数据流的处理模型,它将整个数据处理过程划分为一系列独立的处理单元,每个处理单元称为“过滤器”,负责执行特定的数据处理任务。这些过滤器之间通过“管道”相连,形成一条数据处理的流水线。数据从输入端开始,依次经过各个过滤器进行处理,最终从输出端流出。
在这种架构中,每个过滤器都有一组输入和一组输出。它们从输入端接收输入数据流,经过内部处理后,按照标准顺序将结果数据流送到输出端,以传递完整的计算结果实例。
7.1. 优点
- 松散耦合:过滤器之间通过管道连接,降低了不同模块之间的耦合性。这种松散耦合的方式使得系统更加灵活,可以方便地添加、删除或修改过滤器,以适应不同的数据处理需求。
- 高可扩展性:由于每个过滤器都是独立的模块,因此可以很容易地扩展和修改系统。只需要添加新的过滤器或者修改已有过滤器的实现,就可以实现新的数据处理需求。
- 支持并发执行:每个过滤器可以作为一个单独的任务执行,因此可以与其他过滤器并发执行。这种并行处理的方式可以显著提高数据处理的速度和效率。
- 良好的隐蔽性和内聚性:过滤器内部实现细节被隐藏,只暴露必要的接口,使得整个系统更加健壮和易于维护。同时,每个过滤器专注于完成特定的数据处理任务,具有高内聚性。
7.2. 缺点
- 交互性差:管道过滤器架构通常更适用于批处理或数据流处理场景,而不是需要频繁用户交互的应用。
- 处理效率问题:由于每个过滤器都需要等待其前一个过滤器完成处理后才能开始工作,这可能导致整个处理流程的延迟。特别是在某个过滤器处理速度较慢或存在性能瓶颈时,整个系统的性能都可能受到影响。
7.3. 适用场景
管道过滤器架构适用场景广泛,尤其在需要连续处理数据流的环境中具有显著优势。
- 信号处理:在音频或视频处理系统中,管道过滤器架构被广泛应用于逐步处理信号。例如,通过一系列过滤器实现去噪、编码和解码等功能,确保信号质量并满足特定的处理需求。
- 数据分析与转换:在数据科学和大数据分析领域,管道过滤器架构同样发挥着重要作用。通过多个处理步骤,可以清洗、转换并分析数据,从而提取有价值的信息并辅助决策。
- 编译器设计:编译器通常采用管道过滤器风格,将源代码编译为机器代码。通过词法分析、语法分析、语义分析和代码生成等过程,确保代码的正确性和效率。
- 生物信息学数据分析:在生物信息学领域,管道过滤器架构被用于执行基因序列的读取、过滤、映射和统计分析等任务。每个步骤都由不同的过滤器处理,最终产生可用于科学研究的数据。
- Flink和Spark:数据流处理框架就是使用这种架构方式。
8. 事件驱动架构
事件驱动架构由生成事件流的事件生成者和侦听事件的事件使用者组成,两者之间通过事件来交互。生成者脱离使用者,即生成者不知道哪个使用者正在倾听,使用者之间也能彼此脱离,一切的关注点只是事件。
事件驱动架构模式包含了两种主要的拓扑结构:中介(mediator)拓扑结构和代理(broker)拓扑结构。 mediator 拓扑结构通常在你需要在事件内使用一个核心中介分配、协调多个步骤间的关系、执行顺序时使用;而代理拓扑结构则在你想要不通过一个核心中介将多个事件串联在一起时使用。
这里说明下中介的模式:
1.架构组件
1)事件队列 (event queue)
负责:接收事件的入口。
2)分发器(event mediator)
负责:将不同的事件分发到不同的业务逻辑单元。是一个事件中枢处理单元,知道事件的处理流程,但不执行具体的事件业务处理逻辑,根据事件的特征对初始事件进行拆分编排为处理事件并进行分发。
3)事件通道(event channel)
负责:分发器与处理器之间的联系渠道。是一组各自独立的组件,彼此之间没有依赖,自包含,不依赖于其他 Processor 的处理结果
4)事件处理器 (event processor)
负责:实现业务逻辑,处理完成后会发出事件,触发下一步操作。
2.架构流程
1)客户端发送一个事件到事件队列event queues中,它用来将事件传送给event mediator;
2)Event mediator收到初始的事件后,会发送额外的一些异步事件给event channels来执行处理的每个步骤:
3)Event channels 既可以是消息队列,也可以是消息topic,大部分是消息topic,这样可以由多个消息处理器(eventprocesson)处理同一个消息。
4)Event processors监听event channels,接收事件并处理一些业务逻辑.
8.1. 优点
- 松耦合与独立性:在事件驱动架构中,组件之间通过事件进行通信,无需直接交互。
- 高可扩展性:事件驱动架构可以轻松地添加或删除组件,因为组件只需要订阅或取消订阅相关的事件。这种设计使得系统能够轻松地适应业务变化,满足不断增长的需求。
- 实时响应:由于事件驱动架构采用异步通信方式,系统可以实时响应各种事件。这使得系统能够及时处理用户请求、系统异常等情况,提高了系统的响应速度和用户体验。
- 容错性和可恢复性:事件驱动架构中的组件相互独立,当某个组件发生故障时,不会影响整个系统的正常运行。此外,通过合理的设计和使用适当的消息队列等机制,可以实现事件的持久化和重放,从而提高系统的容错性和可恢复性。
8.2. 缺点
- 编程模式复杂性:事件驱动架构编程模式更为复杂,设计耗费时间会更久。
- 系统复杂度和开发难度增加:事件驱动架构通过引入中间层来实现事件发布-订阅机制进行组件解耦,这虽然带来了一些优势,但同时也增加了系统的复杂度。这可能导致开发难度和维护难度的增加,因为开发者需要理解和处理大量的异步事件。
- 事件处理顺序问题:在事件数量众多的情况下,容易在“事件丛林”中迷失方向,可能会遇到中断风暴、惊群效应等问题。这可能导致某些事件的处理顺序混乱,从而影响系统的稳定性和可靠性。
8.3. 适用场景
- 物联网(IoT):在物联网领域,大量的传感器和设备可以通过事件驱动架构进行数据的采集和处理。当传感器检测到某个事件时,会发布相应的事件消息,由事件处理程序进行处理,如控制设备的运行状态、发送警报等。
- 异步通信和解耦:当系统中的组件或服务需要进行松耦合的交互时,事件驱动架构可以实现消息的发布和订阅,实现异步的、解耦的通信模式。
- 实时数据处理和流式计算:通过将事件作为数据流进行处理,事件驱动架构适用于实时数据处理和流式计算场景,如实时数据分析、监控和决策。
- 复杂业务流程和协作:对于复杂的业务流程和协作场景,事件驱动架构可以提供更灵活、可扩展的解决方案。通过将业务操作和状态变化建模为事件,可以实现业务流程的自动化和协作的分布式执行。
9. Serverless架构
这里讲的就是使用云服务,典型的比如亚马逊AWS、阿里云等。通过部署在云平台上,Serverless架构能够让开发者更加专注于业务逻辑的开发,而无需关心底层的运维工作。云平台不仅负责服务器的运行和维护,还能为应用提供弹性的资源扩展。当然也会带来一系列问题:高昂的成本、网络延迟、和产商高度绑定等问题。
个人认为比较适合给试错的小型初创团队使用,对于大型应用来说,成本是一个非常大的问题。