《微服务架构设计模式》第二章

news2025/1/21 22:01:04

文章目录

  • 微服务架构是什么
    • 软件架构是什么
      • 软件架构的定义
      • 软件架构的4+1视图模型
      • 为什么架构如此重要
    • 什么是架构风格
      • 分层式架构风格
      • 六边形架构风格
      • 微服务架构风格
  • 为应用程序定义微服务架构
    • 识别操作系统
    • 根据业务能力进行拆分
    • 根据子域进行拆分
    • 拆分指导原则
      • 单一职责原则(SRP)
      • 闭包原则(CCP)
    • 拆分单体服务的痛点
    • 定义服务API
      • 把系统操作分配给服务
      • 确定支持服务协作所需要的API
  • 小结

微服务架构是什么

软件架构是什么

软件架构的定义

先看一下大佬是怎么说的:
计算机系统的软件架构是构建这个系统所需要的一组结构,包括软件元素、它们之间的关系以及两者的属性。
–Bass等著《Documenting Software Architectures:Views and Beyond》

这个定义将软件分解为元素和元素之间的关系两个部分,就像一辆汽车可以分为发动机、底盘、轮胎等元素,同时各个元素之间还存在关系,需要互相交互。这样分解有以下两个原因:

  1. 它促进了劳动和知识的分工。不同的团队可以高效系统工作。
  2. 它定义了软件之间的交互方式

软件架构的4+1视图模型

从4个不同的视角来看一个软件的价架构:
在这里插入图片描述

  1. 逻辑视图:由开发人员创建的软件元素,在面向对象的语言中,这些元素就是类和包,他们之间关系就是继承、关联、依赖等。
  2. 实现视图:由构建编译系统创建,元素就是模块和可执行文件。在Java中,模块就是JAR文件,组件通常是WAR文件或者可执行的JAR文件。他们之间的关系就是模块之间的依赖关系以及组件和模块之间的组合关系。
  3. 进程视图:运行时的组件。每个元素都是一个进程,进程之间的关系进程间的通信。
  4. 部署视图:进程如何映射到机器。元素是机器,机器之间的关系带来网络。

除了这四个视图以外,4+1中的+1是指场景,它负责把视图串联在一起。每个场景负责描述在一个视图中的多个架构元素如何协作,以完成一个请求。例如,在逻辑视图中的场景,展现了类是如何协作的。同样,在进程视图中的场景,展现了进程是如何协作的。

为什么架构如此重要

应用程序有两个层面的需求:

  • 功能性需求:这些需求决定了程序可以提供哪些功能。这些功能和应用的架构没有任何关系,只要能实现功能就行,用哪种架构都可以。
  • 非功能性需求:可以称之为质量属性需求,它决定了程序运行时的质量,可扩展性、可靠性。也决定了开发阶段的质量,包含可维护性、可测试性、可扩展性、可部署性。为应用程序选择的架构决定了这些质量属性。

其实说的就是我们在完成一个需求的时候,除了实现功能以外,还要考虑实现的方式是不是能可扩展等等。实现方式不合适,项目时间长了以后,会变得复杂,这时候就需要治理,就是这个原因。

什么是架构风格

同样先来看看大佬怎么说:
因此,架构风格根据结构组织模式定义了一系列此类系统。更具体地说,架构风格确定可以在该风格的实例中使用的组件和连接器的词汇表,以及关于如何组合它们的一组约束。

太抽象了。。不必深究,先来看看具体的几种架构风格:

分层式架构风格

  • 表现层:包含对外提供的API接口
  • 业务逻辑层:包含业务逻辑
  • 数据持久层:实现与数据库交互逻辑

弊端:
-
单一表现层:无法展现应用程序可能不仅由单个系统调用的事实。

  • 单一数据持久化层:它无法展现应用程序可能与多个数据库进行交互的事实。
  • 将业务逻辑层定义为依赖于数据持久化层:理论上,这样的依赖性会妨碍你在没有数据库的情况下测试业务逻辑。

