微服务之异步消息通信

news2024/12/23 18:10:44

Informal Essay By English

I’m sorry that I haven’t updated the article lately because the blogger has been busy with interviews and summarizing their experience. I will create a special article to describe the recent events. Next, let’s get to the topic!
在这里插入图片描述
参考书籍:

  1. “凤凰架构”
  2. “微服务架构设计模式”

引言

以往的文章中我们介绍了微服务架构中远程服务调用中的两种实现方式。基于以往的文章的学习我们再深入思考一个问题“远程服务调用的目的是干什么?”这里博主先卖一个关子(注:会在本文的最后进行回答),在此之前,让我们介绍一下本文的核心内容“微服务之异步消息通信”,看到这个标题,有经验的开发人员脑子里面就已经蹦出了两个词“MQ”,对的就是目前讨论话题热度一直处于比较高的一个中间件。本文不会去重点说某一个消息中间件,而是会从消息机制的角度去解释MQ的特性。本文将讨论讨论以下几个主题,包括在扩展接收方的同时保持消息的顺序、检测和丢弃重复的消息,以及作为数据库事务的一部分发送和接收消息。让我们从查看消息机制的工作原理开始

什么是消息传递

Gregor Hope 和 Bobby Woolf 在《Enterprise Integration Patterns 》一书
中 定 义 了一 种 有 用 的 消 息 传 递 模 型 。在这个模型里面,消息实体是通过消息通道进行交换的。发送方(应用程序或服务)将消息写入通道,接收方(应用程序或服务)从通道读取消息。
在这里插入图片描述

消息

消息由标头(标识或安全信息等元数据)和主体组成。其中标头是名称和值对的集合,描述正在发送的数据的元数据。除了消息发送者提供的名称与值对之外,消息头部还包含其他信息,例如发件人或消息传递基础设施生成的唯一消息D,以及可选的返回地址,该地址指定发送回复的消息通道。消息正文是以文本或二进制格式发送的数据。

将消息归类可以划分为以下几种类型:

  • 文档:仅包含数据的通用消息。由消息接收者去决定怎么消费。对命令式消息的回复是文档消息的一种使用场景
    在这里插入图片描述

  • 命令:一条等同于RPC请求的消息。它指定要调用的操作及其参数
    在这里插入图片描述

  • 事件:表示发送方这一端发生了重要的事件。事件通常是领域事件,表示领域对象 (如 o r d e r 或 C u s t o m e r )的状态更改
    在这里插入图片描述

消息通道

如下图所示,消息通过消息通道进行交换。发送方中的业务逻辑调用发送端接口,该接口封装底层通信机制。 发送端由消息发送适配器类实现(六边形架构),该消息发送适配器类通过消息通道向接收器发送消息。消息通道是消息传递基础设施的抽象。调用接收器中的消息处理程序适配器类来处理消息。它调用接收方业务逻辑实现的接收端接口。任意数量的发送方都可以向通道发送消息 。类似地,任何数量的接收方都可以从通道接收消息
在这里插入图片描述
消息通道可以分为“点对点”、“发布-订阅”这两种类型:

  • 点对点通道:向正在从通道读取的一个消费者传递消息。服务使用点对点通道来实现一对一交互方式。例如,命令式消息通常通过点对点通道发送
    在这里插入图片描述

  • 发布-订阅:通道将一条消息发给所有订阅的接收方。服务使用发布一订阅通道来实现一对多交互方式。例如,事件式消息通常通过发布一订阅通道发送
    在这里插入图片描述

使用消息机制实现交互方式

消息机制的一个有价值的特性是它足够灵活,可以支持常见的如下图所示的所有交互方式,下图中的一些交互方式可以直接通过消息机制直接实现。其他的必须在消息机制之上实现。
在这里插入图片描述
我们来看看消息是如何来实现上图的交互方式的,先从请求/响应和异步请求/响应开始

实现请求 / 响应和异步请求 / 响应

当客户端和服务使用请求/ 响应 或异步请求/ 响应进行交互时,客户端会发送请求,服务会发回回复。两种交互方式之间的区别在于,对于请求/ 响应,客户端期望服务立即响应,而对于异步请求/ 响应,则没有这样的期望。消息机制本质上是异步的,因此只提供异步请求/ 响应。但客户端可能会堵塞,直到收到回复。

