Spring AMQP与RabbitMQ深度整合指南:从基础到高级应用(1)

米饭5个月前行业资讯225

一、初识 MQ

1.1 同步调用:

我们观察下,下面这个余额支付功能的流程图

image-20241128143225761

如果我们采用的是基于 OpenFeign 的同步调用,也就是说业务执行流程是这样的:


支付服务需要先调用用户服务完成余额扣减。

然后支付服务自己要更新支付流水单的状态。

然后支付服务调用交易服务,更新业务订单状态为已支付。

三个步骤依次执行。


这其中就存在3个问题:


拓展性差:

我们目前的业务相对简单,但是随着业务规模扩大,产品的功能也在不断完善。


在大多数电商业务中,用户支付成功后都会以短信或者其它方式通知用户,告知支付成功。假如后期产品经理提出这样新的需求,你怎么办?是不是要在上述业务中再加入通知用户的业务?


某些电商项目中,还会有积分或金币的概念。假如产品经理提出需求,用户支付成功后,给用户以积分奖励或者返还金币,你怎么办?是不是要在上述业务中再加入积分业务、返还金币业务?


最终你的支付业务会越来越臃肿:

image-20241128143524312

也就是说每次有新的需求,现有支付逻辑都要跟着变化,代码经常变动,不符合开闭原则,拓展性不好。


性能下降:

由于我们采用了同步调用,调用者需要等待服务提供者执行完返回结果后,才能继续向下执行,也就是说每次远程调用,调用者都是阻塞等待状态。最终整个业务的响应时长就是每次远程调用的执行时长之和:

image-20241128143701876

假如每个微服务的执行时长都是 50ms,则最终整个业务的耗时可能高达 300ms,性能太差了。


级联失败:

由于我们是基于 OpenFeign 调用交易服务、通知服务。当交易服务、通知服务出现故障时,整个事务都会回滚,交易失败。


这其实就是同步调用的级联失败问题。


不能因为短信通知、更新订单状态失败而回滚整个事务(这些都不是支付服务的主线任务)。


而要解决这些问题,我们就必须用异步调用的方式来代替同步调用。


1.2 异步调用:

异步调用方式其实就是基于消息通知的方式,一般包含三个角色:


消息发送者:投递消息的人,就是原来的调用方。

消息Broker:管理、暂存、转发消息。

消息接收者:接收和处理消息的人,就是原来的服务提供方。

image-20241128144127753

还是以余额支付业务为例:

image-20241128144218877

除了扣减余额、更新支付流水单状态以外,其它调用逻辑全部取消。而是改为发送一条消息到 Broker。而相关的微服务都可以订阅消息通知,一旦消息到达 Broker,则会分发给每一个订阅了的微服务,处理各自的业务。


假如产品经理提出了新的需求,比如要在支付成功后更新用户积分。支付代码完全不用变更,而仅仅是让积分服务也订阅消息即可:

image-20241128144244787

不管后期增加了多少消息订阅者,作为支付服务来讲,执行问扣减余额、更新支付流水状态后,发送消息即可。业务耗时仅仅是这三部分业务耗时,仅仅 100ms,大大提高了业务性能。


另外,不管是交易服务、通知服务,还是积分服务,他们的业务与支付关联度低。现在采用了异步调用,解除了耦合,他们即便执行过程中出现了故障,也不会影响到支付服务。


综上,异步调用的优势包括:


耦合度更低

性能更好

业务拓展性强

故障隔离,避免级联失败

当然,异步通信也并非完美无缺,它存在下列缺点:


完全依赖于 Broker 的可靠性、安全性和性能

架构复杂,后期维护和调试麻烦

消息 Broker,目前常见的实现方案就是消息队列(MessageQueue),简称为 MQ。


下面我们就来进行 RabbitMQ 的学习。

二、RabbitMQ

RabbitMQ 是基于 Erlang 语言开发的开源消息通信中间件,官网地址:


https://www.rabbitmq.com/


接下来,我们就学习它的基本概念和基础用法。