这几个弊端貌似都影响不大??

六边形架构风格

待补充

微服务架构风格

待补充

为应用程序定义微服务架构

如何定义一个微服务架构呢?文章中介绍了一个三部式流,世界上没有一个完美的机械化方法可以遵循,这个也只是大概方法, 现实中还需要不断的迭代。

  1. 定义系统操作
    根据功能性需求文档,定义系统可以提供的操作。如FTGO中,顾客需要下单,那么系统就需要提供需要提供让顾客下单的操作;而商家需要接单,那么商家还需要提供给可以让接单的操作。
  2. 定义服务
    这里说的就是如何分解服务。有几种策略可供选择。一种源于业务架构学派的策略是定义与业务能力相对应的服务。另一种策略是围绕领域驱动设计的子域来分解和设计服务。但这些策略的最终结果都是围绕业务概念而非技术概念分解和设计的服务。什么是子域?简单来说,一个子域是的领域Domain的子部分。无论公司的规模如何,每个领域都可以划分为子域,通过这样做,我们将公司领域的整个复杂性划分为更小的部分,我们将拥有能够很好地理解业务方面的领域专家,因为它是一个特定的子域。
  3. 定义服务API和协作方式
    定义应用程序架构的第三步是确定每个服务的API。为此,你将第一步中标识的每个系统操作分配给服务。服务可以完全独立地实现操作。或者,它可能需要与其他服务协作。在这种情况下,你可以确定服务的协作方式,这通常需要服务来支持其他操作。你还需要确定选用第3章中描述的哪种进程间通信机制来实现每个服务的API。

识别操作系统

待补充

根据业务能力进行拆分

待补充

根据子域进行拆分

待补充

拆分指导原则

单一职责原则(SRP)

改变一个类应该只有一个理由。-Robert C.Martin

如果一个类承载了多个职责,并且互相之间的修改是独立的,那么这个类就会变得非常不稳定。所以定义的每一个类都应该只有一个职责,因此也就只有一个理由对它进行修改。我们在设计微服务架构时也应该遵循SRP 原则,设计小的、内聚的、仅仅含有单一职责的服务。这会缩小服务的大小并提升它的稳定性。新的FTGO架构是应用SRP的一个例子为客户获取餐食的每一个方面(订单获取、订单准备、送餐等) 都由一个单一的服务承载。其实这个原则在实现类的每个方法时,每个类时,也都会用到。

闭包原则(CCP)

在包中包含的所有类应该是对同类的变化的一个集合,也就是说,如果对包做出修改,需要调整的类应该都在这个包之内。-Robert C.Martin
闭包原则就是如果一个类的修改另一个类也必须修改,那么就要把他们两个放到一个包里,这里做目的是当业务规则发生变化时,开发者只需要对一个包做出修改,可以极大改成程序的可维护性。同样我们可以把它应用到拆分服务中,如果一个服务变化会影响到另一个服务,我们就把这两个服务放在一个组件中,这样做可以控制服务数量(防止拆分出的服务数量过多),变更和部署也更容易。理想情况下,一个变更只会影响一个团队和一个服务。CCP有效解决分布式单体的反模式法宝。

