RabbitMQ 2023面试5题(四)

一、RabbitMQ有哪些作用

RabbitMQ是一个消息队列中间件,它的作用是利用高效可靠的消息传递机制进行与平台无关的数据交流,并基于数据通信来进行的分布式系统的集成,主要作用有以下方面:

  1. 实现应用程序之间的异步和解耦:通过使用消息队列,应用程序可以通过读写消息来实现通信,无需直接调用彼此,从而减少了对彼此的直接依赖。
    在这里插入图片描述

  2. 提供基本的最终一致性实现:RabbitMQ可以帮助实现面向服务的架构(SOA),通过消息队列来通信,从而实现不同服务之间的解耦,并确保最终一致性。

  3. 实现消息的缓冲和分发:RabbitMQ可以接收并存储大量消息,直到消费者准备好处理它们,从而避免消费者因为数据量过大而无法及时处理消息的情况。

  4. 支持分布式系统中的事务支持:通过使用消息队列,可以在分布式系统中实现事务的协调和通信。

  5. 实现RPC调用:通过使用消息队列,可以在分布式系统中实现RPC调用,从而实现不同服务之间的通信。

  6. 流量控制:通过使用消息队列,将用户请求写入消息队列,按规则读取请求
    在这里插入图片描述

总的来说,RabbitMQ可以帮助应用程序之间实现解耦、缓冲和分发消息,提供最终一致性实现,支持分布式系统中的事务支持和RPC调用。

二、请列举一个RabbitMQ异步消息处理案例

假设有一个电商系统,包含多个子系统,如订单系统、支付系统、物流系统等。这些子系统之间需要进行高效的通信和协作,才能完成整个电商交易过程。

其中一个典型的场景是,当用户在电商网站上下单后,订单系统需要异步将订单信息发送给支付系统和物流系统,以便它们能够及时处理用户的支付和物流需求。

在这种情况下,可以使用RabbitMQ来实现异步消息处理。具体流程如下:

  1. 订单系统创建一个订单后,将订单信息发送到RabbitMQ消息队列中。
  2. 支付系统和物流系统分别订阅该消息队列,并异步处理订单信息。
  3. 支付系统收到订单信息后,会进行支付处理,并将支付结果发送到RabbitMQ消息队列中。
  4. 物流系统收到订单信息后,会进行物流处理,并将物流结果发送到RabbitMQ消息队列中。
  5. 订单系统异步收到支付系统和物流系统的处理结果后,会将订单状态更新为完成或失败,并返回给用户处理结果。

模拟代码:

import com.rabbitmq.client.*;  
  
import java.io.IOException;  
import java.util.concurrent.TimeoutException;  
  
public class RabbitMQExample {  
  
    private final static String ORDER_QUEUE_NAME = "orders";  
    private final static String PAYMENT_QUEUE_NAME = "payments";  
    private final static String SHIPMENT_QUEUE_NAME = "shipments";  
  
    public static void main(String[] args) throws IOException, TimeoutException {  
        // 创建连接工厂并设置参数  
        ConnectionFactory factory = new ConnectionFactory();  
        factory.setHost("localhost");  
        factory.setUsername("guest");  
        factory.setPassword("guest");  
  
        // 创建连接和通道  
        Connection connection = factory.newConnection();  
        Channel channel = connection.createChannel();  
  
        // 声明队列  
        channel.queueDeclare(ORDER_QUEUE_NAME, false, false, false, null);  
        channel.queueDeclare(PAYMENT_QUEUE_NAME, false, false, false, null);  
        channel.queueDeclare(SHIPMENT_QUEUE_NAME, false, false, false, null);  
  
        // 发送订单消息  
        String orderMessage = "New order created";  
        channel.basicPublish("", ORDER_QUEUE_NAME, null, orderMessage.getBytes("UTF-8"));  
        System.out.println(" [x] Sent order message: " + orderMessage);  
  
        // 发送支付消息  
        String paymentMessage = "Payment received";  
        channel.basicPublish("", PAYMENT_QUEUE_NAME, null, paymentMessage.getBytes("UTF-8"));  
        System.out.println(" [x] Sent payment message: " + paymentMessage);  
  
        // 发送物流消息  
        String shipmentMessage = "Shipment sent";  
        channel.basicPublish("", SHIPMENT_QUEUE_NAME, null, shipmentMessage.getBytes("UTF-8"));  
        System.out.println(" [x] Sent shipment message: " + shipmentMessage);  
  
        // 关闭连接和通道  
        channel.close();  
        connection.close();  
    }  
  