客户端和服务端通过交换 一对消息来实现异步请求/响应方式的交互。如下图所示, 客户端发送命令式消息,该消息指定要对服务执行的操作和参数,这些内容通过服务拥有的 点对点消息通道传递。该服务处理请求,并将包含结果的回复消息发送到客户端拥有的点对点通道
在这里插入图片描述
客户端必须告知服务发送回复消息的位置,并且必须将回复消息与请求匹配。幸运的是,解决这两个问题并不困难。客户端发送具有回复通道头部的命令式消息。服务器将回复消息写人回复通道,该回复消息包含与消息标识符具有相同值的相关性ID。客户端使用相关性 ID将回复消息与请求进行匹配。
由于客户端和服务使用消息机制进行通信,因此交互本质上是异步的。理论上,使用消息机制的客户端可能会阻塞,直到收到回复,但实际上客户端将异步处理回复。而且,回复通常可以由任何一个客户端实例处理。

实现单向通知

使用异步消息实现单向通知非常简单。客户端将消息( 通常是命令式消息)发送到服务所拥有的点对点通道。服务订阅该通道并处理该消息,但是服务不会发回回复。

实现发布 / 订阅

消息机制内置了对发布/ 订网交互方式的支持。客户端将消息发布到由多个接收方读取的发布/ 订阅通道,发布领域事件的服务拥有自己的发布/ 订阅通道,通道的名称往往派生自领域类。例如,Google Cloud Pub/Sub提供竞争消费者和发布订阅频道语义,通过主题(发布订阅)和订阅(竞争消费者)进行管理,如下图所示,在本例中,订阅方Y和订阅方Z都在订阅同一主题C时接收消息3的副本,但要通过单独的订阅。Google Cloud Pub/Sub不支持通配符订阅
在这里插入图片描述

实现发布/异步响应

发布/ 异步响应交互方式是一种更高级别的交互方式,它通过把发布/ 订阅和请求/ 响应 这两种方式的元素组合在一起实现。客户端发布一条消息,在消息的头部中指定回复通道, 这个通道同时也是一个发布一订阅通道。消费者将包含相关性D的回复消息写人回复通道。 客户端通过使用相关性1D来收集响应,以此将回复消息与请求进行匹配。 应用程序中包含异步API 的每个服务都会使用这些实现技术中的一种或多种。带有异步 API调用操作的服务会拥有一个用于发出请求的通道 ,同样地,需要发布事件的服务也会拥有一个事件式消息发布通道。

为基于消息机制的服务API创建API规范(Application Programming Interface:应用程序编程接口)

服务的异步API 规范必须指定消息通道的名称、通过每个通道交换的消息类型及其格式。你还必须使用诸如JSON、XML或Protobuf 之类的标准来描述消息的格式。 但与REST 和Open API 不同,并没有广泛采用的标准来记录通道和消息类型,你需要自己编写这样的文档。
服务的异步API 包含供客户端调用的操作和由服务对外发布的事件 。这些API 的记录方式不尽相同。让我们从操作开始逐一分析。

记录异步操作

在这里插入图片描述

  • 请求/ 异步响应式API :包括服务的命令消息通道、服务接受的命令式消息的具体类型和格式,以及服务发送的回复消息的类型和格式
  • 单向通知式 API:包括服务的命令消息通道,以及服务接受的命令式消息的具体类型和格式。

需要注意的是服务可以对异步请求/ 响应和单向通知使用相同的请求通道。

记录事件发布

服务还可以使用发布/ 订阅的方式对外发布事件。此API 风格的规范包括事件通道以及服务发布到通道的事件式消息的类型和格式。
消息和消息通道模型是一种很好的抽象,也是设计服务异步API 的好方法。但是,为了实现服务,你需要选择具体的消息传递技术并确定如何使用它们的能力来实现设计。让我们看一看所涉及的内容

使用消息代理

基于消息传递的应用程序通常使用消息代理,即服务通信的基础设施服务。但基于消息 代理的架构并不是唯一的消息架构。你还可以使用基于无代理的消息传递架构,其中服务直接相互通信。这两种方法(如下图所示)具有不同的利弊,但通常基于代理的架构是一种更好的方法
在这里插入图片描述

我们先看第一种“无代理架构”的实现方式:

无代理消息

所谓的无代理其实就是不引入一个新的角色进行消息转发,而是由需要通过消息专递信息的两台服务器直接交互。ZeroMQ 是一种流行的无代理消息技术。它既是规范,也是一组适用于不同编程语言的库。它支持各种传输协议, 包括TCP、UNIX风格的套接字和多播。

