RabbitMQ 简单介绍
同步调用
缺点:拓展性差、性能下降、级联失败
优点:时效性强等待结果后返回。
异步调用
消息发送者:投递消息的人,就是原来的调用方
消息代理:管理、暂存、转发消息,你可以把它理解成微信服务器
消息接收者:接收和处理消息的人,就是原来的服务提供方
优点:解除耦合,拓展性强、无需等待,性能好、故障隔离、缓存消息,流量削峰填谷
缺点:不能立刻得到结果,时效低、不确定下游y业务是否执行成功、业务安全依赖于Broker的可靠性
消息队列工具
简单安装
docker部署镜像
# docker load -i mq.tar
# docker run \
-e RABBITMQ_DEFAULT_USER=cqh \
-e RABBITMQ_DEFAULT_PASS=cqh \
-v mq-plugins:/plugins \
--name mq \
--hostname mq \
-p 15672:15672 \
-p 5672:5672 \
--network hmall \
-d \
rabbitmq:3.8-management
出现
就自己创建一个
# docker network create hmall
进行网络连接
# docker network connect hmall mq
查看没有就运行再查看就有了
# docker start mq
访问
就是你的ip+端口号15672
RabbitMQ Managementhttp://192.168.42.129:15672/
输入账号: cqh 密码: cqh 登录进入
rabbitMQ整体架构
publisher:消息发送者
consumer:消息的消费者
queue:队列,存储消息
exchange:交换机,负责路由消息
virtual-host:虚拟主机,起到数据隔离的作用
简单消息发送
控制台创建简单队列
选择交换机
交换机消息绑定
发送测试
成功
消息查看
数据隔离简单实现
用户添加
结果
退出用cqh1登录
创建虚拟主机
效果
java控制
Queuing Protocol,是用于在应用程序Advanced Message之间传递业务消息的开放标准。该协议与语言和平台无关,更符合微服务中独立性的要求。
Spring AMQP是基于AMQP协议定义的一套API规范,提供了模板来发送和接收消息。包含两部分,其中spring-amqp是基础抽象,spring-rabbit是底层的默认实现。
测试
1、引入依赖
<!--AMQP依赖,包含RabbitMQ-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-amqp</artifactId>
</dependency>
父依赖
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>cn.itcast.demo</groupId>
<artifactId>mq-demo</artifactId>
<version>1.0-SNAPSHOT</version>
<modules>
<module>publisher</module>
<module>consumer</module>
</modules>
<packaging>pom</packaging>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.7.12</version>
<relativePath/>
</parent>
<properties>
<maven.compiler.source>8</maven.compiler.source>
<maven.compiler.target>8</maven.compiler.target>
</properties>
<dependencies>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
</dependency>
<!--AMQP依赖,包含RabbitMQ-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-amqp</artifactId>
</dependency>
<!--单元测试-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
</dependency>
<!--Jackson-->
<dependency>
<groupId>com.fasterxml.jackson.dataformat</groupId>
<artifactId>jackson-dataformat-xml</artifactId>
</dependency>
</dependencies>
</project>
总模块
发送模块
2、配置rabbitMQ服务端信息
application.yml
logging:
pattern:
dateformat: MM-dd HH:mm:ss:SSS
spring:
rabbitmq:
host: 192.168.42.129 # 主机名
port: 5672 # 端口
virtual-host: /cqh1 # 虚拟主机
username: cqh1 # 用户名
password: cqh1 # 密码
listener:
simple:
prefetch: 1
创建队列
3、消息发送
测试代码消息发送
@Autowired
private RabbitTemplate rabbitTemplate;
@Test
void testSendMessage2Queue() {
// 队列名称
String queueName = "simple.queue";
// 消息
String msg = "hello, amqp!";
// 发送消息
rabbitTemplate.convertAndSend(queueName, msg);
}
查看发送成功
4、消息接收
监听模块消息接收
添加监听器
@Slf4j
@Component
public class MqListener {
@RabbitListener(queues = "simple.queue")
public void listenSimpleQueue(String msg){
System.out.println("消费者收到了simple.queue的消息:【" + msg +"】");
}
}
yml配置
logging:
pattern:
dateformat: MM-dd HH:mm:ss:SSS
spring:
rabbitmq:
host: 192.168.42.129
port: 5672
virtual-host: /cqh1
username: cqh1
password: cqh1
再次从 消息发送模块中发送测试信息然后可以在监听模块的控制台中看到消息的打印
新增队列
接收模块新增监听代码
@RabbitListener(queues = "work.queue")
public void listenWorkQueue1(String msg) throws InterruptedException {
System.out.println("消费者1 收到了 work.queue的消息:【" + msg +"】");
}
@RabbitListener(queues = "work.queue")
public void listenWorkQueue2(String msg) throws InterruptedException {
System.err.println("消费者2 收到了 work.queue的消息...... :【" + msg +"】");
}
发送模块测试代码新增
@Test
void testWorkQueue() throws InterruptedException {
String queueName = "work.queue";
for (int i = 1; i <= 50; i++) {
String msg = "hello, worker, message_" + i;
rabbitTemplate.convertAndSend(queueName, msg);
Thread.sleep(20);
}
}
默认平均发送轮询发送
修改接收休眠时间模拟消息处理能力
@RabbitListener(queues = "work.queue")
public void listenWorkQueue1(String msg) throws InterruptedException {
System.out.println("消费者1 收到了 work.queue的消息:【" + msg +"】");
Thread.sleep(20);
}
@RabbitListener(queues = "work.queue")
public void listenWorkQueue2(String msg) throws InterruptedException {
System.err.println("消费者2 收到了 work.queue的消息...... :【" + msg +"】");
Thread.sleep(200);
}
消息推送机制能者多劳
消息接收模块的yml加上
变为
logging:
pattern:
dateformat: MM-dd HH:mm:ss:SSS
spring:
rabbitmq:
host: 192.168.42.129
port: 5672
virtual-host: /cqh1
username: cqh1
password: cqh1
listener:
simple:
prefetch: 1
测试结果
Fanout交换机
Fanout Exchange 会将接收到的消息广播到每一个跟其绑定的queue,所以也叫广播模式
Fanout:广播
Direct:定向
Topic:话题