    // 订单处理函数  
    public static void processOrder(String message) {  
        System.out.println(" [x] Processing order: " + message);  
    }  
  
    // 支付处理函数  
    public static void processPayment(String message) {  
        System.out.println(" [x] Processing payment: " + message);  
    }  
  
    // 物流处理函数  
    public static void processShipment(String message) {  
        System.out.println(" [x] Processing shipment: " + message);  
    }  
  
    // 订阅消息并异步处理  
    public static void subscribeToMessages(String queueName) throws IOException, TimeoutException {  
        // 创建连接工厂并设置参数  
        ConnectionFactory factory = new ConnectionFactory();  
        factory.setHost("localhost");  
        factory.setUsername("guest");  
        factory.setPassword("guest");  
  
        // 创建连接和通道  
        Connection connection = factory.newConnection();  
        Channel channel = connection.createChannel();  
  
        // 声明队列  
        channel.queueDeclare(queueName, false, false, false, null);  
        System.out.println(" [*] Waiting for messages. To exit press CTRL+C");  
  
        // 创建消费者并订阅队列  
        Consumer consumer = new DefaultConsumer(channel) {  
            @Override  
            public void handleDelivery(String consumerTag, Envelope envelope, AMQP.BasicProperties properties, byte[] body) throws IOException {  
                String message = new String(body, "UTF-8");  
                if (queueName.equals(ORDER_QUEUE_NAME)) {  
                    processOrder(message);  
                } else if (queueName.equals(PAYMENT_QUEUE_NAME)) {  
                    processPayment(message);  
                } else if (queueName.equals(SHIPMENT_QUEUE_NAME)) {  
                    processShipment(message);  
                }  
            }  
        };  
        channel.basicConsume(queueName, true, consumer);  
    }  
}

三、Sprngboot如何使用RabbitMQ发送消息

代码示例:

  • 引入依赖
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-amqp</artifactId>
</dependency>
  • 配置RabbitMQ连接信息
    在application.properties文件中添加以下配置:
spring.rabbitmq.host=localhost
spring.rabbitmq.port=5672
spring.rabbitmq.username=guest
spring.rabbitmq.password=guest
  • 创建消息生产者
@Service
public class MessageProducer {  
    @Autowired
    private RabbitTemplate rabbitTemplate;    

    public void sendMessage(String message) {
        rabbitTemplate.convertAndSend("myQueue", message);
    }
}
  • 创建消息消费者
@Service
public class MessageConsumer implements MessageListener {    

    @Override
    public void onMessage(Message message) throws Exception {
        System.out.println("Received message: " + new String((byte[]) message.getBody()));
    }
}
  • 在启动类上添加@EnableRabbit注解,启用RabbitMQ自动配置。同时,将消息消费者注册到RabbitMQ队列中。
@SpringBootApplication
@EnableRabbit //启用RabbitMQ自动配置
public class Application implements CommandLineRunner {   

    @Autowired
    private MessageProducer messageProducer;    

    public static void main(String[] args) throws Exception {
        SpringApplication.run(Application.class, args);
    }
}

四、RabbitMQ消息队列主要有多少种形式的目的地?

RabbitMQ消息队列主要有两种形式的目的地,分别是队列(Queue)和主题(Topic)。

  • 队列是点对点的消息容器,它只有一个发送者,但可以由多个消费者消费。发送者将消息发送到队列,消费者从队列中读取消息并进行处理。

  • 主题是一种发布/订阅模式的消息容器,它可以包含多个订阅者。发送者将消息发送到主题,订阅者订阅主题并接收消息。多个订阅者可以同时接收同一条消息,但每个订阅者只能接收到符合自己订阅规则的消息。

在RabbitMQ中,队列和主题都是通过exchange来进行路由的。exchange根据指定的路由规则将消息路由到相应的队列中,这个规则可以是基于消息内容的,也可以是基于其他属性的。

五、JMS(Java Message Service)JAVA消息服务与AMQP(Advanced Message Queuing Protocol)消息服务的区别有哪些?

  • JMS:基于JVM消息代理的规范。ActiveMQ、HornetMQ是JMS实现
  • AMQP:高级消息队列协议,也是一个消息代理的规范,兼容JMS,RabbitMQ是AMQP的实现
    具体区别:
JMS(Java Message Service)AMQP(Advanced Message Queuing Protocol)
定义Java api网络线级协议
跨语言否i
跨平台
Model提供两种消息模型:
(1)、Peer-2-Peer
(2)、Pub/sub
提供了五种消息模型:
(1)、direct exchange
(2)、fanout exchange
(3)、topic change
(4)、headers exchange
(5)、system exchange
本质来讲,后四种和JMS的pub/sub模型没有太大差别,
仅是在路由机制上做了更详细的划分;
支持消息类型多种消息类型:
TextMessage
MapMessage
BytesMessage
StreamMessage
ObjectMessage
Message
(只有消息头和属性)
byte[]
当实际应用时,有复杂的消息,可以将消息序列化后发送。
综合评价JMS 定义了JAVA API层面的标准;在java体系中,多个client均可以通过JMS进行交互,不需要应用修改代码,但是其对跨平台的支持较差;AMQP定义了wire-level层的协议标准;天然具有跨平、跨语言特性。

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

【HTTP 协议2】如何构造 HTTP 请求

文章目录 前言一、地址栏输入二、HTML 特殊标签三、form 表单四、ajax总结 前言 各位读者好, 我是小陈, 这是我的个人主页, 希望我的专栏能够帮助到你: &#x1f4d5; JavaSE基础: 基础语法, 类和对象, 封装继承多态, 接口, 综合小练习图书管理系统等 &#x1f4d7; Java数据结…

JAVA2

文章目录 前言 前言 创建&#xff0c;编译java&#xff08;每4修改一次就要重新编译&#xff01;&#xff09; 第一个程序&#xff1a; 解决中文乱码问题&#xff1a; 效果&#xff1a; 总结&#xff1a;

微信小程序——分页组件的创建与使用

✅作者简介&#xff1a;2022年博客新星 第八。热爱国学的Java后端开发者&#xff0c;修心和技术同步精进。 &#x1f34e;个人主页&#xff1a;Java Fans的博客 &#x1f34a;个人信条&#xff1a;不迁怒&#xff0c;不贰过。小知识&#xff0c;大智慧。 &#x1f49e;当前专栏…

volatile关键字和ThreadLocal

作用&#xff1a; 1.线程的可见性&#xff1a;当一个线程修改一个共享变量时&#xff0c;另外一个线程能读到这个修改的值。 2. 顺序一致性&#xff1a;禁止指令重排序。 线程之间的共享变量存储在主内存中&#xff08;Main Memory&#xff09;中&#xff0c;每个线程都一个都…

有哪些做任务赚佣金的平台 做任务挣钱的app

科思创业汇 大家好&#xff0c;这里是科思创业汇&#xff0c;一个轻资产创业孵化平台。赚钱的方式有很多种&#xff0c;我希望在科思创业汇能够给你带来最快乐的那一种&#xff01; 做任务赚佣金的平台&#xff1f;做任务赚钱一直是一种流行的赚钱方式。现在有无数的app可以通…

6-js基础-3

JavaScript 基础 - 3 知道什么是数组及其应用的场景&#xff0c;掌握数组声明及访问的语法&#xff0c;具备利用数组渲染柱形图表的能力 今日重点&#xff1a; 循环嵌套数组综合案例 今日单词&#xff1a; 循环嵌套 利用循环的知识来对比一个简单的天文知识&#xff0c;我们…

SQL题型:根据逗号拆分列

例1&#xff1a; 表&#xff1a; 要实现的结果&#xff1a; 代码&#xff1a; select a.id as hyId,substring_index(substring_index(a.ch_ry_mc, ,,b.help_topic_id 1 ),,, - 1) AS CH_RY_ID FROM rsgl_hygl_hyxx a JOIN mysql.help_topic b ON b.help_topic_id < ( l…

python爬虫增加多线程获取数据

Python爬虫应用领域广泛&#xff0c;并且在数据爬取领域处于霸主位置&#xff0c;并且拥有很多性能好的框架&#xff0c;像Scrapy、Request、BeautifuSoap、urlib等框架可以实现爬行自如的功能&#xff0c;只要有能爬取的数据&#xff0c;Python爬虫均可实现。数据信息采集离不…

【算法】区间DP (从记忆化搜索到递推DP)⭐

文章目录 前期知识516. 最长回文子序列思路1——转换问题&#xff1a;求 s 和反转后 s 的 LCS&#xff08;最长公共子序列&#xff09;思路2——区间DP&#xff1a;从两侧向内缩小问题规模补充&#xff1a;记忆化搜索代码 1039. 多边形三角剖分的最低得分从记忆化搜索开始翻译成…

LLM - Hugging Face 工程 BERT base model (uncased) 配置

