1. 消息队列概述
-
能够说出什么是消息队列
-
能够安装RabbitMQ
-
能够编写RabbitMQ的入门程序
-
能够说出RabbitMQ的5种模式特征
-
能够使用SpringBoot整合RabbitMQ
目标:能够说出什么是消息队列;为什么使用消息队列;常见产品有哪些
小结:
MQ全称为Message Queue,消息队列是应用程序和应用程序之间的通信方法。
-
为什么使用MQ:在项目中,可将一些无需即时返回且耗时的操作提取出来,进行异步处理,而这种异步处理的方式大大的节省了服务器的请求响应时间**,从而提高了系统的吞吐量。
-
开发中消息队列通常有如下应用场景
1、任务异步处理
将不需要同步处理的并且耗时长的操作由消息队列通知消息接收方进行异步处理。提高了应用程序的响应时
间。2、应用程序解耦合
MQ相当于一个中介,生产方通过MQ与消费方交互,它将应用程序进行解耦合。
https://blog.csdn.net/whoamiyang/article/details/54954780
案例:
大多数程序员在面试中,应该都问过或被问过一个经典却没有标准答案的问题:如何设计一个秒杀系统?这个问题可以有一百个版本的合理答案,但大多数答案中都离不开消息队列。
秒杀系统需要解决的核心问题是,如何利用有限的服务器资源,尽可能多地处理短时间内的海量请求。我们知道,处理一个秒杀请求包含了很多步骤,例如:
- 风险控制(监控哪些用户一直是下单不付款的,如果超过一定的阈值,就给这个用户打上标记,归属黑名单)
- 库存锁定
- 生成订单
- 短信通知
- 更新统计数据
如果没有任何优化,正常的处理流程是:App 将请求发送给网关,依次调用上述 5 个流程,然后将结果返回给 APP。
对于对于这 5 个步骤来说,能否决定秒杀成功,实际上只有风险控制和库存锁定这 2 个步骤。只要用户的秒杀请求通过风险控制,并在服务端完成库存锁定,就可以给用户返回秒杀结果了,对于后续的生成订单、短信通知和更新统计数据等步骤,并不一定要在秒杀请求中处理完成。
所以当服务端完成前面 2 个步骤,确定本次请求的秒杀结果后,就可以马上给用户返回响应,然后把请求的数据放入消息队列中,由消息队列异步地进行后续的操作。
处理一个秒杀请求,从 5 个步骤减少为 2 个步骤,这样不仅响应速度更快,并且在秒杀期间,我们可以把大量的服务器资源用来处理秒杀请求。秒杀结束后再把资源用于处理后面的步骤,充分利用有限的服务器资源处理更多的秒杀请求。
-
实现方式:AMQP,JMS
JMS AMQP 定义 Java api Wire-protocol 跨语言 否 是 跨平台 否 是 模型 提供两种消息模型:Peer-2-Peer,Pub/sub 提供了五种消息模型 支持消息类型 多种消息类型 byte[],当实际应用时,有复杂的消息,可以将消息序列化后发送。 综合评价 JMS 定义了JAVA API层面的标准;在java体系中,多个client均可以通过JMS进行交互,不需要应用修改代码,但是其对跨平台的支持较差; AMQP定义了wire-level层的协议标准;天然具有跨平台、跨语言特性。 -
常见产品:activeMQ,zeroMQ,RabbitMQ,RocketMQ,kafka
三大主流消息队列:
-
rabbitmq:
优点:轻量,迅捷,容易部署和使用,拥有灵活的路由配置
缺点:性能和吞吐量较差,不易进行二次开发
-
rocketmq:
优点:性能好,稳定可靠,有活跃的中文社区
缺点:兼容性较差(因为是在中国比较活跃)
-
kafka:
优点:强大的性能和吞吐量,兼容性好(特别是大数据相关的中间件)
缺点:设计上需要攒一波再一起发送,所以时延会相对比较高,不大适合在线业务场景
基础介绍:
生产(Producing)只味着发送。发送消息的程序是生产者(Producer):
队列是RabbitMQ中的邮箱的名称。尽管消息流经rabbitmq和应用程序,但它们只能存储在队列中。队列只受主机的内存和磁盘限制的约束,它本质上是一个大的消息缓冲区。许多生产者可以将消息发送到一个队列,而许多消费者可以尝试从一个队列接收数据。这就是我们表示队列的方式:
消费和接受有着相似的含义。消费者(Consumer)是一个主要等待接收消息的程序:
注意生产者、消费者和rabbitmq程序不必驻留在同一主机上;事实上,在大多数应用程序中,它们不必驻留在同一主机上。应用程序也可以同时是生产者和消费者。
2. 安装及配置RabbitMQ
目标:按照文档在本机安装windows版本RabbitMQ,并配置其用户和Virtual Hosts
分析:
- 安装erlang;
- 安装rabbitMQ;
- 安装RabbitMQ的图形管理界面插件;
- 创建管理用户;
- 创建虚拟主机Virtual Hosts
小结:
安装上述的组件时候都需要使用以管理员身份运行。
虚拟主机安装:
像mysql拥有数据库的概念并且可以指定用户对库和表等操作的权限。RabbitMQ也有类似的权限管理;在RabbitMQ中可以虚拟消息服务器Virtual Host,每个Virtual Hosts相当于一个相对独立的RabbitMQ服务器,每个VirtualHost
之间是相互隔离的。exchange、queue、message不能互通。 相当于mysql的db。Virtual Name一般以/开头。
3. 搭建RabbitMQ入门工程
目标:搭建RabbitMQ入门工程并配置对应的maven依赖
分析:
创建heima-rabbitmq的工程;用于测试RabbitMQ的消息收发。添加用于操作RabbitMQ的依赖。
<dependency>
<groupId>com.rabbitmq</groupId>
<artifactId>amqp-client</artifactId>
<version>5.6.0</version>
</dependency>
小结:
使用IDEA创建maven工程;使用了jdk1.8。在工程中的pom.xml文件中添加了上述的依赖。
4. 入门工程-生产者
目标:编写消息生产者代码,发送消息到队列
分析:
入门工程:生产者发送消息到RabbitMQ的队列(simple_queue);消费者可以从队列中获取消息。可以使用RabbitMQ的简单模式(simple)。
生产者实现发送消息的步骤:
- 创建连接工厂(设置RabbitMQ的连接参数);
- 创建连接;
- 创建频道;
- 声明队列;
- 发送消息;
- 关闭资源
小结:
package com.itheima.rabbitmq.simple;
import com.rabbitmq.client.Channel;
import com.rabbitmq.client.Connection;
import com.rabbitmq.client.ConnectionFactory;
/**
* 简单模式:发送消息
*/
public class Producer {
static final String QUEUE_NAME = "simple_queue";
public static void main(String[] args) throws Exception {
//1. 创建连接工厂(设置RabbitMQ的连接参数);
ConnectionFactory connectionFactory = new ConnectionFactory();
//主机;默认localhost
connectionFactory.setHost("localhost");
//连接端口;默认5672
connectionFactory.setPort(5672);
//虚拟主机;默认/
connectionFactory.setVirtualHost("/itcast");
//用户名;默认guest
connectionFactory.