架构设计风格
What:主流软件架构风格-数据流、调用返回、独立构件、虚拟机、仓库
Why:风格影响架构质量和实现效率
How:理论结合面试题实战
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 graph LR A[软件架构风格] -->B(数据流风格) A --> C(调用返回风格) A --> D(独立构件风格) A --> E(虚拟机风格) A --> F(仓库风格) B --> B1(批处理序列) B --> B2(管道过滤器) C --> C1(主程序子程序) C --> C2(面向对象) C --> C3(层次结构) D --> D1(进程通信) D --> D2(事件驱动) E --> E1(解释器) E --> E2(规则系统) F --> F1(数据库系统) F --> F2(黑板系统) F --> F3(超文本系统)
数据流风格 批处理序列 批处理风格通常会由总体协调安排批处理过程,保证其每一步处理都是独立的,并且顺序执行。具体来看有以下特点:
强时间顺序: 只有当前一步的计算任务处理完成后,后一步处理才能开始。计算任务前后顺序明确
强完整性:数据传送在计算单元之间通过指定的数据交互方式传递。每一步要确保数据完整,才可以向下一步发起数据传送。
强控制力度:有独立的顺序控制和时间把控机制,并辅以数据检查等功能。
批处理序列,作为常见的架构风格,案例很多:
传统定制批处理任务: 比如银行的夜间批量结算和大小额清算,券商的夜间交易结算和证券系统对账等。特点是通常运行在指定时间,数据流庞大,每一步有精确的数据处理要求和校验机制,顺序逻辑清晰。
Hadoop大数据处理: Hadoop在处理过程中有明确的步骤安排,比如map几次,shuffle几次,再reduce完成数据处理。
Apache Beam大数据处理: 当前比较火的批量处理工具是Apache Beam。虽然它同时支持批处理和流处理,但是在日常使用中其批处理的优势更加明显。它定义类专门的数据集计算过程、管道和执行器。能够形成有向无环图,来保证数据流的方向和结果输出。
管道过滤器 管道过滤器风格,由管道和过滤器两部分组成。
过滤器:是其中的核心构件,负责业务的处理。它从用户或者上游管道获得输入数据,进行数据的变换及增量计算,处理完成后,通过下游管道传递给另一个过滤器。过滤器是独立的实体,它不能与其他的过滤器共享数据,而且一个过滤器不知道它上游和下游的其他过滤器信息。
管道: 是一种数据传输途径。可以是Unix/Linux操作系统的管道文件,也可以是消息队列,只要能确保数据的先进先出,单向进出就可以了
管道-过滤器的经典案例也很多,比如:
编译器: 在编译器系统中,一个阶段(包括词法分析、语法分析、语义分析和代码生成)的输出是另一个阶段的输入,处理阶段是是以数据流进行编译过程驱动流转的。
操作系统管道过程: 比如经典的Linux命令ps -ef | grep java,就是在系统中检查java进程信息,其中的ps -ef和grep java就是两个过滤器,各自处理相关流程步骤,中间的|标识,就是管道,负责在两个过滤器之间进行有向传输。
Streaming流处理: 比如经典的Spark Streaming、Storm、Apache Flink、 Kafka Streams等流式处理框架,或者是完整的流数据管道式处理方式,或者是将数据流进行微小的窗口切分,再采用超小批量处理方式进行数据处理和向后传递。这些技术整体来看,都属于管道-过滤器架构风格。
数据流风格总结 数据流的两种子风格的相似点如下:
解耦: 将每个阶段的处理过程进行了隔离,使得软件构件具有良好的隐蔽性和高内聚、低耦合的特点; 每个批处理过程或者过滤器独立管理,可以方便地进行替换。
复用: 支持软件重用,只要提供适合数据处理的需求,任何两个批处理过程和过滤器都可有序被连接起来。
高吞吐: 数据流风格在5大风格中是最适合大数据的架构风格。它可以完成各种大量数据互通、传递、处理的过程。
同时,批处理序列风格与管道过滤器风格的不同点也很多:
计划性: 批处理通常由时间规划和任务调度统筹安排,而管道过滤器是递增式处理过程是由数据驱动的处理流程
敏捷性: 批处理需要完成前序任务,再进行后续任务,通常整个任务处理周期较长,通常以分钟、小时、天为单位,管道过滤器在传输过程中没有整体处理的概念,可以快速将-份小的数据变动流过相关的过滤器和管道,实现秒级、分钟级的快速响应。
调用返回风格 主程序/子程序 主程序子程序风格是面向过程的经典架构风格。一般采用单线程控制,把问题划分为若干处理步骤,分别由主程序和子程序完成。主程序调用子程序,子程序将调用结果返回给主程序。同时,子程序通常也可以合成为模块,增加调用过程的层次性。主程序最终结果的正确性,取决于其下属的模块和子程序的执行结果。
这一风格基本上涵盖了所有面向过程的开发模式,作为程序开发的最经典模式,被普遍使用。主要特点:
简单明了: 符合传统的商业行为过程: 浏览->添加购物车->购买->支付->收货->评价等
架构清晰: 可以和程序流图、泳道图、状态机模型等架构图一一对应,方便开发和验证这一风格基本上涵盖了所有面向过程的开发模式,作为程序开发的最经典模式,被普遍使用。
面向对象风格 这种风格是主程序子程席风格的进化,它随时面向对象语言的产生而同步出现。它将数据的表示方法和它们的相应操作封装在一个抽象数据类型或对象中。由对象来负责保持资源的完整性(成员变量)和程序之间的过程调用关系 (方法)。
这一风格基本上涵盖了所有面向对象的开发模式,是高级语言程序开发的最经典模式。
主要特点,非常鲜明:
完整性:每个对象独立负责维护其本身的完整性,比主程序子程序的紧耦合方式,更容易实现应用体完整性
隐蔽性: 对象的表示对其他对象而言是隐蔽的,对象可以不影响它的客户就能改变其实现方法。
面向对象编程的优势:可以充分利用高级语言的优势来实现封装、聚合、继承、接口、多态、依赖、抽象、复用等特质。和现实生活中的实体逻辑可以一一映射地进行实现。
层次结构风格 分层是软件架构设计的主流方法之一,将应用设计成一个层次系统,每一层为上层服务,并作为下层客户。每一层最多只影响上下两层,同时允许每层可以用不同的方法来实现应用逻辑和功能。这对于解决软件的复杂性和重用性,提供了强大的支持。
经典模式比如:
OSI网络7层模型,TCP/IP网络4层模型:确保每一层可以采用不同的技术栈和设计思路,所有数据会根据网络层次结构进行数据包的封装,不会出现层次的跳跃现象。
操作系统内核和用户态管理: 操作系统从核心的内核层,到外围的工具、用户系统,类似一个洋葱模型,所有的过程调用只在相邻两层之间进行。
应用分层模型:比如MVC三层模型、领域驱动4层模型等。我们将在后续的领域驱动章节详细介绍4层领域模型。可以想见,层次结构风格极大化地抽象了软件架构,摆脱了编程语言的限制。其他如C/S、B/S、SOA应用架构等,横跨了软件、系统和网络范畴。但它们有一个共同点,都采用了层次化的描述方式,所以可以看成是层次结构风格的延伸。
主要特点:
隐藏复杂性:每一层可以独立设计、开发,只要满足和上下层的接口定义即可。同一层可以实现架构重用和借鉴,从整体上将应用实现了分层解耦。
邻居互动性:每一层至多和相邻的上下层交互,因此功能的改变最多影响相邻的上下层。
调用返回风格总结
调用返回风格是5大架构风格中最润物细无声的一种。它几平自然而然地被运用在了所有开发设计过程中:
在面向过程的开发中,通常都采用了主程序/子程序风格
在面向对象的开发中,几乎都是用了面向对象风格
在应用的分层设计中,几乎都采用了层次结构风格
它们组合起来,真正实现了软件构件的解耦和互动。
独立构件风格 进程通信 构件之间通过独立的进程来实现消息传递。比较经典的例子包括:
应用之间的RPC调用: 通常采用同步或异步方式,远程调用其他模块的接口程序。
应用之间的RestAPl调用: 通过规定的消息传输机制(REST接口规范)来实现同步或异步方式的进程间通信。
点对点通信: 比如像区块链、BitTorrent等的点对点通信,也是进程通信风格的延伸
主要特点:
目标明确: 远程通信具有清晰的指向性,目标明确0。
同步为主: 通常以同步调用为主,辅以异步交互式通信方式。
事件驱动系统 事件驱动系统风格是基于事件的隐式调用风格,构件不直接调用一个过程,而是触发或广播一个或多个事件。后续执行过程会被注册在一或多个事件,当对应的事件被触发或者广播时,系统会自动调用该事件中注册的过程,执行相应的模块功能支持基于事件的隐式调用的应用系统很多:
调试器: 在IDE工具中设置断点,当触发断点后,IDE工具处理程序在断点处停下,变量监视器自动刷新变量数值。整个过程IDE工具和调试模块之间没有直接的进程通信,而是采用事件驱动的机制实现过程调用。
消息队列: 消息队列通常用于应用间的通信和业务流的峰填谷,当消息被发送到消息队列后,对应的消息监听应用会自动消费该消息,并进行相应数据和业务处理操作。整个过程中消息的生产者和消费者之间没有直接的互动和了解,完全由消息队列来驱动数据流的指向。
事件驱动设计: 事件驱动设计(Event Driven Architecture)是当今很火的话题,结合CQRS读写分离等技术,可以实现完整的业务分解和设计。我们会在后续的领域驱动设计章节来详细讨论事件驱动系统风格。
事件驱动系统风格的主要特点:
隐式调用,匿名互动:事件的触发者并不知道哪些构件会被这些事件影响。这样不能假定构件的处理顺序,甚至不知道哪些过程会被调用,体现了极强的低耦合性。
广播机制: 通常事件驱动的接受者不止一个,会采用广播方式进行信息传输,方便实现一对多的过程调用和应用交。
独立构件风格总结
独立构件风格是5大架构风格中,最偏重沟通的一种风格。它描述了在一个应用系统中,各个构件是如何进行通信的:
可以是点对点的、指定方向的进程通信风格
也可以是广播的、隐式调用的事件驱动系统风格
他们组合起来,真正实现了进程与进程、模块与模块、系统与系统间的互动。
虚拟机风格 解释器 解释器通常包括:完成解释工作的解释引擎,被解释代码的存储区、记录解释警当前工作状态的数据结构、记录源代码被解释执行进度的数据结构等。
解释器可以仿真硬件的执行过程和一些关键应用,通常被用来弥合程序语义与硬件语义之间的差异。其缺点是执行效率较低。
比较经典的例子包括:
编程语言解释器: 如Java语言解释器JVM。它负责Java语言的解释和虚拟机运行环境。
容器运行解释器:像Docker Daemon等容器运行环境,也可以理解为容器的解释器和虚拟机,完成了自定义的容器内应用的解释和管理。
CAD仿真环境: 电路前端后端仿真运行环境,负责解释电路设计程序,并提供运行仿真环境。
专家系统:基于经验的大数据推理系统。将专家推理逻辑和程序,转换成决策平台的解释系统。
主要特点:
虚拟环境: 提供虚拟运行环境
程序解释: 解释程序代码、运行状态等
基于规则的系统 基于规则的系统包括规则集、规则解释器、规则/数据选择器及工作内存等。
比较经典的例子如:
业务规则引擎:像Drools开源规则引擎、IBM iLog商业规则引擎,都是业务人员的好伙伴。业务人员不能像程序员一样精通if/else逻辑开发,但是又需要可以随时进行业务逻辑的修改和优化。业务规则引擎提供了有效的途径,它可以采用图形化的方式,让业务人员拖拖拉拉地指定业务逻辑。比如优惠券的计算逻辑、产品的价格制定逻辑、仓储系统的内部流转逻辑等。
大数据分析引擎: 大数据分析通常满足82原则,80%的数据分析仍然是有规律可循,可以采用一定的规则引擎来处理,另外的20%数据才需要A人工智能的强大分能力来完成。在规则化的处理过程中,通常数据科学家不会直接编程来完成逻辑规则的指定,所以大数据环境,分析规则引擎也被广泛使用,来协助数据工程和数据分析。
网络防护系统: 比如WAF应用防火墙、机器人识别防护、IDS/IPS入侵检测和防御,通常都依赖于规则的设定
运维自动化: 在IT运维和数据中心运维中,越来越多的采用了规则类的工具和系统来实现自动化。
基于规则引擎的系统的主要特点:
规则决策:规则的细节被引擎所解析,来决定业务、监控等策略和措施的制定。
人工智能:简化人工智能、加速自动化和逻辑处理
虚拟机风格总结
虚拟机风格是5大架构风格中,最偏重运行环境的一种风格。它描述了在一个应用系统中,程序代码是如何被解释和用于决策的:
虚拟机方式提供解释引擎和中间数据存储过程
规则引擎来匹配和解释规则集,指定最终决策
它们组合起来,真正实现了程序产生智能,IT掌控世界。
仓库风格 数据库系统 数据库架构是仓库风格最常见的形式,所有的关系型和非关系型数据库的使用都可以归为这一风格。它有一个中央数据库或者数据仓库,作为共享数据源,保存当前系统的数据状态:大量的分布式和不同业务逻辑的系统,作为独立处理元素,对数据元素进行操作。
主要特点:
共享数据源:集中式的共享数据库
独立处理单元:分布式的独立处理节点
超文本系统 超文本系统风格主要是用于共享静态网页
比较经典的例子如:
CMS内容管理系统:保存有JavaScript、CSS、HTML等静态网页,用于让不同领域的前端节点来共享地访问静态页面元素和框架。
分布式文件互通: 节点各自存储部分文档,通过节点跳跃、网状链接等方式共享静态文件。
主要特点:
多种共享形式:超文本系统可以是集中式的文件资源方式,也可以是网状互通的分布式资源共享方式。
非结构化文件: 适合管理非结构化文件,如静态文件、对象存储等。
黑板 黑板是所有软件架构风格里最复杂的一套风格。通常只在特定领域使用,比如语音识别、模式识别、信号处理等。黑板系统是一种问题求解模型。以语音识别为例,通常一段语音的识别没有必然正确的最优解,只有根据现有知识和模型的匹配近似解。将原有问题通过变换、分割等方式转换为多个子问题,并将原始数据也相应地转换为高级数据结构。1000个人心中有1000个哈姆雷特,同样地,1000个专家(或专家系统)也会有1000个不同的子问题解。用一个黑板,让这些专家将已经获得的信息、已经处理完的数据、已经完成的子问题都写到同一个黑板上。其他专家可以通过这个共享的里板的数据变更,很快地作出反应,优化自己手上的子问题计算,这个黑板,就是用于记录组织推理步骤、控制状态数据和问题求解之领域知识的框架。它将问题的解空间组织成一个或多个应用相关的分级结构。这些分级结构将由不同的专家(系统),通过不同知识表达方法、推理框架和控制机制的组合来形成各自的知识源。知识源之间没有直接的数据传输,所有交互都通过共享的黑板的数据更新来完成。
主要特点:
分布式知识源:不同的子问题采用不同的数据集、推理框架和控制机制,生产分布式的知识源。
集中式的数据共享:通过黑板这个集中式逻辑系统完成所有知识源的数据共享。
集中式控制: 通过黑板的数据更新,通知各数据源,从而驱动分布式计算的进行。
它们组合起来,真正实现了分布式世界中数据的存储和共享。