欢迎关注我的CSDN&#xff1a;https://spike.blog.csdn.net/ 本文地址&#xff1a;https://blog.csdn.net/caroline_wendy/article/details/131400428 BERT是一个在大量英文数据上以自监督的方式预训练的变换器模型。这意味着它只是在原始文本上进行预训练&#xff0c;没有人以…

el-table多级表头处理方法,了解lebel和prop的真实含义,template的意义,减少全局定义变量。

Element - The worlds most popular Vue UI framework 官网地址 其原理只需要在 el-table-column 里面嵌套 el-table-column&#xff0c;就可以实现多级表头。 要实现的效果如下图所示&#xff1a; <div class"c-table" id"tablePrint"><el-tabl…

信号链噪声分析15

文章目录 概要整体架构流程技术名词解释技术细节小结 概要 提示&#xff1a;这里可以添加技术概要 模数转换器(ADC)将模拟量——现实世界中绝大部分现象的特征——转换为数字语言&#xff0c; 以便用于信息处理、计算、数据传输和控制系统。数模转换器(DAC)则用于将发送或存 储…

【学习笔记】Unity基础(九)【cinemachine基础(body、aim参数详解)】(多fig动图示范)

目录 一 速览1.1 cinemachine下载1.2 官方示例速览1.3 cinemachine定义 二 cinemachine详解2.1 Virtual Camera2.1.1 virtual camera参数通览2.1.2 Status2.1.3 有关Dutch angle2.1.4 Standby Update2.1.5 Transitions 2.2 virtual cameral关键参数详解2.2.1 Body2.2.1.1 Do No…

主辅助服务市场出清模型研究【旋转备用】(Matlab代码实现)

&#x1f4a5;&#x1f4a5;&#x1f49e;&#x1f49e;欢迎来到本博客❤️❤️&#x1f4a5;&#x1f4a5; &#x1f3c6;博主优势&#xff1a;&#x1f31e;&#x1f31e;&#x1f31e;博客内容尽量做到思维缜密&#xff0c;逻辑清晰&#xff0c;为了方便读者。 ⛳️座右铭&a…

vue 3.0 + vite + flv 视频流播放

官方提供的 demo 地址&#xff0c;大家可以用自己的流地址&#xff0c;先试试是否符合需求&#xff1b; http://bilibili.github.io/flv.js/demo/ Flv.js API https://gitee.com/mirrors/flv.js/blob/master/docs/api.md 安装 Flv.js npm install --save flv.js更改 tscon…

软件测试工程师的工作内容?告诉你们什么是真正的测试工程师

目录 前言 1.何为软件测试工程师&#xff1f; 2.软件测试工程师的职责&#xff1f; 3.为什么要做软件测试&#xff1f; 4.软件测试的前途如何&#xff1f; 5.工具和思维谁更重要&#xff1f; 6.测试和开发相差大吗&#xff1f; 7.成为测试工程师的必备条件 8.测试的分…

局域网远程连接

一根网线连接两台电脑 前言步骤1 设置B“允许远程连接”2 A和B必须在同一个网段下面3 “winr”&#xff0c;输入“mstsc”中4 弹出“远程桌面连接”窗口&#xff0c;输入B的ip地址和B电脑的用户名及密码&#xff08;winL键锁屏&#xff0c;看看B的用户名和密码是什么&#xff0…

【正点原子STM32连载】 第四十五章 FLASH模拟EEPROM实验 摘自【正点原子】STM32F103 战舰开发指南V1.2

第四十五章 FLASH模拟EEPROM实验 STM32本身没有自带EEPROM&#xff0c;但是STM32具有IAP&#xff08;在应用编程&#xff09;功能&#xff0c;所以我们可以把它的FLASH当成EEPROM来使用。本章&#xff0c;我们将利用STM32内部的FLASH来实现第三十六章实验类似的效果&#xff0…

MVTEC 3D dataset

官网&#xff1a;https://www.mvtec.com/company/research/datasets/mvtec-3d-ad/downloads https://www.mvtec.com/company/research/datasets/mvtec-3d-adhttps://www.mvtec.com/company/research/datasets/mvtec-3d-ad 数据大小&#xff1a;13个G 1. 介绍 MVTec 3D异常检测…

OpenCV 学习笔记(C++)(1.4W字)

一切图像皆Mat OpenCV中图像对象的创建与复制 Mat基本结构 Mat对象数据组成&#xff1a;头部和数据部分&#xff0c;头部存储图像的属性&#xff08;大小、宽高、图像类型&#xff1a;浮点数类型、字节类型、16位整型、32位整型、双精度浮点型&#xff0c;通道数量和获取途径…