1.同步和异步有什么差别?
a.快递员送快递,直接送给收件人,是同步操作;
b.员送快递,放快递柜,收件人自己去快递柜收取,是异步操作;

同步操作:

异步操作:


2.为什么需要消息队列?

MQ对比:

2.什么是RabbitMQ

2.1 RabbitMQ安装

2.2 登录后界面

- 生产者-Broker(rabbitMQ)-消费者示意图

- RabbitMQ的模式总述

2.3 HelloWorld级别代码实现- 单个生产者,与MQ连接成功,选个默认交换机,指定单个队列发送,给队列发1条消息; - 单个消费者,与MQ连接成功,选个默认交换机,指定单个队列监听,接收队列里的1条消息;

- 引入依赖

生产者代码
java
import com.rabbitmq.client.*;
import java.io.IOException;
import java.util.HashMap;
import java.util.Map;
public class RabbitMqProducer {
public static void main(String[] args) throws Exception {
// 创建连接工厂
ConnectionFactory connectionFactory = new ConnectionFactory();
// 设置主机地址
connectionFactory.setHost("192.168.200.100");
// 设置连接端口号:默认为 5672
connectionFactory.setPort(5672);
// 虚拟主机名称: 默认为 /
connectionFactory.setVirtualHost("/");
// 设置连接用户名:默认为guest
connectionFactory.setUsername("guest");
// 设置连接密码:默认为guest
connectionFactory.setPassword("123456");
// 创建连接
Connection connection = connectionFactory.newConnection();
// 创建频道
Channel channel = connection.createChannel();
// 声明(创建)队列
// queue 参数1: 队列名称
// durable 参数2: 是否定义持久化队列, 当 MQ 重启之后还在
// exclusive 参数3: 是否独占本次连接, 若独占, 只能有一个消费者监听这个队列且 Connection 关闭时删除这个队列
// autoDelete 参数4: 是否在不使用的时候自动删除队列, 也就是在没有Consumer时自动删除
// arguments 参数5: 队列其它参数
channel.queueDeclare("helloWorld_queue", true, false, false, null);
// 要发送的信息
String message = "你好; 小兔子!";
// 参数1: 交换机名称,如果没有指定则使用默认交换机(名字是空字符串的 Direct 交换机)
// 参数2: 路由key,简单模式可以传递队列名称
// 参数3: 配置信息
// 参数4: 消息内容
channel.basicPublish("", "helloWorld_queue", null, message.getBytes());
System.out.println("已发送消息: " + message);
// 关闭资源
channel.close();
connection.close();
}
}
消费者代码
java
import com.rabbitmq.client.*;
import java.io.IOException;
public class RabbitMqConsumer {
public static void main(String[] args) throws Exception {
// 1.创建连接工厂
ConnectionFactory factory = new ConnectionFactory();
// 2. 设置参数
factory.setHost("192.168.47.100");
factory.setPort(5672);
factory.setVirtualHost("/");
factory.setUsername("guest");
factory.setPassword("123456");
// 3. 创建连接 Connection
Connection connection = factory.newConnection();
// 4. 创建Channel
Channel channel = connection.createChannel();
// 5. 创建队列
// 如果没有一个名字叫helloWorld_queue的队列,则会创建该队列,如果有则不会创建
// 参数1. queue: 队列名称
// 参数2. durable: 是否持久化。如果持久化,则当MQ重启之后还在
// 参数3. exclusive: 是否独占。
// 参数4. autoDelete: 是否自动删除。当没有Consumer时,自动删掉
// 参数5. arguments: 其它参数。
channel.queueDeclare("helloWorld_queue", true, false, false, null);
// 接收消息
DefaultConsumer 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 {
System.out.println("consumerTag: " + consumerTag);
System.out.println("Exchange: " + envelope.getExchange());
System.out.println("RoutingKey: " + envelope.getRoutingKey());
System.out.println("properties: " + properties);
System.out.println("body: " + new String(body));
}
};
// 参数1. queue: 队列名称
// 参数2. autoAck: 是否自动确认, 类似咱们发短信, 发送成功会收到一个确认消息
// 参数3. callback: 回调对象
// 消费者类似一个监听程序, 主要是用来监听消息
channel.basicConsume("helloWorld_queue", true, consumer);
}
}
- Work Queues 多消费者争抢同一队列里的消息


发布和订阅模式




路由模式(实际开发中用的最多)

主题模式




SpringBoot引入rabbitMQ


- rabbitmq消费端监听器

- 消费者代码

- 生产者代码

消息的可靠性
- 未成功发送到MQ上

- MQ宕机,消息丢失

- 消息没有消费成功

- 解决方案

- 消息确认机制具体操作



备份交换机