使用无代理架构有以下好处:

  • 允许更轻的网络流量和更低的延迟,因为消息直接从发送方发送到接收方,而不必从发送方到消息代理,再从代理转发到接收方
  • 消除了消息代理可能成为性能瓶颈或单点故障的可能性
  • 具有较低的操作复杂性,因为不需要设置和维护消息代理

同样的无代理也有着非常明显的弊端:

  • 服务需要了解彼此的位置,因此必须使用服务发现机制
  • 会导致可用性降低,因为在交换消息时,消息的发送方和接收方都必须同时在线
  • 在实现例如确保消息能够成功投递这些复杂功能时的挑战性更大

无代理架构中的一些弊端于使用同步请求/响应交互方式所导致的弊端相同,因此很多时候我们都会选用基于消息代理的架构。

基于代理的消息

这种基于代理的消息其实就是我们目前市面上流传的MQ,如:Apache ActiveMQ、RabbitMQ、Apache Kafka、RocketMQ(以前由阿里维护,现交由apache维护)
这种架构的消息的一个重要好处是发送方不需要知道接收方的网络位置。另一个好处是消息代理缓冲消息,直到接收方能够处理它们

在进行MQ的技术栈的选择的时候我们需要关注一下几个点:

  • 支持的编程语言:你选择的消息代理应该支持尽可能多的编程语言
  • 支持的消息标准:消息代理是否支持多种消息标准,比如AMQP 和STOMP,还是它仅支持专用的消息标准
  • 消息排序:消息代理是否能够保留消息的排序
  • 投递保证:消息代理提供什么样的消息投递保证
  • 持久性:消息是否持久化保存到磁盘并且能够在代理崩溃时恢复
  • 耐久性:如果接收方重新连接到消息代理,它是否会收到断开连接时发送的消息
  • 可扩展性:消息代理的可扩展性如何
  • 延迟:端到端是否有较大延迟
  • 并发:消息代理是否支持高并发场景

每个消息代理都有不同的侧重点。例如,一个非常低延迟的代理可能不会保留消息的顺序 ,不保证消息投递成功,只在内存中存储消息。保证投递成功并在磁盘上可靠地存储消息的代理可能具有更高的延迟。哪种消息代理最适合取决于你的应用程序的需求。你的应用程序的不同部分甚至可能具有不同的消息传递需求。 但是,消息顺序和可扩展性很可能是必不可少的。

还是同样的,先列举一下使用代理架构的消息的优势:

  • 松耩合:客户端发起请求时只要发送给特定的通道即可,客户端完全不需要感知服务实例的情况,客户端不需要使用服务发现机制去获得服务实例的网络位置
  • 消息缓存:消息代理可以在消息被处理之前一直缓存消息。像HTTP这样的同步请求/ 响应协议 ,在交换数据时,发送方和接收方必领同时在线。然而,在使用消息机制的情况下,消息会在队列中缓存,直到它们被按收方处理。这就意味着,例如,即使订单处理系统暂时离线或不可用,在线商店仍1旧能够接受客户的订单。订单消息将会在队列中缓存 (并不会丢失)
  • 灵活的通信:消息机制支持前面提到的所有交互方式
  • 明确的进程间通信:基于RPC的机制总是企图让远程服务调用跟本地调用看上去没
    什么区别 (在客户端和服务端同时使用远程调用代理)。然而,因为物理定律 (如服务器不可预计的硬件失效)和可能的局部故障,远程和本地调用还是大相径庭的。消息机制让这些差异变得很明确,这样软件工程师不会陷人一种“太平盛世” 的错觉

有优势必然会有一定弊端,使用代理架构的消息有如下弊端:

  • 潜在的性能瓶颈:消息代理可能存在性能瓶颈(许多现代消息代理都支持高度的横向扩展)
  • 潜在的单点故障:消息代理的高可用性至关重要,否则系统整体的可靠性将受到影响(大多数现代消息代理都是高可用的)
  • 额外的操作复杂性 :消息系统是一个必须独立安装、配置和运维的系统组件(这个才是最主要的弊端🤪)

