RabbitMQ常⻅⾯试题

news/2024/11/17 22:57:01/

1. MQ的作⽤及应⽤场景

类似问题:

项⽬什么场景下使⽤到了MQ,

为什么需要MQ RabbitMQ 的作⽤?

使⽤场景有哪些

RabbitMQ的主要应⽤场景

消息队列解耦应⽤程序的例⼦

消息队列的应⽤场景

为什么说消息队列可以削峰

  • 异步解耦: 在业务流程中, ⼀些操作可能⾮常耗时, 但并不需要即时返回结果. 可以借助MQ把这些操作异步化.(⽐如⽤⼾注册后发送注册短信或邮件通知, 可以作为异步任务处理, ⽽不必等待这些操作 完成后才告知⽤⼾注册成功)

  • 流量削峰: 在访问量剧增的情况下, 应⽤仍然需要继续发挥作⽤, 但是是这样的突发流量并不常⻅. 如果以能处理这类峰值为标准⽽投⼊资源,⽆疑是巨⼤的浪费. 使⽤MQ能够使关键组件⽀撑突发访问压⼒, 不会因为突发流量⽽崩溃. (⽐如秒杀或者促销活动, 可以使⽤MQ来控制流量, 将请求排队, 然后系统根据⾃⼰的处理能⼒逐步处理这些请求)
  • 异步通信: 在很多时候应⽤不需要⽴即处理消息, MQ提供了异步处理机制, 允许应⽤把⼀些消息放⼊ MQ中, 但并不⽴即处理它,在需要的时候再慢慢处理. 
  • 消息分发: 当多个系统需要对同⼀数据做出响应时, 可以使⽤MQ进⾏消息分发. ⽐如⽀付成功后, ⽀付系统可以向MQ发送消息, 其他系统订阅该消息, ⽽⽆需轮询数据库. 
  • 延迟通知: 在需要在特定时间后发送通知的场景中, 可以使⽤MQ的延迟消息功能, ⽐如在电⼦商务平台中,如果⽤⼾下单后⼀定时间内未⽀付,可以使⽤延迟队列在超时后⾃动取消订单

 

2. 了解过哪些MQ,以及区别 

类似问题:

了解过哪些MQ, 与其他同类产品的对⽐

kafka 和 RabbitMQ的对⽐

对⽐其他消息队列,不同mq分别⽤在什么场景

kafka和rocketmq⽐较

消息队列除了使⽤RabbitMQ,可以⽤RocketMQ吗?

⽬前业界有很多的MQ产品, 例如RabbitMQ, RocketMQ, ActiveMQ, Kafka, ZeroMQ等, 简单介绍其中3种:

1. Kafaka

Kafka⼀开始的⽬的就是⽤于⽇志收集和传输,追求⾼吞吐量, 性能卓越, 单机吞吐达到⼗万级, 在⽇志领域⽐较成熟, 功能较为简单, 主要⽀持简单的 MQ 功能. 适合⼤数据处理, ⽇志聚合, 实时分析等场景

2. RabbitMQ

采⽤Erlang语⾔开发, MQ 功能⽐较完备, 且⼏乎⽀持所有主流语⾔, 开源提供的界⾯也⾮常友好, 性能较好, 吞吐量能达到万级, 社区活跃度较⾼,⽂档更新频繁, ⽐较适合中⼩型公司, 数据量没那么⼤, 且并发没那么⾼的场景.

3. RocketMQ

采⽤Java语⾔开发, 由阿⾥巴巴开源, 后捐赠给了Apache. 在可⽤性, 可靠性以及稳定性等⽅⾯都⾮常出⾊, 吞吐量能达到⼗万级, 在Alibaba集团内部⼴泛使⽤, 但⽀持的客⼾端语⾔不多, 产品较新⽂档较少, 且社区活跃度⼀般. 适合于⼤规模分布式系统, 可靠性要求⾼, 且并发⼤的场景, ⽐如互联⽹⾦融.

3. 介绍下RabbitMQ的核⼼概念及⼯作流程

相关⾯试题:

RabbitMQ的核⼼流程简单介绍⼀下

讲下RabbitMQ的结构

 