安装:


基于 Docker 来安装 RabbitMQ,使用下面的命令即可:

docker run \
 -e RABBITMQ_DEFAULT_USER=itheima \
 -e RABBITMQ_DEFAULT_PASS=123321 \
 -v mq-plugins:/plugins \
 --name mq \
 --hostname mq \
 -p 15672:15672 \
 -p 5672:5672 \
 --network hm-net\
 -d \
 rabbitmq:3.8-management

可以看到在安装命令中有两个映射的端口:


15672:RabbitMQ提供的管理控制台的端口

5672:RabbitMQ的消息发送处理接口

安装完成后,我们访问 http://ip地址:15672即可看到管理控制台。首次访问需要登录,默认的用户名和密码在配置文件中已经指定了。


登录后即可看到管理控制台总览页面:

543cb9833e29204c79787b9f8d46eb48.pngRabbitMQ 对应的架构如图:

image-20241128144930936

其中包含几个概念:


publisher:生产者。

consumer:消费者。

queue:队列,存储消息。生产者投递的消息会暂存在消息队列中,等待消费者处理。

exchange:交换机,负责消息路由。生产者发送的消息由交换机决定投递到哪个队列。

virtual host:虚拟主机,起到数据隔离的作用。每个虚拟主机相互独立,有各自的 exchange、queue。这个就像一个 mysql 有多个数据库每个数据库有自己的表。

在 MQ 的客户端也可以实现收发消息,比较简单,所以这里跳过。


本文系转载,版权归原作者所有,如若侵权请联系我们进行删除!  

云掣基于多年在运维领域的丰富时间经验,编写了《云运维服务白皮书》,欢迎大家互相交流学习:

《云运维服务白皮书》下载地址:https://fs80.cn/v2kbbq

想了解更多大数据运维托管服务、数据库运维托管服务、应用系统运维托管服务的的客户,欢迎点击云掣官网沟通咨询:https://yunche.pro/?t=shequ


相关文章

从传统运维到SRE的转型路线

从传统运维到SRE的转型路线

从传统运维向SRE(Site Reliability Engineering)转型需要技术技能、思维方式和工作模式的全面转变。以下是详细的转型路线图:一、理解SRE的核心理念SRE的定义SRE是Goo...

C++二分算法:1713得到子序列的最少操作次数

C++二分算法:1713得到子序列的最少操作次数

本文涉及的基础知识点二分查找算法合集LeetCode1713题目给你一个数组 target ,包含若干 互不相同 的整数,以及另一个整数数组 arr ,arr 可能 包含重复元素。每一次操作中,你可以...

MySQL运维之分库分表与读写分离

MySQL运维之分库分表与读写分离

分库分表1.介绍问题分析随着互联网以及移动互联网的发展,应用系统的数据量也是成指数式增长,若采用单数据库进行数据存储,存在以下性能瓶颈:IO瓶颈:热点数据太多,数据库缓存不足,产生大量磁盘IO,效率较...

ubuntu下如何查看显卡及显卡驱动

ubuntu下如何查看显卡及显卡驱动

ubuntu下如何查看显卡及显卡驱动使用nvidia-smi 工具查看查看显卡型号nvida-smi -L$ nvidia-smi -L GPU 0:&nbs...

Docker--Docker是什么和对Docker的了解

Docker--Docker是什么和对Docker的了解

Docker 的本质Docker的本质是LXC(Linux容器)之类的增强版,它本身不是容器,而是容器的易用工具。Docker通过虚拟化技术,将代码、依赖项和运行环境打包成一个容器,并利用隔离机制来使...

SRE(站点可靠性工程)介绍

SRE(站点可靠性工程)介绍

概述站点可靠性工程(SRE)是 IT 运维的软件工程方案。SRE 团队使用软件作为工具,来管理系统、解决问题并实现运维任务自动化。SRE 执行的任务以前通常由运维团队手动执行,或者交给使用软件和自动化...

发表评论    

◎欢迎参与讨论,请在这里发表您的看法、交流您的观点。