拆分单体服务的痛点

  1. 网络延迟
    分布式系统网络延迟是分布式系统中一直存在的问题。、服务的特定分解会导致两个服务之间的大量往返调用。有时我们可以通过实施批处理 API在一次往返中获取多个对象,从而将延迟减少到可接受的数量。但在其他情况下,解决方案是把多个相关的服务组合在一起,用编程语言的函数调用替换昂贵的进程间通信。就是把多个相关的服务写成一个,本地调用肯定要比进程间通信要快。
  2. 同步进程间通信导致可用性降低
    A服务要调用B服务,如果二者是同步调用,B服务不可用了或者是挂了,那么A服务部分功能可能就不能用了。但是在第3章中学习异步消息之后,你就会发现其实有更好的办法来消除这类同步调用产生的紧耦合并提升可用性。
  3. 在服务之间维持数据一致性
    对于一些系统操作,可能需要同时更新多个模块的数据。如电商系统中,用户下单操作需要调用订单管理模块的方法,新增一条订单到数据库,同时需要调用库存模块的方法,锁定一个商品库存,更新库存数量。还需要调用支付模块的方法,新增一条支付记录,状态为待支付。如果用户在规定时间内支付了,需要更新库存-1,订单状态改为已支付等。如果用户未在规定时间内支付,锁定的库存需要释放,订单状态改为已取消,支付状态改为支付超时等 。这个系统操作所涉及到的订单、支付、库存等操作,需要保证原子性。要么全部成功,要么全部失败。假如支付成功了,库存扣减失败了,那是不行的。如果是在单体系统中,可以操作属于一个本地事务,我们可以通过数据库的事务来保证。但是在微服务架构中,订单、库存、支付分属于三个服务,每个服务有有对应的数据库,要保证一致性,就需要分布式事务。传统的解决方案是使用基于两阶段提交(two phase commit)的分布式事务管理机制。
    书中作者没有对两阶段提交详细介绍,想了解可以参考这篇文章:链接
    但是作者提到了使用一种非常不同的方法来处理事务管理,这就是Saga。Saga 是一系列使用消息协作的本地事务。Saga 比传统的ACID 事更复杂,但它们在许多情况下都能工作得很好。Saga 的一个限制是它们最终是一致的。如果你需要以原子方式更新某些数据,那么它必须位于单个服务中,这可能是分解的障碍。后边章节会详细讲。
  4. 获取一致的数据视图
    分解的另一个障碍是无法跨多个数据库获得真正一致的数据视图。在单体应用程序中,ACID 事务的属性保证查询将返回数据库的一致视图。相反,在微服务架构中,即使每个服务的数据库是一致的,你也无法获得全局一致的数据视图。如果你需要一些数据的一致视图,那么它必须驻留在单个服务中,这也是服务分解所面临的问题。幸运的是,在实践中这很少带来真正的问题。
  5. 上帝类阻碍了拆分

定义服务API

把系统操作分配给服务

第一步是确定哪个服务是请求的初始入口点。许多系统操作可以清晰地映射到服务(如创建订单很明显是订单服务),但有时映射会不太明显。例如,考虑使用noteUpdatedLocation()操作来更新送餐员的位置。一方面,因为它与送餐员有关,所以应该将此操作分配给 Courier Service。另一方面,它是需要送餐地点的 Delivery Service。在这种情况下,将操作分配给需要操作所提供信息的服务是更好的选择(说的很绕啊??)。在其他情况下,将操作分配给具有处理它所需信息的服务可能是有意义的。如处理findAvailableRestaurants()这个操作,需要从RestaurantService服务查信息,所以就把这个操作分配到这个服务。在这里插入图片描述

确定支持服务协作所需要的API

把操作分配给服务后,下一步是确定在处理每一个系统操作时,服务之间如何交互。
某些系统操作完全由单个服务处理。例如,在FTGO应用程序中,ConsumerService完全独立地处理 createconsumer()操作。但是,某些系统操作跨越多个服务,处理这些请求之一所需的数据可能分散在多个服务周围。例如createOrder()操作,orderService必须调用以下服务以验证其前置条件并使后置条件成立:
Consumer Service:验证消费者是否可以下订单并获取其付款信息。
Restaurant Service:验证订单行项目,验证送货地址和时间是否在餐厅的服区域内,验证订单最低要求,并获得订单行项目的价格
Kitchen Service:创建Ticket(后厨工单)
AccountingService:授权消费者的信用卡
为了完整定义服务API,你需要分析每个系统操作并确定所需的协作。其实到这一步,就是具体问题,具体分析了。

小结

