在linux中使用Docker创建RabbitMQ的容器。
Docker安装过程
下载Docker-CE rpm安装包
Index of linux/centos/7/x86_64/stable/Packages/
注意下载版本要和操作系统版本对应。
docker-ce-18.06.0.ce-3.el7.x86_64.rpm
安装Docker
上传 docker-ce-18.06.0.ce-3.el7.x86_64.rpm 到opt
执行命令: yum install -y docker-ce-18.06.0.ce-3.el7.x86_64.rpm
注意:确保linux服务器处于联网状态。
常见问题:
当用yum安装时报错。。。
Error: Package: glibc-headers-2.17-196.el7_4.2.x86_64 (ultra-centos-7.4-updates)
Requires: glibc = 2.17-196.el7_4.2
Installed: glibc-2.17-222.el7.x86_64 (installed)
glibc = 2.17-222.el7
Available: glibc-2.17-196.el7.x86_64 (ultra-centos-7.4-base)
glibc = 2.17-196.el7
Available: glibc-2.17-196.el7_4.2.x86_64 (ultra-centos-7.4-updates)
glibc = 2.17-196.el7_4.2
Error: Package: gcc-4.8.5-16.el7_4.2.x86_64 (ultra-centos-7.4-updates)
Requires: libgomp = 4.8.5-16.el7_4.2
Installed: libgomp-4.8.5-28.el7_5.1.x86_64 (installed)
libgomp = 4.8.2-16.el7_5
libgomp = 4.8.5-28.el7_5.1
Available: libgomp-4.8.5-16.el7.x86_64 (ultra-centos-7.4-base)
libgomp = 4.8.5-16.el7
libgomp = 4.8.2-16.el7
Available: libgomp-4.8.5-16.el7_4.1.x86_64 (ultra-centos-7.4-updates)
libgomp = 4.8.5-16.el7_4.1
libgomp = 4.8.2-16.el7_4
Available: libgomp-4.8.5-16.el7_4.2.x86_64 (ultra-centos-7.4-updates)
libgomp = 4.8.5-16.el7_4.2
libgomp = 4.8.2-16.el7_4
Error: Package: glibc-devel-2.17-196.el7_4.2.x86_64 (ultra-centos-7.4-updates)
Requires: glibc = 2.17-196.el7_4.2
Installed: glibc-2.17-222.el7.x86_64 (installed)
glibc = 2.17-222.el7
Available: glibc-2.17-196.el7.x86_64 (ultra-centos-7.4-base)
glibc = 2.17-196.el7
Available: glibc-2.17-196.el7_4.2.x86_64 (ultra-centos-7.4-updates)
glibc = 2.17-196.el7_4.2
You could try using --skip-broken to work around the problem
You could try running: rpm -Va --nofiles --nodigest
解决办法:
wget -O /etc/yum.repos.d/CentOS-Base.repo http://mirrors.aliyun.com/repo/Centos-7.repo
sed -i 's/$releasever/7/g' /etc/yum.repos.d/CentOS-Base.repo
、yum repolist
启动与停止Docker
启动docker:systemctl start docker
停止docker:systemctl stop docker
重启docker:systemctl restart docker
查看docker状态:systemctl status docker
//设置docker服务开机自启动 systemctl enable docker
验证Docker是否安装成功
执行命令:docker info
查看返回信息,能否查看到Docker相关信息
到此,Docker安装完毕!
RabbitMQ安装
1 docker镜像下载
docker pull rabbitmq:management
注意:如果docker pull rabbitmq 后面不带management,启动rabbitmq后是无法打开管理界面的,所以我们要下载带management插件的rabbitmq.
2.查看docker镜像
docker images
3.创建rabbitmq容器
docker run -di -p 5672:5672 -p 15672:15672 --name rabbitmq rabbitmq:management
4.访问管理界面
访问管理界面的地址就是 http://主机或虚拟机ip:15672,可以使用默认的账户登录,用户名和密码都guest
项目构建
本人使用springBoot项目父依赖2.6.2版本,下面为mq和mysql的版本依赖:
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-amqp</artifactId>
<version>2.6.2</version>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>5.1.32</version>
</dependency>
<!-- 连接池 -->
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid</artifactId>
<version>1.1.14</version>
</dependency>
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>javax.servlet-api</artifactId>
<version>3.1.0</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
</dependency>
配置application.yml
server:
port: 9090
spring:
datasource:
driver-class-name: com.mysql.jdbc.Driver
url: jdbc:mysql://localhost:3306/uedu?useUnicode=true&characterEncoding=UTF-8&serverTimezone=GMT%2B8
username: root
password: 123456
type: com.alibaba.druid.pool.DruidDataSource
rabbitmq:
host: 192.168.157.128 #mq所在主机或虚拟机ip
port: 5672
username: guest
password: guest
listener:
simple:
prefetch: 1 #每次只处理一个信息
concurrency: 10 #初始化并发数量
max-concurrency: 20 #设置最大并发数
default-requeue-rejected: false
acknowledge-mode: manual # ack确认开启
retry:
enabled: true #开启消费者进行重试
max-attempts: 5 #最大重试次数
initial-interval: 3000 #重试时间间隔
type: simple
publisher-confirm-type: correlated #确认消息已发送到交换机(Exchange) # 消息确认(ACK)
publisher-returns: true #确认消息已发送到队列(Queue)
template:
mandatory: true #场景1消息找不到对应的Exchange。场景2找到了Exchange但是找不到对应的Queue。 操作:自动删除(false)或 返回到客户端(true)。
创建一个MQ的配置类,创建MQ的业务交换机,业务队列,死信交换机,死信队列,交换机队列绑定,配置过期时间,死信交换机,持久化。代码中有解释。
package org.example.config;
import lombok.extern.slf4j.Slf4j;
import org.example.common.Constants;
import org.example.service.RabbitMqMessageService;
import org.springframework.amqp.core.*;
import org.springframework.amqp.rabbit.connection.ConnectionFactory;
import org.springframework.amqp.rabbit.connection.CorrelationData;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import java.util.HashMap;
import java.util.Map;
/**
* Feng, Ge 2020/8/15 20:21
*/
@Configuration
@Slf4j
public class RabbitMQConfig {
@Autowired
private RetryCache retryCache;
public static final String BUSINESS_EXCHANGE_NAME = "dead.letter.demo.simple.business.exchange";
public static final String BUSINESS_QUEUEA_NAME = "dead.letter.demo.simple.business.queuea";
public static final String BUSINESS_QUEUEB_NAME = "dead.letter.demo.simple.business.queueb";
public static final String DEAD_LETTER_EXCHANGE = "dead.letter.demo.simple.deadletter.exchange";
public static final String DEAD_LETTER_QUEUEA_ROUTING_KEY = "dead.letter.demo.simple.deadletter.queuea.routingkey";
public static final String DEAD_LETTER_QUEUEB_ROUTING_KEY = "dead.letter.demo.simple.deadletter.queueb.routingkey";
public static final String DEAD_LETTER_QUEUEA_NAME = "dead.letter.demo.simple.deadletter.queuea";
public static final String DEAD_LETTER_QUEUEB_NAME = "dead.letter.demo.simple.deadletter.queueb";
// 声明业务Exchange 广播模式FanoutExchange
@Bean("businessExchange")
public FanoutExchange businessExchange(){
// 第一个参数 交换机的名字,
// 第二个参数 是否持久化。durable
// 第三个参数 是否自动删除 autoDelete
return new FanoutExchange(BUSINESS_EXCHANGE_NAME,true,false);
}
// 声明死信Exchange 定向模式DirectExchange
@Bean("deadLetterExchange")
public DirectExchange deadLetterExchange(){
return new DirectExchange(DEAD_LETTER_EXCHANGE,true,false);
}
// 声明业务队列A
@Bean("businessQueueA")
public Queue businessQueueA(){
Map<String, Object> args = new HashMap<>(3);
// x-dead-letter-exchange 这里声明当前队列绑定的死信交换机
args.put("x-dead-letter-exchange", DEAD_LETTER_EXCHANGE);
// x-dead-letter-routing-key 这里声明当前队列的死信路由key
args.put("x-dead-letter-routing-key", DEAD_LETTER_QUEUEA_ROUTING_KEY);
// x-message-ttl 这里生命当前队列的消息超时时间,6s
args.put("x-message-ttl",6000);
// .durable持久化
return QueueBuilder.durable(BUSINESS_QUEUEA_NAME).withArguments(args).build();
}
// 声明业务队列B
@Bean("businessQueueB")
public Queue businessQueueB(){
Map<String, Object> args = new HashMap<>(3);
// x-dead-letter-exchange 这里声明当前队列绑定的死信交换机
args.put("x-dead-letter-exchange", DEAD_LETTER_EXCHANGE);
// x-dead-letter-routing-key 这里声明当前队列的死信路由key
args.put("x-dead-letter-routing-key", DEAD_LETTER_QUEUEB_ROUTING_KEY);
args.put("x-message-ttl",6000);
return QueueBuilder.durable(BUSINESS_QUEUEB_NAME).withArguments(args).build();
}
// 声明死信队列A
@Bean("deadLetterQueueA")
public Queue deadLetterQueueA(){
Map<String, Object> args = new HashMap<>();
// 设置死信队列长度 100M
args.put("x-max-length-bytes", 100*1024*1024);
args.put("x-message-ttl",6000);
return QueueBuilder.durable(DEAD_LETTER_QUEUEA_NAME).withArguments(args).build();
// 另一种队列创建方法
// return new Queue(DEAD_LETTER_QUEUEA_NAME,true,false,false);
}
// 声明死信队列B
@Bean("deadLetterQueueB")
public Queue deadLetterQueueB(){
return new Queue(DEAD_LETTER_QUEUEB_NAME,true,false,false);
}
// 声明业务队列A绑定关系
@Bean
public Binding businessBindingA(@Qualifier("businessQueueA") Queue queue,
@Qualifier("businessExchange") FanoutExchange exchange){
return BindingBuilder.bind(queue).to(exchange);
}
// 声明业务队列B绑定关系
@Bean
public Binding businessBindingB(@Qualifier("businessQueueB") Queue queue,
@Qualifier("businessExchange") FanoutExchange exchange){
return BindingBuilder.bind(queue).to(exchange);
}
// 声明死信队列A绑定关系
@Bean
public Binding deadLetterBindingA(@Qualifier("deadLetterQueueA") Queue queue,
@Qualifier("deadLetterExchange") DirectExchange exchange){
// 因为死信队列是定向模式 .with() 指定routing key
return BindingBuilder.bind(queue).to(exchange).with(DEAD_LETTER_QUEUEA_ROUTING_KEY);
}
// 声明死信队列B绑定关系
@Bean
public Binding deadLetterBindingB(@Qualifier("deadLetterQueueB") Queue queue,
@Qualifier("deadLetterExchange") DirectExchange exchange){
return BindingBuilder.bind(queue).to(exchange).with(DEAD_LETTER_QUEUEB_ROUTING_KEY);
}
// rabbitMq的回调函数,返回消息到达交换机,到达队列的回调
@Bean
public RabbitTemplate createRabbitTemplate(ConnectionFactory connectionFactory)
{
RabbitTemplate rabbitTemplate = new RabbitTemplate();
rabbitTemplate.setConnectionFactory(connectionFactory);
//设置开启Mandatory,才能触发回调函数,无论消息推送结果怎么样都强制调用回调函数
rabbitTemplate.setMandatory(true);
//确认消息送到交换机(Exchange)回调
rabbitTemplate.setConfirmCallback(new RabbitTemplate.ConfirmCallback()
{
@Override
public void confirm(CorrelationData correlationData, boolean ack, String cause)
{
System.out.println("\n确认消息送到交换机(Exchange)结果:");
System.out.println("相关数据:" + correlationData);
System.out.println("是否成功:" + ack);
System.out.println("错误原因:" + cause);
// 使用ack确认机制,到达ack为true,
if (!ack){
// 发送失败,会调用消息重发,这里显示信息。
log.info("send message failed: " + cause + correlationData.toString());
}else {
//成功调用自己写的retryCache类,删除保存的消息id。
System.out.println("删除correlationData.getId()"+correlationData.getId());
retryCache.del(Long.valueOf(correlationData.getId()));
}
}
});
//确认消息送到队列(Queue)回调
rabbitTemplate.setReturnsCallback(new RabbitTemplate.ReturnsCallback()
{
@Override
public void returnedMessage(ReturnedMessage returnedMessage)
{
System.out.println("\n确认消息送到队列(Queue)结果:");
System.out.println("发生消息:" + returnedMessage.getMessage());
System.out.println("回应码:" + returnedMessage.getReplyCode());
System.out.println("回应信息:" + returnedMessage.getReplyText());
System.out.println("交换机:" + returnedMessage.getExchange());
System.out.println("路由键:" + returnedMessage.getRoutingKey());
try {
Thread.sleep(Constants.ONE_SECOND);
} catch (InterruptedException e) {
e.printStackTrace();
}
log.info("send message failed: " + returnedMessage.getReplyCode() + " " + returnedMessage.getReplyText());
rabbitTemplate.send(returnedMessage.getMessage());
}
});
return rabbitTemplate;
}
}
MQ的重发类与静态常量类
public class Constants {
//线程数
public final static int THREAD_COUNT = 5;
//处理间隔时间
//mils
public final static int INTERVAL_MILS = 0;
//consumer失败后等待时间(mils)
public static final int ONE_SECOND = 1 * 1000;
//异常sleep时间(mils)
public static final int ONE_MINUTE = 1 * 6 * 1000;
//MQ消息retry时间
public static final int RETRY_TIME_INTERVAL = ONE_MINUTE;
//MQ消息有效时间
public static final int VALID_TIME = ONE_MINUTE;
}
package org.example.common;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
/**
* Created by littlersmall on 2018/5/16.
*/
@NoArgsConstructor
@AllArgsConstructor
@Data
public class MessageWithTime {
private long id;
private long time;
private Object message;
}
package org.example.config;
import lombok.extern.slf4j.Slf4j;
import org.example.common.Constants;
import org.example.common.DetailRes;
import org.example.common.MessageWithTime;
import org.example.pojo.RabbitMqFailMessage;
import org.example.pojo.RabbitMqMessage;
import org.example.quartz.MqFailScheduler;
import org.example.service.BusinessMessageSender;
import org.example.service.RabbitMqFailService;
import org.example.service.RabbitMqMessageService;
import org.springframework.amqp.AmqpException;
import org.springframework.amqp.rabbit.connection.CorrelationData;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import java.util.Date;
import java.util.Map;
import java.util.concurrent.ConcurrentSkipListMap;
import java.util.concurrent.atomic.AtomicLong;
@Slf4j
@Component
public class RetryCache {
@Autowired
// 把MQ发送的消息保存在数据库的服务类 需要自己简单写下,
private RabbitMqMessageService messageService;
@Autowired
// 把MQ发送失败的消息保存在数据库的服务类 需要自己简单写下,
private RabbitMqFailService rabbitMqFailService;
// 这是Mq消息发送服务类
private BusinessMessageSender sender;
private boolean stop = false;
private Map<Long, MessageWithTime> map = new ConcurrentSkipListMap<>();
private AtomicLong id = new AtomicLong();
public static boolean state = false;
// 接口消息发送时接受BusinessMessageSender服务,启动startRetry()方法。
public void setSender(BusinessMessageSender sender) {
this.sender = sender;
System.out.println("startRetry();开启");
startRetry();
}
public long generateId() {
return id.incrementAndGet();
}
// 发送MQ时把MQ的id与信息保存在map中。
public void add(MessageWithTime messageWithTime) {
map.putIfAbsent(messageWithTime.getId(), messageWithTime);
System.out.println("map:++++"+map);
}
// 发送成功删除map中那个id的MQ消息
public void del(long id) {
map.remove(id);
}
private void startRetry() {
new Thread(() ->{
while (!stop) {
try {
Thread.sleep(Constants.RETRY_TIME_INTERVAL);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("map:++++"+map);
long now = System.currentTimeMillis();
for (Map.Entry<Long, MessageWithTime> entry : map.entrySet()) {
System.out.println("entry:++++"+entry);
MessageWithTime messageWithTime = entry.getValue();
if (null != messageWithTime) {
System.out.println("messageWithTime:++++"+messageWithTime);
// 初次发送时间加3次重新发送间隔时间,如果大于当前时间,不发送,删除。 只发送三次
if (messageWithTime.getTime() + 6 * Constants.VALID_TIME < now) {
log.info("send message {} failed after 3 min ", messageWithTime);
//删除数据库数据 这是我的服务类,这段代码,你可以不要,或自己简单写下只是简单的数据库增删改
RabbitMqMessage rabbitMqMessage = new RabbitMqMessage();
rabbitMqMessage.setId(messageWithTime.getId());
rabbitMqMessage.setMessage(messageWithTime.getMessage().toString());
rabbitMqMessage.setIsConsume(0);
rabbitMqMessage.setIsDelete(1); // 设置可用为1 不可用表示删除
Long aLong = messageService.saveMessage(rabbitMqMessage);
// 3次重发后将还没有发出去的保存到发送失败数据库表,用quartz定时再发送一次 这是我的服务类,这段代码,你可以不要,或自己简单写下
RabbitMqFailMessage rabbitMqFailMessage = new RabbitMqFailMessage();
rabbitMqFailMessage.setId(messageWithTime.getId());
rabbitMqFailMessage.setMessage(messageWithTime.getMessage().toString());
rabbitMqFailMessage.setIsSend(0); // 设置可用为0 表示可定时发送
rabbitMqFailMessage.setCreateTime(new Date());
rabbitMqFailMessage.setIsSuccess(0);
Long aLong1 = rabbitMqFailService.saveFailMessage(rabbitMqFailMessage);
if (aLong != null && aLong1 != null){
del(entry.getKey());
}
// 初次发送时间+重新发送间隔时间,如果大于当前时间。重新发送
} else if (messageWithTime.getTime() + Constants.VALID_TIME < now) {
Boolean aBoolean = sender.retryMsg(messageWithTime);
}
}
}
}
}).start();
}
}
mq所涉及到的两个数据库表:
消息发送表
消息发送失败表
好,现在咱们的消息队列的重发也创建完成了。接下来实现下简单的监听。
创建监听类
package org.example.listener;
import lombok.extern.slf4j.Slf4j;
import org.example.pojo.RabbitMqMessage;
import org.example.service.RabbitMqMessageService;
import org.springframework.amqp.rabbit.annotation.RabbitListener;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.amqp.core.Message;
import com.rabbitmq.client.Channel;
import org.springframework.transaction.annotation.Isolation;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;
import java.io.IOException;
@Component
@Slf4j
public class BusinessMessageReceiver {
@Autowired
// Mq发送的消息保存到数据库服务类
private RabbitMqMessageService messageService;
public static final String BUSINESS_QUEUEA_NAME = "dead.letter.demo.simple.business.queuea";
public static final String BUSINESS_QUEUEB_NAME = "dead.letter.demo.simple.business.queueb";
// 监听的队列名
@RabbitListener(queues = BUSINESS_QUEUEA_NAME)
public void receiveA(Message message, Channel channel) throws IOException {
String msg = new String(message.getBody());
log.info("收到业务消息A:{}", msg);
boolean ack = true;
Exception exception = null;
try {
// 模拟死信队列,发送deadletter信息,模拟消息出错。
if (msg.contains("deadletter")){
throw new RuntimeException("dead letter exception");
}
if (msg != null && msg.length()>0){
// msg = msg + "@"+消息id; 简单定义发送消息时。消息id与消息用@分割
String[] split = msg.split("@");
String id = split[1];
// 查询数据库看这个消息是否存在可用
RabbitMqMessage byId = messageService.findById(Long.parseLong(id));
System.out.println("消息A:{}"+byId);
if (byId != null && byId.getIsConsume() == 0 && byId.getIsDelete() == 0){
byId.setIsConsume(1);
messageService.saveMessage(byId);
log.info("处理完成业务消息A:{}", msg);
}else {
log.error("消息已消费,或数据库查不到。");
// basic.nack方法为不确认deliveryTag对应的消息,第二个参数是否应用于多消息,第三个参数是否requeue,true则重新入队列,否则丢弃或者进入死信队列。
channel.basicNack(message.getMessageProperties().getDeliveryTag(),false,false);
}
}
} catch (Exception e){
ack = false;
exception = e;
}
if (!ack){
log.error("消息消费发生异常,error msg:{}", exception.getMessage(), exception);
channel.basicNack(message.getMessageProperties().getDeliveryTag(), false, false);
} else {
channel.basicAck(message.getMessageProperties().getDeliveryTag(), false);
}
}
@RabbitListener(queues = BUSINESS_QUEUEB_NAME)
public void receiveB(Message message, Channel channel) throws IOException {
String msg = new String(message.getBody());
log.info("收到业务消息B:{}", msg);
if (msg != null && msg.length()>0){
String[] split = msg.split("@");
String id = split[1];
RabbitMqMessage byId = messageService.findById(Long.parseLong(id));
System.out.println("消息B :{}"+byId);
if (byId != null && byId.getIsConsume() == 0 && byId.getIsDelete() == 0){
byId.setIsConsume(1);
messageService.saveMessage(byId);
log.info("处理完成业务消息B:{}", msg);
}else {
log.error("消息已消费,或数据库查不到。");
channel.basicNack(message.getMessageProperties().getDeliveryTag(),false,false);
}
}
channel.basicAck(message.getMessageProperties().getDeliveryTag(), false);
}
}
发送消息服务类:
package org.example.service;
import lombok.extern.slf4j.Slf4j;
import org.example.common.DetailRes;
import org.example.common.MessageWithTime;
import org.example.config.RetryCache;
import org.example.pojo.RabbitMqMessage;
import org.springframework.amqp.AmqpException;
import org.springframework.amqp.core.Message;
import org.springframework.amqp.core.MessageBuilder;
import org.springframework.amqp.rabbit.connection.CorrelationData;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import java.util.UUID;
@Component
@Slf4j
public class BusinessMessageSender {
public static final String BUSINESS_EXCHANGE_NAME = "dead.letter.demo.simple.business.exchange";
@Autowired
private RabbitTemplate rabbitTemplate;
@Autowired
private RabbitMqMessageService messageService;
@Autowired
private RetryCache retryCache;
public DetailRes sendMsg(String msg){
try {
log.info("message conent:"+msg);
//保存数据库
RabbitMqMessage messageEntity = new RabbitMqMessage(msg.toString(),0);
messageEntity.setIsDelete(0);
// 将消息保存到数据库,并把数据库中这条消息的id设置成MQ发送这条消息的id
Long aLong = messageService.saveMessage(messageEntity);
msg = msg + "@"+aLong;
long time = System.currentTimeMillis();
MessageWithTime messageWithTime = new MessageWithTime(aLong, time, msg);
retryCache.add(messageWithTime);
//发送消息 第一个参数交换机名,第二个routingKey,第三个 消息 第四个 消息id
rabbitTemplate.convertSendAndReceive(BUSINESS_EXCHANGE_NAME, "", msg,
new CorrelationData(String.valueOf(messageWithTime.getId())));
} catch (AmqpException e) {
return new DetailRes(false,"");
}
return new DetailRes(true,"");
}
}
Controller层
package org.example.controller;
import org.example.common.DetailRes;
import org.example.config.RetryCache;
import org.example.service.BusinessMessageSender;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
@RequestMapping("rabbitmqTest")
@RestController
@CrossOrigin
public class RabbitMQMsgController {
@Autowired
private BusinessMessageSender sender;
@Autowired
RetryCache retryCache;
@GetMapping("sendMsg")
public Boolean sendMsg(@RequestParam(value = "msg") String msg){
DetailRes detailRes = sender.sendMsg(msg);
System.out.println("detailRes::::"+detailRes);
if (RetryCache.state == false){
RetryCache.state = true;
retryCache.setSender(sender);
}
return detailRes.isSuccess();
}
}
接下来就可以启动springBoot项目的启动项了。
正常启动后,打开网页:http://localhost:9090/rabbitmqTest/sendMsg/?msg=fsd回车
开发控制台会收到如下:发送MQ
接受MQ
http://MQip地址:15672/#/exchanges
打开MQ的网页,点击Exchanges。 Features标签下的D就是持久化标志。其他信息也可见