到此,基于消息的通信,我们已经介绍的差不多了,其实在《微服务架构设计模式》中还对目前主流的MQ中间件是如何“处理并发和消息顺序”、“处理重复消息”、“事物性消息”这几个点进行了详细的描述,但是博主认为这些都是设计到具体的中间件的事情,不应该放到这种偏理论的文章中,以后MQ专题中,我们可以单拎出来进行一个详细的解释,因此此篇文章并不花篇幅去解释了。

最后就是再回答一开始提出的问题“远程服务调用的目的是干什么?”

远程服务调用的本质其实还是不同进程间的消息传递,既然RPC的本质是进行消息传递,那么RPC能做的事情,MQ很大程度上也是可以做到的,那么为什么还要有这种两技术栈出现让我们开发人员去选择呢?其实主要还是由他们在交互方式的实现上有不同,因此导致不同的业务场景需要使用不同的技术栈去实现不同进程间的消息传递,稍微总结归纳一下就是:

  • 使用 RPC 的场景一般都是上游服务需要实时依赖下游服务的返回
  • 使用MQ的场景一般都是上游不关心下游结果的场景

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

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

相关文章

FRP 内网穿透,绕过防火墙控制内网机器

内网穿透,端口映射技术是一门十分古老的技术,他一直是一把双刃剑,可以绕过防火墙入侵目标服务器,也可以方便我们运维,工作。 早年的lcx 或者portmap都是比较老的工具了,frp这个工具比之前的lcx或者portmap都…

element-china-area-data 中国省市区级联选择器

1.安装 npm install element-china-area-data -S 2. 说明 文档:element-china-area-data - npm provinceAndCityData是省市二级联动数据(不带“全部”选项) regionData是省市区三级联动数据(不带“全部”选项) prov…

车载操作系统架构研究报告

目 录 前 言 ............................................... 1 1 术语定义及缩略语 ................................................................ 3 1.1 术语与定义 ................................................................. 3 1.2 缩略语 ..............…

[读书笔记] Variational AutoEncoders