1.架构决定了软件的各种非功能性因素,比如可维护性、可测试性、可部署性和可扩展性,它们会直接影响开发速度。这也是软件架构重要的原因
2. 微服务架构是一种架构风格,它给应用程序带来了更高的可维护性、可测试性、可部署性和可扩展性。
3. 微服务中的服务是根据业务需求进行组织的,按照业务能力或者子域,而不是技术上的考量。
4. 有两种分解模式
按业务能力分解,其起源于业务架构
基于领域驱动设计的概念,通过子域进行分解。可以通过应用DDD并为每个服务定义单独的领域模型
5. 可以通过应用DDD并为每个服务定义单独的领域模型来消除上帝类,正是上帝类引起了阻碍分解的交织依赖项。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/996655.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

idea的GsonFormatPlus插件教程

1 安装 插件 打开idea, File—>Setting—>Plugins,搜索 GsonFormatPlus 直接安装 2 json 转化为 实体类 2.1 新建一个类 2.2 点击右键 2.4 点击Format 生成注释

聊一下酱香拿铁,瑞幸与茅台强强联手

(点击即可收听) 这两天,酱香拿铁火爆朋友圈了的 为什么唯独酱香拿铁会火成这样,不知道有人思考过背后逻辑? 难道只是因为一个新出的拿铁咖啡吗? 奇葩咖啡那么多为什么都没有这个一出来就爆火。 联名本身就是…

BUUCTF内涵的软件 1

使用die查看文件信息,没有pe64就是pe32 运行看看 使用IDA打开文件 shift F12 打开字符串窗口 可能有人猜到了上面的 DBAPP{49d3c93df25caad81232130f3d2ebfad} 可能就是flag,但是我们保持做题的思路来得到这个flag 因为编码问题,这里显…

第29节-PhotoShop基础课程-滤镜库

文章目录 前言1.滤镜库2.Camera Raw滤镜 (用来对图片进行预处理,最全面的一个)3.神经滤镜(2022插件 需要先下载)4.液化(胖-> 瘦 矮->高)5.其它滤镜1.自适应广角2.镜头矫正 把图片放正3.消…

分享配置FreeRTOSConfig.h文件因部分宏值配置不对以及相应函数未定义出现的三个错误解决方法

今天来分享一个在创建FreeRTOS时候调用官方的FreeRTOSConfig头文件时,因部分宏值的配置与FreeRTOS内核文件中的函数不匹配,导致编译时候出现了相应的错误。 于是,既然遇到了,就准备拿出来讲一下,让其他遇到的小伙伴也…

VBA技术资料MF55:VBA_突出显示小于某值的单元格

【分享成果,随喜正能量】当你对别人有用时,人性就是善良的;当你对别人无用时,人性就是自私的;当你触碰别人利益时,人性就是恶毒的。活得通透的人必须做到:圈子越来越小,话也越来越少…

解决transform带来的z-index失效问题

现象如下: 其实下拉列表已经设置了z-index: 但是为什么z-index没有生效呢。 后来发现原来它的父级元素使用了transform进行垂直方向居中 网上查询了相关资料,说: tranform由于会构造一个新的context层, 然后这个层的z轴优先级会最低巴拉巴拉的&#xff…

通信原理板块——信道之无线信道和有线信道

微信公众号上线,搜索公众号小灰灰的FPGA,关注可获取相关源码,定期更新有关FPGA的项目以及开源项目源码,包括但不限于各类检测芯片驱动、低速接口驱动、高速接口驱动、数据信号处理、图像处理以及AXI总线等 1、信道 通信模型中的信道&#xf…

初探JVM

五道常问面试题 1.请你谈谈你对JVM的理解?java8虚拟机和之前的变化更新? 2.什么是OOM,什么是栈溢出StackOverFlowError?怎么分析? 3.JVM的常用调优参数有哪些? 4.内存快照如何抓取,怎么分析Dump文件?知道吗&#xf…

队列(Queue)的顶级理解

