SprintBoot使用RabbitMQ

SpringBoot实战:RabbitMQ配置与消息确认机制
本文详细介绍了如何在SpringBoot应用中配置RabbitMQ,包括创建交换机(direct、fanout、headers和topic类型)、队列绑定,以及如何使用producer进行消息发送,设置publisher-confirm回调和returns机制。同时涵盖了消费者如何接收并处理消息,重点讲解了消息确认和重试处理的代码实现。

1、配置RabbitMQ

1.1、创建交换机

创建交换机的时候需要指定虚拟主机以及交换机的类型(direct(路由模式)、fanout(广播)、headers、topic)

  • direct:Exchange通过消息携带的路由键来将消息分发到对应的队列中
  • fanout:Exchange将消息分发到所有绑定到交换机的队列中
  • headers:Exchange通过判断消息头的值是否与绑定的值相匹配来分发消息

x-match为any时,消息头的任意一个值匹配就可以满足条件
x-match为all时,消息头的所有值匹配才能满足条件

  • topic:Exchange将满足路由规则的消息分发到对应的队列

1.2、创建队列

创建队列时需要绑定到交换机上

 

2、SpringBoot使用RabbitMQ

2.1、导入依赖

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-amqp</artifactId>
</dependency>

2.2、生产者发送消息

修改配置文件

spring.rabbitmq.host=192.168.1.100
spring.rabbitmq.port=5672
spring.rabbitmq.username=admin
spring.rabbitmq.password=123456

#虚拟主机
spring.rabbitmq.virtual-host=host3

#可以确保消息成功发送到交换器
spring.rabbitmq.publisher-confirm-type=correlated
#可以确保消息在未被队列接收时返回,通常会和mandatory属性配合一起使用
spring.rabbitmq.publisher-returns=true
#指定消息在没有被队列接收时是否强行退回还是直接丢弃
spring.rabbitmq.template.mandatory=true

spring.rabbitmq.publisher-confirm-type 属性用来配置消息发送到交换机之后是否触发回调方法。

有三种确认类型:

  • NONE:禁用发布确认模式,是默认值
  • CORRELATED:发布消息成功到交换器后会触发回调方法
  • SIMPLE:有两种效果,其一效果和CORRELATED值一样会触发回调方法,其二在发布消息成功后使用rabbitTemplate调用waitForConfirms或waitForConfirmsOrDie方法等待broker节点返回发送结果,根据返回结果来判定下一步的逻辑,要注意的点是waitForConfirmsOrDie方法如果返回false则会关闭channel,则接下来无法发送消息到broker;

生产者发布消息

//注入AmqpTemplate
private RabbitTemplate amqpTemplate;
public void sendMessage() {
    //通过convertAndSend方法发送消息
    String msg = "hello world";
    amqpTemplate.convertAndSend("Exchange1", "message", msg);
}

定义回调

@Slf4j
@Component
public class ReturnCallbackService implements RabbitTemplate.ReturnsCallback {
    @Override
    public void returnedMessage(ReturnedMessage returnedMessage) {
        log.info("returnedMessage ===> {}", returnedMessage.getMessage());
    }
}
@Slf4j
@Component
public class ConfirmCallbackService implements RabbitTemplate.ConfirmCallback {
    @Override
    public void confirm(CorrelationData correlationData, boolean ack, String cause) {
        if (!ack) {
            log.error("消息发送异常! cause={}", cause);
        } else {
            log.info("发送者已经收到确认");
        }
    }
}

 消息确认回调方法:

/**
* 设置生产者消息publish-confirm回调函数
*/
amqpTemplate.setConfirmCallback(confirmCallbackService);

//或者
amqpTemplate.setConfirmCallback((correlationData, ack, cause) -> {
    if (!ack) {
        log.error("消息发送异常! Id={}, ack={}, cause={}", correlationData.getId(), ack, cause);
    } else {
        log.info("发送者已经收到确认,Id={}", correlationData.getId());
    }
});

 消息退回回调方法:

/**
* 确保消息发送失败后可以重新返回到队列中
* 注意:yml需要配置 publisher-returns: true
*/
amqpTemplate.setMandatory(true);

/**
* 消息投递到队列失败回调处理
*/
amqpTemplate.setReturnsCallback(returnCallbackService);

2.3、消费者接收消息

修改配置文件

spring.rabbitmq.host=192.168.1.100
spring.rabbitmq.port=5672
spring.rabbitmq.username=admin
spring.rabbitmq.password=123456