RabbitMQ是⼀个消息中间件, 也是⼀个⽣产者消费者模型. 它负责接收, 存储并转发消息. 根据⼯作流程 图, 来介绍它的核⼼概念: 

  • Producer: ⽣产者, 向RabbitMQ发送消息 
  • Consumer: 消费者, 从RabbitMQ接收消息
  • Broker: 消息队列服务器或服务实例, 也就是rabbitMQ Server,接收并转发消息
  • Connection: ⽹络连接, 它允许客⼾端与 RabbitMQ通信
  • Channel: 连接⾥的⼀个虚拟通道, 发送或者接收消息都是通过通道进⾏的. 
  • Exchange: 交换机. 负责接收⽣产者发送的消息, 并根据路由算法和规则将消息路由到⼀个或多个队 列
  • Queue: 消息队列, 存储消息直到它们被消费者消费

工作流程:

  1. 创建连接: Producer连接到RabbitMQBroker, 建⽴⼀个连接(Connection), 开启⼀个信道(Channel)
  2. 声明交换机和队列,以及绑定规则: Producer 声明⼀个交换机(Exchange)和队列, 并绑定Queue到 Exchange
  3. 发布消息: Producer 发送消息⾄RabbitMQ Broker
  4. 消息存储: RabbitMQ Broker 接收消息, 并存⼊相应的队列(Queue)中, 如果未找到相应的队列, 则根 据⽣产者的配置, 选择丢弃或者退回给⽣产者.
  5. 消费消息: 消费者监听Queue, 当消息到达时, 从Queue中获取消息, 处理后, 向RabbitMQ发送消息确 认
  6. 消息删除: 消息被确认后, RabbitMQ 会把消息从Queue中删除.

4. RabbitMQ如何保证消息的可靠性

相关⾯试题:

RabbitMQ消息丢失原因及其解决⽅案

如何保证消息不丢失

消息写⼊失败怎么办

消息消费失败如何处理

MQ的主动ack和被动ack有什么区别

RabbitMQ如何解决数据丢失问题, 如何保证⼀致性

消息队列怎么保证消费者的消息不丢失的?

从以下⼏个⽅⾯来回答

1. 发送⽅投递可靠性

2. RabbitMQ可靠性

3. 消费者可靠性

详见高级特性3.3

5. RabbitMQ如何保证消息的顺序性

相关⾯试题:

RabbitMQ怎么保证消息的顺序性?

如何保证消息能够有序消费?

  • 单队列单消费者
  • 分区消费
  • 事务和消息确认机制
  • 业务逻辑控制, ⽐如消费端内部实现消息排序逻辑 

详看应用问题2.顺序性保障 

6. 如何保证消息消费时的幂等性

相关问题:

RabbitMQ怎么保证消息不重复消费

消息或请求存在重复消费问题吗? 是怎么解决的?

怎么解决MQ重复消费的问题

详看应用问题1. 幂等性保障

7. RabbitMQ有哪些特性

  • 发送⽅消息确认
  • 持久化
  • 消费端消息确认
  • 重试机制
  • TTL
  • 死信队列

详看高级特性 

8. 介绍下RabbitMQ的死信队列

类似问题:

RabbitMQ的死信队列以及应⽤场景

 从以下⽅⾯来回答:

  • 死信队列的概念
  • 死信的来源
  • 死信队列的应⽤场景

详看高级特性-死信队列 

9. 介绍下RabbitMQ的延迟队列

 类似问题:

rabbitmq延迟队列的实

从以下三个⽅⾯来回答

  • 概念
  • 应⽤场景
  • 实现⽅式 

详看高级特性-死信队列 

10. 介绍下RabbitMQ的⼯作模式

 相关⾯试题:

RabbitMQ的⼏种模式, work模式怎么实现的能者多劳

1. Simple(简单模式)

2. Work Queue(⼯作队列)

3. Publish/Subscribe (发布/订阅)

4. Routing(路由模式)

5. Topics(通配符模式)

6. RPC(RPC通信)

7. Publisher Confirms(发布确认)

11. 消息积压的原因, 如何处理

类似问题:

MQ消息堆积问题

如果解决MQ的数据囤积?

消息积压的原因:

  • 消息⽣产过快
  • 消费者能⼒不⾜
  • ⽹络问题
  • RabbitMQ服务配置偏低

