RabbitMQ到底为什么要使用它?

news2024/12/23 10:30:36

导入

一个技术的衍生必然是为了解决现实出现的问题,在讲这个问题之前我们先了解一下传统开发中关于服务调用出现的问题(痛点)有哪些?


我们为什么要使用MQ?

①、同步——超时

在多服务体系架构中,必然存在着多个服务之间的调用关系,当用户提交了订单,订单服务会调用支付服务执行用户的金钱操作,执行完毕之后紧接着调用商品服务对商家的商品信息(库存、成交量、收入等)进行更新,执行完毕之后又调用物流服务(对接发货公司、收发地带你)对用户买的商品进行物流实时同步。每一次的服务调用都要等待另一个服务的执行完,整个流程下来很耗时。对于系统来说要求实时性要强,可立即得到结果,而同步调用还存在着其他问题

资源浪费:调用链中每个服务在等待响应过程中,不能释放请求占用的资源,高并发场景下会极度浪费系统资源

级联失败:如果服务提供者出现问题,所有调用方都会跟着出问题,如同多米诺骨牌一样,迅速导致真个微服务群鼓掌

②、服务耦合高

订单服务需要分别调用支付服务、商品服务、物流服务,调用者需要等待服务提供者响应,但是如果作为上游服务的物流服务突然宕机,这样会导致订单服务也会出现问题,用户下单失败;并且如果每次加入新需求,此时如果还需要调用通信服务实时给用户同步下单情况这样一个需求,我们就要修改原来的代码,耦合度很高

③、流量高峰

一般在秒杀或团抢活动中使用广泛。比方说订单系统经过测试组接口测试发现最多只能承受100万次请求,而在面对618、双一这种购物狂潮的高峰期,如果一下来了500万的请求系统时是无法处理的,可能会导致数据库无法承受这么大的压力,响应变慢或者直接挂掉

有没有什么办法能够帮助解决上面出现的问题呢?面对上述的种种问题,伟大的人类就提出了一个奇思妙想——把数据暂存。可不可把所有要传输的消息放在一个容器中,当大量请求来的时候先把一部分的消息(逻辑)暂存在容器中,然后慢慢去处理? 于是出现了消息队列的概念


MQ简介

MQ是什么?

Message Queue,消息队列,是基础数据结构中“先进先出”的一种数据结构。把要传输的消息(数据)放在队列中,用队列机制来实现消息传递——生产者生产消息把消息放入队列,然后消费者去处理。消费者可以到指定队列拉取消息,或者订阅响应的队列,由MQ服务端给其推送消息。

为什么要使用队列这种数据结构呢?

我们知道队列具有先进先出的特点。而消息队列就是将消息放到队列里,用队列做存储消息的介质,看作是一个容器。那这里的消息我们可以指代文本字符串,也可以是更复杂的嵌入对象。消息的发送放称为生产者,消息的接收方称为消费者

MQ要解决什么问题?

结合前面讲到应用场景出现的问题,我们来针对性讨论一下方案:

①、同步请求—>异步请求

通过引入MQ之后,我为了提升系统响应性能,我们可以它改造为异步,那异步请求有什么好处?它是如何解决同步出现的问题?

异步调用的本质是一种事件驱动模式:

  • 耦合度低(不需要调用对方,只需要发布事件,事件去响应即可)
  • 吞吐量提升(不需要等待对方,执行时间更短,吞吐量更大)
  • 故障隔离(如果出现故障更容易排查)
  • 流量削峰(broker做缓存)

②、高耦合—>低耦合

如果使用消息队列,当订单服务执行完成之后,发送一条消息到队列中,其余三个服务读取到这条消息,那么它立刻开始进行业务的执行。使用了消息队列后,消息的发送方和接收方并不需要知道彼此,这样相互之间也就是没有直接关系,即解耦。

③、削峰

这种峰值流量场景一般是集中于一小段时间内,为了防止系统在这个峰值时间内被流量冲垮,可以采用消息队列来削弱峰值流量,此时的消息队列就可以理解为是一个缓冲区,比方说系统只能处理100万请求,但此时同时有500万请求来临,我们就可以把把多余的400万请求先放到队列中,等系统根据自己处理请求的能力去消息队列去消费。

一般用来解决应用解耦异步消息,流量削峰等问题,目的是为了实现高性能、高可用、可伸缩和最终一致性架构

MQ的产品有哪些?

RabbitMQ、ActiveMQ、RocketMQ、ZeroMQ、Kafka、IBM WebSphere 等

通过我提出来的应用场景想必大家对于为什么要使用MQ有了初步的了解,接下来我们重点讨论一下RabbitMQ


RabbitMQ

RabbitMQ是什么?

RabbitMQ是一个由Erlang语言开发的AMQP的开源中间件

补充:AMQP是什么?