#虚拟主机
spring.rabbitmq.virtual-host=host3

#监听异常重试次数
spring.rabbitmq.listener.simple.retry.max-attempts=3
#是否开启重试
spring.rabbitmq.listener.simple.retry.enabled=true
#重试间隔
spring.rabbitmq.listener.simple.retry.initial-interval=3000ms

#是否开启拒绝
spring.rabbitmq.listener.simple.default-requeue-rejected=false
#确认机制 自动 手动
spring.rabbitmq.listener.simple.acknowledge-mode=manual

SpringBoot中提供监听器来监听队列
@RabbitListener注解监听队列
@RabbitHandle注解作用于方法,用来处理消息

@RabbitListener(queues = "queue1")
@RabbitHandler
public void getMsg(String msg, Channel channel, Message message) throws IOException {
    try {
        log.info("message队列收到消息:{}", msg);
        channel.basicAck(message.getMessageProperties().getDeliveryTag(), false);
    }  catch (Exception e) {
        if (message.getMessageProperties().getRedelivered()) {
            log.error("消息已重复处理失败,拒绝再次接收...");
            channel.basicReject(message.getMessageProperties().getDeliveryTag(), false);
        } else {
            log.error("消息即将再次返回队列处理...");
            channel.basicNack(message.getMessageProperties().getDeliveryTag(), false, true);
        }
    }
}

### Spring Boot集成RabbitMQ进行消息传递 #### 一、引入依赖 为了使Spring Boot项目能够与RabbitMQ交互,需在项目的`pom.xml`文件中加入如下依赖: ```xml <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-amqp</artifactId> </dependency> ``` 此操作简化了与AMQP协议兼容的消息中间件如RabbitMQ之间的连接过程[^1]。 #### 二、配置application.yml 接着,在`application.yml`或`.properties`文件内指定RabbitMQ的相关属性。以下是基于YAML格式的一个实例化配置片段: ```yaml spring: rabbitmq: host: localhost # RabbitMQ服务主机名/IP地址 port: 5672 # 默认端口 username: guest # 登录账号 password: guest # 密码 virtual-host: / template: retry: enabled: true # 开启重试机制 max-attempts: 3 # 设置最大尝试次数 listener: simple: concurrency: 3 # 并发消费者数量下限 max-concurrency: 10 # 上限 acknowledge-mode: manual # 手动应答模式 prefetch: 1 # 每次预取一条未处理的信息 ``` 上述配置不仅涵盖了基本的身份验证信息,还包含了关于错误恢复策略以及性能调优方面的设定[^4]。 #### 三、定义消息生产者 创建一个用于向队列发送消息的服务类。这里给出一段简单的Java代码作为示范: ```java import org.springframework.amqp.rabbit.core.RabbitTemplate; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; @Service public class MessageProducer { private final RabbitTemplate rabbitTemplate; @Autowired public MessageProducer(RabbitTemplate rabbitTemplate){ this.rabbitTemplate = rabbitTemplate; } /** * 发送字符串形式的消息到默认交换机下的特定路由键对应的队列里 */ public void sendMessage(String queueName, String messageBody){ System.out.println("Sending message..."); rabbitTemplate.convertAndSend("",queueName,messageBody); System.out.println("Message sent."); } } ``` 这段程序利用了@Autowired注入的方式获取到了核心组件`RabbitTemplate`,并通过它实现了消息的封装与传输功能。 #### 四、构建消息监听器(Consumer) 最后一步是要建立消费端逻辑来接收来自队列的数据流。下面是一个典型的消费者实现方式: ```java import com.rabbitmq.client.Channel; import org.springframework.amqp.core.Message; import org.springframework.amqp.rabbit.listener.api.ChannelAwareMessageListener; import org.springframework.stereotype.Component; @Component public class MessageReceiver implements ChannelAwareMessageListener { @Override public void onMessage(Message message, Channel channel) throws Exception { byte[] body = message.getBody(); try{ // 处理接收到的消息体... long deliveryTag = message.getMessageProperties().getDeliveryTag(); // 成功后手动确认已成功消费该条目 channel.basicAck(deliveryTag , false ); }catch(Exception e){ // 出现异常时拒绝这条记录,并将其重新入队等待下次被其他节点拾起 channel.basicNack(message.getMessageProperties().getDeliveryTag(),false,true); } } } ``` 在这个例子中,当有新数据到达目标队列时会触发`onMessage()`方法执行相应的业务流程;同时支持自定义异常捕获路径以便于灵活应对各种意外情况的发生[^3]。
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值