.....

解决⽅案:

  • 提⾼消费者效率, ⽐如增加机器, 优化业务逻辑
  • 限制消费者⽣产速率
  • 资源配置优化

详看应用问题-消息积压 

 

12. RabbitMQ是推模式还是拉模式

概念

RabbitMQ⽀持两种消息传递模式: 推模式(push)和拉模式(pull)

推模式:消息中间件主动将消息推送给消费者.

拉模式:消费者主动从消息中间件拉取消息.

RabbitMQ主要是基于推模式⼯作的, 它的核⼼设计是让消息队列中的消费者接收到由⽣产者发送的消息. 使⽤channel.basicConsume⽅法订阅队列, RabbitMQ就会把消息推送到订阅该队列的消费者, 如果只想从队列中获取单条消息而不是持续订阅,则可以使⽤channel.basicGet⽅法来进⾏消费消息.

借助SpringBoot:


使用SDK来完成: 

 

public class Producer {public static void main(String[] args) throws IOException, TimeoutException {//1. 建立连接ConnectionFactory connectionFactory = new ConnectionFactory();connectionFactory.setHost(Constants.HOST);connectionFactory.setPort(Constants.PORT); //需要提前开放端口号connectionFactory.setUsername(Constants.USER_NAME);//账号connectionFactory.setPassword(Constants.PASSWORD);  //密码connectionFactory.setVirtualHost(Constants.VIRTUAL_HOST); //虚拟主机Connection connection = connectionFactory.newConnection();//2. 开启信道Channel channel = connection.createChannel();//3. 声明队列   使用内置的交换机//如果队列不存在, 则创建, 如果队列存在, 则不创建channel.queueDeclare(Constants.MESSAGE_QUEUE,true,false,false,null);//4. 发送消息for (int i = 0; i < 10; i++) {String msg = "hello message queue...."+i;channel.basicPublish("",Constants.MESSAGE_QUEUE, null, msg.getBytes());}System.out.println("消息发送成功~");//5. 资源释放channel.close();connection.close();}
}

 

/*** 拉模式*/
public class PullController {public static void main(String[] args) throws IOException, TimeoutException {//1. 建立连接ConnectionFactory connectionFactory = new ConnectionFactory();connectionFactory.setHost(Constants.HOST);connectionFactory.setPort(Constants.PORT); //需要提前开放端口号connectionFactory.setUsername(Constants.USER_NAME);//账号connectionFactory.setPassword(Constants.PASSWORD);  //密码connectionFactory.setVirtualHost(Constants.VIRTUAL_HOST); //虚拟主机Connection connection = connectionFactory.newConnection();//2. 开启信道Channel channel = connection.createChannel();//3. 声明队列   使用内置的交换机//如果队列不存在, 则创建, 如果队列存在, 则不创建channel.queueDeclare(Constants.MESSAGE_QUEUE, true, false, false, null);//4.拉模式获取GetResponse getResponse = channel.basicGet(Constants.MESSAGE_QUEUE, true);System.out.println("拉模式获取消息:"+new String(getResponse.getBody(),"UTF-8"));//5. 资源释放
//        channel.close();
//        connection.close();}
}

 

/*** 推模式*/
public class PushController {public static void main(String[] args) throws IOException, TimeoutException, IOException, TimeoutException {//1. 建立连接ConnectionFactory connectionFactory = new ConnectionFactory();connectionFactory.setHost(Constants.HOST);connectionFactory.setPort(Constants.PORT); //需要提前开放端口号connectionFactory.setUsername(Constants.USER_NAME);//账号connectionFactory.setPassword(Constants.PASSWORD);  //密码connectionFactory.setVirtualHost(Constants.VIRTUAL_HOST); //虚拟主机Connection connection = connectionFactory.newConnection();//2. 开启信道Channel channel = connection.createChannel();//3. 声明队列   使用内置的交换机//如果队列不存在, 则创建, 如果队列存在, 则不创建channel.queueDeclare(Constants.MESSAGE_QUEUE, true, false, false, null);//4. 消费消息DefaultConsumer consumer = new DefaultConsumer(channel){//从队列中收到消息, 就会执行的方法@Overridepublic void handleDelivery(String consumerTag, Envelope envelope, AMQP.BasicProperties properties, byte[] body) throws IOException {//TODOSystem.out.println("接收到消息:"+ new String(body));}};channel.basicConsume(Constants.MESSAGE_QUEUE, true, consumer);//        //5. 资源释放
//        channel.close();
//        connection.close();}
}

两种方式区别:

推模式:

对消息的获取更加实时, 适合对数据实时性要求⽐较⾼时, ⽐如实时数据处理, 如监控系统, 报表系统等.

拉模式:

消费端可以按照⾃⼰的处理速度来消费, 避免消息积压, 适合需要流量控制, 或者需要⼤量计算资源的任 务, 拉取模式允许消费者在准备好后再请求消息, 避免资源浪费


http://www.ppmy.cn/news/1547822.html

相关文章

嵌入式硬件杂谈(二)-芯片输入接入0.1uf电容的本质(退耦电容)

引言&#xff1a;对于嵌入式硬件这个庞大的知识体系而言&#xff0c;太多离散的知识点很容易疏漏&#xff0c;因此对于这些容易忘记甚至不明白的知识点做成一个梳理&#xff0c;供大家参考以及学习&#xff0c;本文主要针对芯片输入接入0.1uf电容的本质的知识点的进行学习。 目…

如何知道表之间的关系(为了知识图谱的构建)

今天就简单点&#xff0c;把今天花时间做的一个程序说下。 我们在做常规知识图谱的时候&#xff0c;面临一个问题就是要知道关系是如何建立。如果表的数量比较少&#xff0c;人工来做还是比较容易的。 如果有非常多的表&#xff0c;并且这些表之间的关联关系都不清楚的情况下…

vscode报错:Connecting with SSH time-out.

当我们在vscode上远程连接&#xff08;Remote_SSH&#xff09;Linux时&#xff0c;如果直接点关闭vscode,下次远程登陆后&#xff0c;就会弹出以下界面&#xff0c; 点击重新加载window就会弹出以下报错&#xff1a; 这是因为我们没有正常关闭remote-ssh, 导致linux上有多个vsc…

执行npm run build -- --report后,生产report.html文件是什么?

‌ 执行npm run build -- --report后&#xff0c;生成的report.html文件是一个打包分析报告&#xff0c;它详细记录了项目的打包结果和各个文件的大小信息。‌ 这个报告文件通常包含以下内容&#xff1a; ‌文件大小信息‌&#xff1a;报告会列出项目中每个文件的大小&#…

记录一下跨域的问题,讲讲跨域

一、为什么有跨域 跨域问题本质上是由于浏览器的同源策略&#xff08;Same Origin Policy&#xff09;引起的。这个策略是为了增强网页的安全性&#xff0c;防止恶意网站获取用户的敏感信息。也就是说经过浏览器的才有跨域&#xff0c;在前端代码中进行数据请求的时候往往都要…

地质旅游平台推动“旅游+地质”融合发展

2024年元旦假期&#xff0c;哈尔滨文旅市场持续火爆。据哈尔滨市文化广电和旅游局大数据测算&#xff0c;截至1月1日&#xff0c;哈尔滨市累计接待游客304.79万人次&#xff0c;实现旅游总收入59.14亿元&#xff0c;游客接待量与旅游总收入达到历史峰值。 夏有进“淄”赶烤&…

springboot003基于springboot的图书个性化推荐系统(源码+包运行+LW+技术指导)

项目描述 临近学期结束&#xff0c;还是毕业设计&#xff0c;你还在做java程序网络编程&#xff0c;期末作业&#xff0c;老师的作业要求觉得大了吗?不知道毕业设计该怎么办?网页功能的数量是否太多?没有合适的类型或系统?等等。这里根据疫情当下&#xff0c;你想解决的问…

用PHP实现一个简单的http服务器

在 PHP 中&#xff0c;你可以使用 socket 函数编写一个简单的 HTTP 服务器。以下是一个示例代码&#xff0c;监听 9000 端口&#xff0c;当收到请求时返回 "Hello, World"&#xff1a; <?php // 设置监听端口 $host 127.0.0.1; $port 9000;// 创建一个 TCP 套…