首页 > 其他分享 >RMQ异步通信处理机制

RMQ异步通信处理机制

时间:2024-11-07 18:46:32浏览次数:6  
标签:异步 RMQ 服务 通信处理机 绑定 队列 交换机 消息 路由

                                           

场景再现

       在一个微服务架构的商城系统中有两个服务:下单服务和库存服务。当我们进行下单的时候,此时会调用库存服务,进行库存的扣减。这种服务间的调用/通信我们之前是用FeignClient以接口式的请求实现的。但是,OpenFeign是以HTTP协议为基础的,默认下是属于同步通信的,调用者会等待被调用者的响应,所以这个过程是阻塞式的。只有两种结果:要么响应,要么超时,必须等到了结果才会进行下一步的逻辑处理。

       对于有的操作是必须使用同步调用的,只有得到了响应才能进行下一步的操作,而对于有的是不需要等待响应结果的,就比如上面的库存服务,又或者是一些不那么核心的边缘服务。如果就为了等响应,全部等着,性能就大大下降了。此时就需要使用异步通信了。

MQ(Message Queue)

一种用于在分布式系统(如微服务)中实现异步通信的消息中间件。如RabbitMQ。

核心概念

生产者:也就是发送消息的人(程序,服务)

消费者:接收到消息的人(程序,服务)

队列:存储消息的容器,任何发送过来的消息都会进入这个队列,等待消费者取出

交换机:可以理解为消息路由转发器,它位于生产者和队列之间,进入交换机的消息会根据规则转发到相应的队列。只转发不存储。常用交换机:

             FanOut广播模式:将消息转发到所有绑定了这个交换机的队列,等于说对消息进行了N份复制,然后广播给所有人

             Direct直连模式:根据路由键(条件)匹配相应的队列,然后消息转发。

绑定:指队列和交换机之间的绑定,多个队列绑定到了同一个交换机才能接收到交换机的消息。至于交换机会把消息转发给哪个队列,取决于绑定的路由键。

路由键:队列和交换机进行绑定的时候,设置一个路由键(标识),当生产者发消息的时候,传递一个路由键,然后交换机会找到具有此路由键标识的队列进行转发。

虚拟主机:可以理解为类似于容器的东西,每个虚拟主机拥有独立的交换机、队列、绑定和权限配置,可以用来隔离应用。

如:用户有两个队列q1,q2,以及交换机exchange1,两个队列都与交换机进行了绑定,并且指定了不同队列的路由键

 

如果现在发消息,并且指定路由键为test1,那么此时能接收到消息的就只有q1队列了。

异步优点

1,非阻塞

支付服务发送消息后,不会阻塞等待订单状态修改的结果,因此支付服务的调用不会因为消息处理失败而挂起。

2,解耦

支付服务和订单服务解耦了,支付服务只关心是否发送消息,而订单服务负责接收并处理消息。即使订单服务暂时不可用,支付服务也不会受到影响。

3,错误处理

即使消费者处理消息失败(例如订单服务不可用),也不会影响生产者(支付服务)。可以在消费者端设置重试机制或使用死信队列(Dead Letter Queue)来处理失败的消息。

基于注解的方式使用MQ

以支付和交易服务为例,如果支付成功,就调用交易服务,进行订单状态的更改。不使用OpenFeign。

1,引入依赖

此时生产者为支付,消费者为交易,两边都引入依赖

RMQ是基于AMQP协议的,使用Spring提供的依赖简化开发

2,配置RMQ服务的地址等

3,消息处理

生产者只是消息发送,所以我们将队列的创建以及交换机的绑定写在消费者端,方便处理接收到消息后的逻辑。

生产者:

原本是使用Feign客户端进行调用操作的,现在用发消息代替。

参数为:发送到哪个交换机的哪个队列,消息是什么?这里的消息是传过去的订单ID

// 5.修改订单状态
        //orderClient.markOrderPaySuccess(po.getBizOrderNo());
        rabbitTemplate.convertAndSend("trade.exchange","pay.success",po.getBizOrderNo());
消费者:

@RabbitListener  标记此方法为RMQ的消息监听器(消费者)

@QueueBinding  声明队列和交换机的绑定关系

并且指定了这个队列使用名为key的路由键。这个接收及处理消息的方法会接收到反序列化回来的消息ID,然后调用交易服务进行修改。

消息转换器

什么是消息转换?当生产者把消息发送出去的时候,是发送到了RMQ服务器,这个消息可以是普通的变量值,也可以是集合,对象等,当向网络发送这些消息的时候,这些消息会被JDK默认自带的序列化机制序列化为字节流进行发送,会导致原本只有如32字节的数据变成几百字节,占用空间。在服务端看到的还是一堆乱码。可以自定义一个新的消息转换器来解决:

引入依赖,配置即可,Spring 会自动将其应用于 AMQP 相关的组件中,替代原本的默认转换器。

解决后:

应用执行后,服务端可以看见创建的队列以及交换机等。

 如果消息发送后,还有后续操作不依赖于消息结果,异步就非常有意义,它不会阻塞程序。

以上只针对消息发送成功的情况,如果消息发送失败呢?关注不迷路。

消息通知失败icon-default.png?t=O83Ahttps://mp.csdn.net/mp_blog/creation/editor/143590954

往期

网关与微服务的通信icon-default.png?t=O83Ahttps://mp.csdn.net/mp_blog/creation/editor/143430164

OpenFeign同步通信机制icon-default.png?t=O83Ahttps://mp.csdn.net/mp_blog/creation/editor/143435763

标签:异步,RMQ,服务,通信处理机,绑定,队列,交换机,消息,路由
From: https://blog.csdn.net/2301_81243054/article/details/143577224

相关文章

  • Vue3 - 详细实现虚拟列表前端虚拟滚动列表解决方案,vue3长列表优化之虚拟列表,解决列表
    前言Vue2版本,请访问这篇文章在vue3项目开发中,详解实现虚拟列表高度不固定(不定高)且复杂含有图片视频等复杂虚拟列表教程,决列表每项高度不确定及img图像或视频的加载方案,利用缓冲区技术解决用户浏览时渲染不及时列表闪烁白屏/列表加载闪屏,解vue3实现虚拟列表优化大......
  • 深入解析 WKWebView 的 didFinish 回调时机:页面加载与异步操作的处理
    在iOS开发中,我们经常会用WKWebView来加载和展示H5页面。通常,开发者会在WKWebView的didFinish方法中处理页面加载完成后的逻辑,例如更新UI或执行后续操作。然而,didFinish的触发时机并不总是如我们所期待,它并不会等待所有异步操作(如AJAX请求、图片加载等)完成后再执行......
  • ST表(RMQ问题)
    算法理解RMQ问题就是对与区间最值查询一类问题的总称对于RMQ问题的求解主要有以下两种方式:线段树,建树O(n),查询O(logn),支持在线修改ST表,预处理O(logn),查询O(1),不支持在线修改这个单元主要讲解的是ST表倍增思想考虑一个数必然能被拆分成二进制,所以我们先预处理出\(2^k\)......
  • es6,for....of是异步的嘛? 如何实现循环中异步实现
    for...of循环本身不是异步的,它是同步执行的。这意味着for...of循环会按顺序依次执行每一项,直到循环结束。如果循环中的操作是异步的(例如,async函数或者Promise),则这些异步操作会并发执行,但for...of本身不会等待这些操作完成,除非你显式地处理它们。让我们通过一个例子来说明......
  • 微信小程序使用Promise异步请求
     在微信小程序中,如果你希望在一个HTTP请求完成后再继续执行下面的代码,可以将后续代码放入请求的回调函数中。如果不想使用嵌套的回调函数,可以考虑使用 Promise 来处理异步请求。这样可以更清晰地组织代码,还能避免“回调地狱”的问题。这是原方法并不会在执行完http请求后......
  • C#异步和多线程的理解
    1.异步编程(AsynchronousProgramming)异步编程是通过非阻塞方式执行任务,通常适用于I/O密集型任务,例如文件读写、网络请求、数据库访问等。这类操作不需要占用大量CPU资源,而是等待外部资源(如网络或硬盘)响应。在C#中,异步编程使用async和await关键字来实现。异步方法会返......
  • CompletableFuture异步编排接口优化方案
    接口优化方案(1)程序本身,减少不必要的条件判断、循环(2)减少数据库的交互次数,以及每个sql查询的数据量(列数和行数越少越好)(3)提高sql的性能,通过建立合适的索引(4)使用java8的stream流提高集合的遍历操作的效率(5)引入缓存,从redis中加载数据的效率高于mysql(6)使用多线程异步......
  • $RMQ$问题($ST$表)
    \(RMQ\)(区间最值)问题,通常用\(ST\)表。\(ST\)表不仅可以解决区间最大最小问题,还可以解决区间最大公因数/最小公倍数(例)二维\(ST\)表(例),其实就是两个维度都进行倍增,但注意两个维度都要从\(0\)开始枚举,一个为0,一个不为时也要转移。结合二分,当二分一个值(如区间长度,区间端点)并需要......
  • 异步编程的利之Future模式深入解析(In Depth Analysis of Future Patterns)
     ......
  • playwright异步操作-多标签执行
    #作者:yancy#创建日期:2024/11/210:06#放屁:钱钱钱importasyncioimporttimefromplaywright.async_apiimportasync_playwrightfromplaywright.sync_apiimportsync_playwrightimportrandomasyncdefget_url(page,url):awaitpage.goto(url,timeout......