小全读书笔记 《Variational AutoEncoders》 1. Generative Model (生成式模型)简述2. 简单生成模型 AutoEncoders![AutoEncoder结构图](https://img-blog.csdnimg.cn/46c5dcf47e754bf7b71d973a15507e0e.png#pic_center)2.1 结构2.2 不足 3. Variational…

【Vue已解决】阻止Vue在启动时生成生产提示

介绍 这里是小编成长之路的历程,也是小编的学习之路。希望和各位大佬们一起成长! 以下为小编最喜欢的两句话: 要有最朴素的生活和最遥远的梦想,即使明天天寒地冻,山高水远,路远马亡。 一个人为什么要努力&a…

3 redis线程IO模型

1 IO模型 1.1 IO IO (Input/Output&#xff0c;输入/输出)即数据的读取&#xff08;接收&#xff09;或写入&#xff08;发送&#xff09;操作&#xff0c;通常用户进程中的一个完整IO分为两阶段&#xff1a;用户进程空间<–>内核空间、内核空间<–>设备空间&…

常用脚本记录

文章目录 1. shell脚本1.1 backup.sh // 目录备份&#xff08;数据备份&#xff09;1.2 check_ip.sh // 检查ip1.3 FlotMonitor.sh // 流量监控1.4 ssh_NoPasswd.sh // 集群免密 2. python脚本2.1 游戏脚本2.1.1 saolei.py // 扫雷(python3)2.1.2 Guessnum.py // 猜数字(python…

Centos7 部署单机 Minio 对象存储服务

MinIO 是一款基于 Go 语言发开的高性能、分布式的对象存储系统&#xff0c;客户端支持 Java&#xff0c;Net&#xff0c;Python&#xff0c;Javacript&#xff0c;Golang语言。 MinIO 的主要目标是作为私有云对象存储的标准方案&#xff0c;非常适合于存储大容量非结构化的数据…

基于AT89C51单片机的简易计算机设计

点击链接获取Keil源码与Project Backups仿真图&#xff1a; https://download.csdn.net/download/qq_64505944/87715642?spm1001.2014.3001.5503 源码获取 主要内容&#xff1a; 本设计是以单片机AT89C51为核心的简易计算器设计&#xff0c;要通过芯片AT89C51实现计算器程序…

Vue核心 计算属性 侦听属性

1.9.计算属性 1.插值语法实现 <!DOCTYPE html> <head><meta charset"UTF-8"><title>姓名案例_插值语法实现</title><!-- 引入Vue --><script type"text/javascript" src"../js/vue.js"></script…

linux部署jdk\redis\nginx\fastdfs

一、jdk安装及配置修改 1、本地下载jdk包 jdk-8u131-linux-x64.tar.gz&#xff0c;上传到服务器&#xff08;也可通过命令直接下载&#xff09; 2、将压缩包放服务器/usr/local路径下&#xff0c;后解压&#xff1a;tar -zxvf jdk-8u131-linux-x64.tar.gz 如之前已安装&…

OSCP-XPosedAPI(本地文件包含、查看源码、os.system、命令盲注)

目录 扫描 Web API枚举 命令盲注 提权 扫描 发现了两个开放的端口:端口22上的SSH和端口13337上的未知服务。 用netcat手动探测端口13337,但是运行几个常见的TCP/UDP服务初始化命令没有输出。 尝试了一个完整的脚本和版本nmap扫描的开放端口࿰

Vue3:基础入门

Vue3&#xff1a;基础入门 Date: April 10, 2023 Sum: vue简介、vue的基本使用、vue的指令与过滤器、品牌列表案例 目标&#xff1a; 能够知道 vue 的基本使用步骤 掌握插值表达式和 v-bind 指令的用法 能够掌握如何使用 v-on 指令绑定事件 能够使用 v-model 指令实现数据…

Science | 华盛顿大学Baker团队提出AI新范式设计全新蛋白复合物

蛋白质的结构形态和生物学功能是由氨基酸序列决定的。 人工蛋白质设计的目标就是创造可以折叠成特定结构以实现特定功能的新型氨基酸序列。 当然&#xff0c;这并不是一个简单的问题&#xff0c;因为它需要了解蛋白质如何在细胞中折叠&#xff0c;而这一过程在很大程度上仍不为…

【微服务】- 分布式系统的流量防卫兵 - sentinel

Sentinel流量防卫兵 &#x1f604;生命不息&#xff0c;写作不止 &#x1f525; 继续踏上学习之路&#xff0c;学之分享笔记 &#x1f44a; 总有一天我也能像各位大佬一样 &#x1f3c6; 一个有梦有戏的人 怒放吧德德 &#x1f31d;分享学习心得&#xff0c;欢迎指正&#xff0…

代码优化- 中间表示上的优化

中间表示上的代码优化依赖于具体所使用的中间表示&#xff1a;控制流图&#xff08;CFG&#xff09;、控制依赖图&#xff08;CDG&#xff09;、静态单赋值形式&#xff08;SSA&#xff09;、后续传递风格&#xff08;CPS&#xff09;等 共同的特点是需要进行程序分析&#xf…

7 ADC(一)

7 ADC ADC简介 ADC&#xff08;Analog-Digital Converter&#xff09;模拟-数字转换器 ADC可以将引脚上连续变化的模拟电压转换为内存中存储的数字变量&#xff0c;建立模拟电路到数字电路的桥梁 12位&#xff08;0-2^(12-1)&#xff09;逐次逼近型ADC&#xff0c;1us转换时间…

HTTP连接要考虑超时,重试和并发之原因

一、原因&#xff08;why) 连接超时配置得特别长&#xff0c;比如 60 秒。一般来说&#xff0c;TCP 三次握手建立连接需要的时间非常短&#xff0c;通常在毫秒级最多到秒级&#xff0c;不可能需要十几秒甚至几十秒。如果很久都无法建连&#xff0c;很可能是网络或防火墙配置的…

光纤网卡传输速率和它的应用领域有哪些呢?通常用会到有哪些型号网络变压器呢?

Hqst盈盛&#xff08;华强盛&#xff09;电子导读&#xff1a;常有客户问起光纤网卡该如何选用到合适的产品&#xff0c;选用时要注意到哪些事项&#xff0c;这节将结合配合到的网络变压器和大家一起探讨&#xff0c;希望对大家有些帮助。 1&#xff0e;光纤网卡传输速率与网络…

AlgoC++第三课:C++世界观

目录 C世界观前言1. 程序逻辑2. 内存的逻辑3. 调度的逻辑4. 编译的逻辑5. 作用域的逻辑6. 命名空间的逻辑7. 生命周期的逻辑8. C类的逻辑9. 编译时和运行时的逻辑总结 C世界观 前言 手写AI推出的全新面向AI算法的C课程 Algo C&#xff0c;链接。记录下个人学习笔记&#xff0c…