AMQP我们可以看作是一种协议活规范,而RabbitMQ是基于这个协议下的实现框架。类似于:JDBC和mysql

RabbitMQ的工作原理是什么?

架构图

组件

描述

生产者(Producer)

发送消息的应用程序,将消息发送到Broker

消费者(Consumer)

接收消息的应用程序,从RabbitMQ Broker获取消息进行处理

Broker

RabbitMQ消息代理服务器,负责接收和分发消息。

交换机(Exchange)

接收生产者发送的消息,并根据路由键routingKey规则将消息路由到跟交换机绑定的一个或多个队列。

交换机主要用来将生产者生产出来的消息,传送到对应的队列中,即交换机是一个消息传送的媒介(具有存储-转发功能),如果路由不到,或许会返回给 Producer(生产者) ,或许会被直接丢弃掉

绑定(Binding)

定义交换机和队列之间的关系,指定消息的路由规则。

路由键(Routing Key)

生产者在发送消息时,将消息附带的路由键发送给交换机,交换机根据路由键将消息路由到相应的队列。

生产者将消息发给交换器的时候,一般会指定一个 RoutingKey(路由键),用来指定这个消息的路由规则,而这个 RoutingKey 需要与交换器类型和绑定键(BindingKey)联合使用才能最终生效

队列(Queue)

存储消息的容器,消费者从队列中获取消息进行处理。

它是消息的容器,也是消息的终点

整个消息传输流程为:

1. 生产者将消息发送到交换机;

2. 交换机根据路由键将消息路由到相应的队列;

3. 消费者从队列中获取消息进行处理。


RabbitMQ有哪些工作模式?

官方网站:RabbitMQ Tutorials — RabbitMQ

①、Simple(简单工作模式)

特点:一个队列只有一个消费者

消息分发的方式。不同工作模式指的是消息路由的策略和方式不同

内部使用的默认交换机

生产者将消息发送到队列,消费者从队列取出消息

②、Work Queues(工作模式)

特点:多个消费者监听同一个队列

在一个队列中如果有多个消费者,消费者之间对于同一个消息的关系是竞争关系,同一条消息只能由一个消费者消费。但是分担压力,比方说有10条消息,C1处理13579消息,C2处理246810消息。顺序取消息,C1取一条,C2取一条,消费规则是轮询

应用场景:

③、Pub/Sub(订阅模式)

特点:多个消息队列,每个消息队列有一个消费者监听

X:交换机,

生产者生产了消息发给交换机,交换机路由分发给不同的消费者,消费者监听获取消息。一个消息可以被多个消费者同时接收消费

每个消费者都监听自己的队列

使用场景:

A服务可以通过异常处理,如果A服务发送后出现问题可以回滚,什么都有可能出现问题,而我们的目的是保持一致性

④、Routing(路由模式)

特点:一个交换机绑定多个消息队列,每个消息队列都有自己唯一的key,每个消息队列有一个消费者监听

Topics(通配符/主题模式)

*:一个单词

#:零个或多个单词


实战演练

依赖

<dependencies>
        <dependency>
            <groupId>com.rabbitmq</groupId>
            <artifactId>amqp-client</artifactId>
            <version>5.6.0</version>
        </dependency>
</dependencies>

生产者

package com.itheima.producer;

import com.rabbitmq.client.Channel;
import com.rabbitmq.client.Connection;
import com.rabbitmq.client.ConnectionFactory;
import java.io.IOException;
import java.util.concurrent.TimeoutException;

public class Producer_HelloWorld {
    public static void main(String[] args) throws IOException, TimeoutException {
        //1.创建连接工厂
        ConnectionFactory factory = new ConnectionFactory();

        //2.设置参数
        factory.setHost("114.115.170.214");
        factory.setPort(5672);
        factory.setVirtualHost("/itcast");
        factory.setUsername("admin");
        factory.setPassword("admin");

        //3.创建连接 Connection
        Connection connection = factory.newConnection();

        //4.创建Channel
        Channel channel = connection.createChannel();

        //5.创建队列Queue
        channel.queueDeclare("denglimei",true,false,false,null);

        //要发送的消息
        String body ="hello rabbitmq~~~";

        //6.发送消息
        channel.basicPublish("","denglimei",null,body.getBytes());
         //7.释放资源
        channel.close();
        connection.close();
    }
}

消费者

package com.itheima.consumer;

import com.rabbitmq.client.*;
import java.io.IOException;
import java.util.concurrent.TimeoutException;

