1.首先介绍一下RabbitMQ 的工作流程:
黄色的圈圈就是我们的消息推送服务,将消息推送到 中间方框里面也就是 rabbitMq的服务器,然后经过服务器里面的交换机、队列等各种关系将数据处理入列后,最终右边的蓝色圈圈消费者获取对应监听的消息。
生产者往交换机中发送消息;
交换机通过规则绑定队列,通过路由键将消息存储到队列中;
消费者获取队列中的消息进行消费;
2.在SpringBoot中集成rabbitmq
1.在springboot中添加依赖
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
2.在application.properties中配置MQ
#RabbitMQ的IP地址
spring.rabbitmq.host=192.168.33.xx
#rabbitmq服务端口号
spring.rabbitmq.port=5672
#rabbitmq虚拟主机
spring.rabbitmq.virtual-host=/
#用户名
spring.rabbitmq.username=guest
#密码
spring.rabbitmq.password=guest
#预先载入数量,默认250为一批
spring.rabbitmq.listener.simple.prefetch=1
# 自动应答 (设置为manual为手动应答,当设置后,下面配合全部失效)
spring.rabbitmq.listener.simple.acknowledge-mode=auto
# 开启自动重试
spring.rabbitmq.listener.simple.retry.enabled=true
# 最大重试次数
spring.rabbitmq.listener.simple.retry.max-attempts=5
# 最大间隔时间
spring.rabbitmq.listener.simple.retry.max-interval=20000ms
# 重试间隔时间
spring.rabbitmq.listener.simple.retry.initial-interval=3000ms
# 乘子 重试间隔*乘子 得出下次重试间隔 3s 6s 12s 24s 此处24s>20s 走20s
spring.rabbitmq.listener.simple.retry.multiplier=2
# 重试次数超过上面的设置之后是否丢弃(false不丢弃时需要写相应代码将该信息加入到死信队列)
spring.rabbitmq.listener.simple.default-requeue-rejected=false
3.配置交换机,队列和bindingKey
import org.springframework.amqp.core.*;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@Configuration
public class RabbitConfig {
@Bean
public DirectExchange directExchange(){
return new DirectExchange("DirectExchange-01",true,false);
}
@Bean
public Queue directQueue(){
return QueueBuilder.durable("DirectQueue-01").build();
}
@Bean
public Binding binding(){
return BindingBuilder.bind(directQueue()).to(directExchange()).with("Direct-RoutingKey-01");
}
}
4.编写消费者代码
消费者接收消息的过程:
- 消费者连接到RabbitMQ Broker ,建立一个连接(Connection ) ,开启一个信道(Channel) 。
- 消费者向RabbitMQ Broker 请求消费相应队列中的消息,可能会设置相应的回调函数, 以及做一些准备工作
- 等待RabbitMQ Broker 回应并投递相应队列中的消息, 消费者接收消息。
- 消费者确认( ack) 接收到的消息。
- RabbitMQ 从队列中删除相应己经被确认的消息。
- 关闭信道。
- 关闭连接。
package com.example.consumer;
import org.springframework.amqp.core.Message;
import org.springframework.amqp.rabbit.annotation.RabbitHandler;
import org.springframework.amqp.rabbit.annotation.RabbitListener;
import org.springframework.stereotype.Component;
@Component
public class DirectConsumer {
@RabbitHandler
@RabbitListener(queues ="DirectQueue-01" )
public void process(Message message){
String test = new String(message.getBody());
System.out.println(test);
}
}
5.编写生产者代码
生产者发送消息的流程:
- 生产者连接RabbitMQ,建立TCP连接( Connection),开启信道(Channel)
- 生产者声明一个Exchange(交换器),并设置相关属性,比如交换器类型、是否持久化等
- 生产者声明一个队列井设置相关属性,比如是否排他、是否持久化、是否自动删除等
- 生产者通过 bindingKey (绑定Key)将交换器和队列绑定( binding )起来
- 生产者发送消息至RabbitMQ Broker,其中包含 routingKey (路由键)、交换器等信息
- 相应的交换器根据接收到的 routingKey 查找相匹配的队列。
- 如果找到,则将从生产者发送过来的消息存入相应的队列中。
- 如果没有找到,则根据生产者配置的属性选择丢弃还是回退给生产者
- 关闭信道。
- 关闭连接。
import org.springframework.amqp.core.Message;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.stereotype.Component;
import javax.annotation.Resource;
@Component
public class DirectProvider {
@Resource
private RabbitTemplate rabbitTemplate;
public void send(){
Message message = new Message("你好".getBytes());
rabbitTemplate.send("DirectExchange-01","Direct-RoutingKey-01",message);
}
}
6.测试类
package com.example;
import com.example.provider.DirectProvider;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import javax.annotation.Resource;
@SpringBootTest
class APPTests {
@Autowired
DirectProvider directProvider;
@Test
void test() throws InterruptedException {
directProvider.send();
Thread.sleep(5000);
}
}