目录 1.队列(Queue) 的概念 2.单链表模拟实现队列 2.1创建队列 2.2入队列 2.3判断是否为空 2.4出队列 2.5获取队头元素 2.6完整代码: 2.7双向链表模拟实现队列代码 3.数组模拟实现队列代码 3.1创建队列 3.2判断是否为满 3.3检查是否为空 3.4插入元素 3…

时序分解 | MATLAB实现RIME-VMD霜冰优化算法优化VMD变分模态分解信号分量可视化

时序分解 | MATLAB实现RIME-VMD霜冰优化算法优化VMD变分模态分解信号分量可视化 目录 时序分解 | MATLAB实现RIME-VMD霜冰优化算法优化VMD变分模态分解信号分量可视化效果一览基本介绍程序设计参考资料 效果一览 基本介绍 RIME-VMD【23年新算法】霜冰优化算法优化VMD变分模态分…

基于springboot跨国旅游系统

博主主页:猫头鹰源码 博主简介:Java领域优质创作者、CSDN博客专家、公司架构师、全网粉丝5万、专注Java技术领域和毕业设计项目实战 主要内容:毕业设计(Javaweb项目|小程序等)、简历模板、学习资料、面试题库、技术咨询 文末联系获取 项目介绍…

微信小程序ibeacon搜索功能制作

以下是一个完整的微信小程序代码示例,演示如何实现iBeacon搜索功能: // 在小程序页面中的js文件中编写代码Page({data: {beacons: [] // 存储搜索到的iBeacon设备信息},onReady() {// 初始化iBeaconwx.startBeaconDiscovery({uuids: [你的UUID], // 替换…

关于中了halo勒索病毒,这些你需要了解,勒索病毒解密数据恢复

一,什么是halo勒索病毒? halo勒索病毒是一种新兴的电脑病毒,其主要目标是加密受害者的文件并索要赎金以解锁。这种病毒利用各种手段进行传播,包括电子邮件、恶意网站、网络下载等方式。halo勒索病毒是一种相对较新的勒索病毒&…

免费敏捷需求管理工具,需求管理方案

​传统的瀑布工作模式使用详细的需求说明书来表达需求,需求人员负责做需求调研,根据调研情况编制详细的需求说明书,进行需求评审,评审之后签字确认交给研发团队设计开发。在这样的环境下,需求文档是信息传递的主体&…

Spring框架简介

🌷🍁 博主猫头虎(🐅🐾)带您 Go to New World✨🍁 🦄 博客首页——🐅🐾猫头虎的博客🎐 🐳 《面试题大全专栏》 🦕 文章图文…

GLSL ES着色器语言 使用矢量和矩阵的相关规范

目录 矢量和矩阵类型 下面是声明矢量和矩阵的例子: 赋值和构造 矢量构造函数 矩阵构造函数 构造矩阵的几种方式 访问元素 . 运算符 矢量的分量名 [ ]运算符 运算符 矢量和矩阵可用的运算符 矢量和矩阵相关运算 矢量和浮点数的…

JSP SSM 成果展示系统myeclipse开发mysql数据库springMVC模式java编程计算机网页设计

一、源码特点 JSP SSM 冬奥建设成果展示系统是一套完善的web设计系统(系统采用SSM框架进行设计开发,springspringMVCmybatis),对理解JSP java编程开发语言有帮助,系统具有完整的 源代码和数据库,系统主…

汇编语言Nasmide编辑软件

用来编写汇编语言源程序,Windows 记事本并不是一个好工具。同时,在命令行编译源程序也令很多人迷糊。毕竟,很多年轻的朋友都是用着 Windows 成长起来的,他们缺少在 DOS和 UNIX 下工作的经历。 我一直想找一个自己中意的汇编语言编…

无涯教程-JavaScript - CUMPRINC函数

描述 CUMPRINC函数返回start_period和end_period之间的贷款累计本金。 语法 CUMPRINC (rate, nper, pv, start_period, end_period, type)争论 Argument描述Required/OptionalRateThe interest rate.RequiredNperThe total number of payment periods.RequiredPvThe presen…