public class Consumer_HelloWorld {
    public static void main(String[] args) throws IOException, TimeoutException {
        //1.创建连接工厂
        ConnectionFactory factory = new ConnectionFactory();

        //2.设置参数
        factory.setHost("114.115.170.214");
        factory.setPort(5672);
        factory.setVirtualHost("/itcast");
        factory.setUsername("admin");
        factory.setPassword("admin");

        //3.创建连接 Connection
        Connection connection = factory.newConnection();

        //4.创建Channel
        Channel channel = connection.createChannel();

        //5.创建队列Queue
        channel.queueDeclare("hello_world",true,false,false,null);

        //匿名内部类
        Consumer consumer = new DefaultConsumer(channel){
            /*
             * 回调方法,当收到消息后,会自动执行该方法
             * 1.consumerTag:标识
             * 2.envelope:获取一些信息,交换机,路由key
             * 3.properties:配置信息
             * 4.body:数据
             * */
            @Override
            public void handleDelivery(String consumerTag, Envelope envelope, AMQP.BasicProperties properties,
                                       byte[] body) throws IOException {
                long start = System.currentTimeMillis();
                for (int i = 0; i < 10000; i++) {
                    System.out.println("第"+i+"条");
                }
                long end = System.currentTimeMillis();

                System.out.println(start-end);
            }
        };

        //接收消息
        channel.basicConsume("hello_world",true,consumer);

        //注意:消费者作为监听者,不要去关闭资源,否则如何监听资源?
    }
}

总结

本次先对MQ和衍生出来的RabbitMQ先做了基本介绍,后续会针对RabbitMQ如何在项目中如何进行削峰、如何解决死信队列等内容做具体介绍,敬请期待~

如果有想要交流的内容欢迎在评论区进行留言,如果这篇文档受到了您的喜欢那就留下你点赞+收藏+评论脚印支持一下博主~

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

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

相关文章

掘金量化—Python SDK文档—5.API 介绍(2)

Python SDK文档 5.API介绍 5.6通用数据函数&#xff08;免费&#xff09; python 通用数据 API 包含在 gm3.0.148 版本及以上版本&#xff0c;不需要引入新库 get_symbol_infos - 查询标的基本信息 获取指定(范围)交易标的基本信息&#xff0c;与时间无关. 此函数为掘金公…

C# 动态字典(可以随机实时增删访问,保证先入先出的字典)

如果你有以下需求&#xff1a; 1. 需要对Dictionary进行遍历的同时移除或者添加元素 2. 需要按顺序遍历Dictionary并且保证先入先出 3. 需要即时的获取字典内的元素数量&#xff0c;即时增删 如果你觉得好&#xff0c;请给我的框架点一个免费的star&#xff0c;球球啦 Yueh0607…

如何将视频转换为AVI格式?3个方法轻松转换!

在数字化时代&#xff0c;视频成为了人们记录和分享重要时刻的主要方式之一。然而&#xff0c;不同设备和平台对视频格式的要求千差万别&#xff0c;有时您可能需要将视频转换为特定格式以便于播放或编辑。在本文中&#xff0c;我们将重点介绍将视频转换为AVI&#xff08;Audio…

python实现小波降噪

文章目录 小波分解小波系数小波降噪阈值确定的一些小知识点python 实现小波去噪小波分解 上图为对信号进行3层小波分解,其中,Approximation 为近似小波系数(信号的低频成分),Detail为细节小波系数(信号的高频成分),分解后得到四个小波系数分别为A3,D3,D2,D1。 小波系数 小…

易查分怎么上传成绩?

当使用易查分制作查询系统时&#xff0c;许多老师可能对于如何上传成绩感到困惑。有时候&#xff0c;导入成绩到易查分系统后&#xff0c;信息可能无法完全显示&#xff0c;而且也很难找到错误的原因。因此&#xff0c;今天我将与老师们分享一下易查分上传成绩的方法。这个技巧…

【软件测试】Git实战-分支的新建和合并(超细整理)

目录&#xff1a;导读 前言一、Python编程入门到精通二、接口自动化项目实战三、Web自动化项目实战四、App自动化项目实战五、一线大厂简历六、测试开发DevOps体系七、常用自动化测试工具八、JMeter性能测试九、总结&#xff08;尾部小惊喜&#xff09; 前言 新建分支 首先&a…

ERROR 2003 (HY000): Can‘t connect to MySQL server on ‘localhost:3306‘ (10061)

用压缩包安装MySQL&#xff0c;执行mysql -u root -p命令&#xff0c;报错&#xff1a; ERROR 2003 (HY000): Cant connect to MySQL server on localhost:3306 (10061) 这是因为MySQL服务器没有启动&#xff0c;我打开任务管理器看了一下&#xff0c;确实没有启动&#xff0c;…

携手航天·追求卓越|诚邀优秀企业加入航天采购平台供应商库

近日&#xff0c;第九届中国&#xff08;国际&#xff09;商业航天高峰论坛在武汉开幕&#xff0c;中国载人航天工程副总设计师张海联在《我国载人月球探测发展总体考虑》主旨报告中介绍了中国载人登月的初步方案。为此&#xff0c;我国科研人员正在研制长征十号运载火箭、新一…

