springboot整合rabbitmq
添加rabbitmq的依赖
<?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>com.cslg</groupId>
<artifactId>rabbitTest</artifactId>
<version>1.0-SNAPSHOT</version>
<parent>
<artifactId>spring-boot-starter-parent</artifactId>
<groupId>org.springframework.boot</groupId>
<version>2.7.6</version>
</parent>
<properties>
<maven.compiler.source>8</maven.compiler.source>
<maven.compiler.target>8</maven.compiler.target>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<!-- 添加rabbitmq的依赖-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-amqp</artifactId>
</dependency>
</dependencies>
</project>
编写配置文件
spring:
rabbitmq:
host: localhost #设置主机地址
username: guest #设置用户名
password: guest #设置密码
virtual-host: / #设置虚拟路径
port: 5672 #设置端口号
编写配置类
package com.cslg;
import com.rabbitmq.client.Channel;
import org.springframework.amqp.core.AcknowledgeMode;
import org.springframework.amqp.core.Message;
import org.springframework.amqp.core.MessageListener;
import org.springframework.amqp.core.ReturnedMessage;
import org.springframework.amqp.rabbit.connection.CachingConnectionFactory;
import org.springframework.amqp.rabbit.connection.ConnectionFactory;
import org.springframework.amqp.rabbit.connection.CorrelationData;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.amqp.rabbit.listener.SimpleMessageListenerContainer;
import org.springframework.amqp.rabbit.listener.api.ChannelAwareMessageListener;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import javax.annotation.Resource;
/**
* @author wuqirui.
* @date 2023/3/16 15:15
*/
@Configuration
public class RabbitConfig {
// 创建连接工厂
@Bean
public ConnectionFactory connectionFactory(){
CachingConnectionFactory connectionFactory = new CachingConnectionFactory();
connectionFactory.setHost("localhost");
connectionFactory.setUsername("guest");
connectionFactory.setPassword("guest");
connectionFactory.setVirtualHost("/");
connectionFactory.setPort(5672);
// 设置生产者到rabbitmq之间的消息传递需要进行确认
connectionFactory.setPublisherConfirmType(CachingConnectionFactory.ConfirmType.SIMPLE);
return connectionFactory;
}
// 创建对应的rabbitmq的模板
@Bean
public RabbitTemplate rabbitTemplate() {
RabbitTemplate rabbitTemplate = new RabbitTemplate();
// 设置生产者发送消息失败的回调函数
rabbitTemplate.setConfirmCallback(new RabbitTemplate.ConfirmCallback() {
@Override
public void confirm(CorrelationData correlationData, boolean ack, String cause) {
if (ack){
// 发送成功
}
else{
// 发送失败,并进行相应的操作
}
}
});
// 设置开启路由失败通知
rabbitTemplate.setMandatory(true);
// 设置路由失败的函数
rabbitTemplate.setReturnsCallback(new RabbitTemplate.ReturnsCallback() {
@Override
public void returnedMessage(ReturnedMessage returnedMessage) {
// 进行路由失败后的相关操作
}
});
return rabbitTemplate;
}
// 创建一个队列消费者
@Resource
private ConnectionFactory connectionFactory;
@Bean
public SimpleMessageListenerContainer simpleMessageListenerContainer(){
SimpleMessageListenerContainer listenerContainer = new SimpleMessageListenerContainer(connectionFactory);
// 设置要监听的队列
listenerContainer.setQueueNames("设置要监听的队列");
// 设置手动提交
listenerContainer.setAcknowledgeMode(AcknowledgeMode.MANUAL);
// 设置对应的消费方法
listenerContainer.setMessageListener(new ChannelAwareMessageListener() {
@Override
public void onMessage(Message message, Channel channel) throws Exception {
// 获取消息后要做哪些事情
// 业务处理成功后的相关操作
channel.basicAck(message.getMessageProperties().getDeliveryTag(),false);//将已经消费的消息从任务队列中移除
// 如果出现了异常,设置此消息没有消费成功,需要重新排队,当然如果多次重新排队失败这条消息会进入到一个死信队列中然后进行相关的操作
channel.basicNack(message.getMessageProperties().getDeliveryTag(),false,true);
}
});
return listenerContainer;
}
}
以上就是rabbit保证他可靠性的方法:
1、确保生产者发送消息成功
开启connectionFactory.setPublisherConfirmType(CachingConnectionFactory.ConfirmType.SIMPLE);
rabbitTemplate.setConfirmCallback(new RabbitTemplate.ConfirmCallback() {
@Override
public void confirm(CorrelationData correlationData, boolean ack, String cause) {
if (ack){
// 发送成功
}
else{
// 发送失败,并进行相应的操作
}
}
});
// 设置开启路由失败通知
rabbitTemplate.setMandatory(true);
// 设置路由失败的函数
rabbitTemplate.setReturnsCallback(new RabbitTemplate.ReturnsCallback() {
@Override
public void returnedMessage(ReturnedMessage returnedMessage) {
// 进行路由失败后的相关操作
}
});
2、确保消息路由成功
// 设置开启路由失败通知
rabbitTemplate.setMandatory(true);
// 设置路由失败的函数
rabbitTemplate.setReturnsCallback(new RabbitTemplate.ReturnsCallback() {
@Override
public void returnedMessage(ReturnedMessage returnedMessage) {
// 进行路由失败后的相关操作
}
});
3、确保消息、队列、交换机持久化进行持久化
消息持久化:
channel.basicPublish(EXCHANGE_NAME,"",MessageProperties.PERSISTENT_TEXT_PLAIN,message.getBytes());
队列持久化
@Bean("log_exchage")
public Exchange LogExchange() {
return ExchangeBuilder.directExchange(EXHANGE_NAME).durable(true).build();
}
交换机持久化:
@Bean("log_exchage")
public Exchange LogExchange() {
return ExchangeBuilder.directExchange(EXHANGE_NAME).durable(true).build();
}
4、确保消费者消费成功,就是手动提交消费成功确认
@Bean
public SimpleMessageListenerContainer simpleMessageListenerContainer(){
SimpleMessageListenerContainer listenerContainer = new SimpleMessageListenerContainer(connectionFactory);
// 设置要监听的队列
listenerContainer.setQueueNames("设置要监听的队列");
// 设置手动提交
listenerContainer.setAcknowledgeMode(AcknowledgeMode.MANUAL);
// 设置对应的消费方法
listenerContainer.setMessageListener(new ChannelAwareMessageListener() {
@Override
public void onMessage(Message message, Channel channel) throws Exception {
// 获取消息后要做哪些事情
// 业务处理成功后的相关操作
channel.basicAck(message.getMessageProperties().getDeliveryTag(),false);//将已经消费的消息从任务队列中移除
// 如果出现了异常,设置此消息没有消费成功,需要重新排队,当然如果多次重新排队失败这条消息会进入到一个死信队列中然后进行相关的操作
channel.basicNack(message.getMessageProperties().getDeliveryTag(),false,true);
}
});
return listenerContainer;
}
消息重复(其实就是解决幂等性操作)
通过MVCC(多版本控制),就是利用乐观锁进行(利用version版本号)