科技云报道:大模型“百团大战”,容联云的机会在哪里?

科技云报道原创。 “大模型的迭代是一场‘暴力’填数据、拔规模而造就的‘美学盛宴’”&#xff0c;中金公司研究团队在“AI浪潮之巅”系列报告中如是说。 在大模型发展初期&#xff0c;大模型或许还称得上是“大厂的游戏”&#xff0c;但半年之后的今天&#xff0c;国内10亿…

【Linux】日志与守护进程

目录 一、预备知识 二、打印日志 三、守护进程 1、前置知识 2、守护进程 一、预备知识 日志是有等级的&#xff0c;表明该条日志的重要程度&#xff0c;一般分为以下几个级别&#xff1a; #define DEBUG 0 //调试信息 #define INFO 1 //正常运行 #define WARNING 2 //报…

【Python爬虫+可视化案例】采集电商网站商品数据信息,并可视化分析

爬虫可视化案例 &#xff1a;苏宁易购 案例所需要掌握的知识点&#xff1a; selenium的使用html标签数据解析方法 需要准备的环境&#xff1a; python 3.8pycharm 2022专业版selenium python里面的第三方库 可以用来操作浏览器 爬虫代码展示 所需模块 【代码领取 请看文末…

017 - STM32学习笔记 - SPI读写FLASH(二)-flash数据写入与读取

016 - STM32学习笔记 - SPI访问Flash&#xff08;二&#xff09; 上节内容学习了通过SPI读取FLASH的JEDEC_ID&#xff0c;在flash资料的指令表中&#xff0c;还看到有很多指令可以使用&#xff0c;这节继续学习使用其他指令&#xff0c;程序模板采用上节的模板。 为了方便起…

为何异地销号这么难?这些注意事项要熟记!

最近有不少小伙伴私信小编&#xff0c;他们在网上办理的大流量手机号卡&#xff0c;用了一段时间之后想换其他的卡&#xff0c;所以想注销当前用的卡&#xff0c;但是注销的时候确实屡屡碰壁&#xff0c;程序还比较繁琐&#xff0c;有的甚至申请注销了几个月还注销不掉&#xf…

在Microsoft Excel中如何合并多个表格

如果你问那些处理数据的人,你会知道合并 Excel 文件或合并工作簿是他们日常工作的一部分。 Power Query 是将多个 Excel 文件中的数据合并或组合到一个文件中的最佳方式。你需要将所有文件存储在一个文件夹中,然后使用该文件夹将这些文件中的数据加载到高级查询编辑器中。它…

了解kubernetes部署:namespace和Node设置

节点及namespace的设置 kubectlcreate-f/opt/kubernetes/namespaces.yaml 通过此命令我们创建了如下namespace: ns-elasticsearch:elasticsearch相关  ns-rabbitmq:rabbitmq相关  ns-javashop&#xff1a;javashop应用相关 接下来我们要根据具体情况安排各个节点的部署规划…

CSS科技感四角边框

实现效果:使用before和after就可以实现,代码量不多,长度颜色都可以自己调整 <!DOCTYPE html> <html lang="en"> <head><meta charset="UTF-8"><title>Title</title><style>*{margin:0;padding:0;}html,body{…

OBS录制双屏

1.设置视频分辨率&#xff0c;假如要录制两个1920x1080分辨率的屏幕&#xff0c;那就把需要录制的分辨率改为3840x10802. 添加显示器采集 3.点击开始录制 4.最终效果

python_PyQt5开发股票指定区间K线操作工具_裸K

目录 写在前面&#xff1a; 工具使用演示&#xff1a; 代码&#xff1a; 导入包 横坐标控件、K线控件、带查询下拉列表控件 K线图控件 主界面代码 执行代码 写在前面&#xff1a; 继前面文章提到筛出低位股票后&#xff0c;想逐一查看这些股票今年的K线走势&#xff…

香港视频直播服务器需要多大的带宽(带宽计算方式)

​  香港视频直播服务器需要多大的带宽(怎么计算带宽大小)。目前短视频行业兴起&#xff0c;有许多人也想利用香港服务器搭建一个直播平台&#xff0c;但无奈不知道怎么选择资源大小&#xff0c;或者说什么样的配置能够满足直播的需求。关于直播的带宽大小和流量消耗的计算同…

记录一次抓取WiFi驱动日志以及sniffer日志

起因 路由器桥接一个WiFi&#xff0c;然后设备连接这个路由器的WiFi&#xff0c;发现网络不可用&#xff0c;而手机或者电脑连接就没问题&#xff0c;与供应商沟通问题&#xff0c;需要抓取日志&#xff0c;记录一下 抓取WLAN DRIVER WLAN FW3日志 进入开发者模式打开启动WL…