MQ消息中间件

启动RabbitMQ管理插件

1.启动 RabbitMQ 管理插件。
rabbitmq-plugins enable rabbitmq_management
rabbitmq-server # 直接启动,如果关闭窗⼝或需要在该窗⼝使⽤其他命令时应⽤就会停⽌
rabbitmq-server -detached # 后台启动
rabbitmq-server start # 启⽤服务
rabbitmq-server restart # 重启服务
rabbitmqctl status # 查看状态
rabbitmqctl stop # 停⽌服务
   <!-- RabbitMQ 启动依赖 -->
       <dependency>
           <groupId>org.springframework.boot</groupId>
           <artifactId>spring-boot-starter-amqp</artifactId>
       </dependency>
       <!-- RabbitMQ测试依赖 -->
       <dependency>
           <groupId>org.springframework.amqp</groupId>
           <artifactId>spring-rabbit-test</artifactId>
           <scope>test</scope>
       </dependency>

创建虚拟机。选择【Admin-Virtual Hosts-Add a new virtual host】选项,添加⼀个虚拟机

 yml中导入依赖

spring:
  # 配置RabbitMQ消息中间件连接配置
  rabbitmq:
    host: 192.168.48.67
    port: 5672 # 编程端口(固定)
    username: admin
    password: 123456
    virtual-host: /zhengchunbo # 配置RabbitMQ虚拟主机路径(默认为"/"可以省略)

 

一·Publish/Subscribe(发布订阅模式)

Spring Boot整合RabbitMQ中间件实现消息服务,主要围绕3个部分的⼯作进⾏展开:定制中间件、消息发送者发 送消息、消息消费者接收消息。其中,定制中间件是⽐较麻烦的⼯作,且必须预先定制。下⾯我们以⽤户注册成功 后同时发送邮件通知和短信通知这⼀场景为例, 分别使⽤基于API、基于配置类和基于注解这3种⽅式实现 Publish/Subscribe⼯作模式的整合。

.1基于配置类的⽅式

1.开RabbitMQ消息配置类RabbitMQConfig,在该配置类中使⽤基于配置类的⽅式定制消息发送相关组件。

package com.example.demo.collection.config;
import org.springframework.amqp.core.*;
import org.springframework.amqp.support.converter.Jackson2JsonMessageConverter;
import org.springframework.amqp.support.converter.MessageConverter;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@Configuration
public class RabbitMQConfig {
//    //定制Json格式的消息转化器
  @Bean
    public MessageConverter messageConverter() {
        return new Jackson2JsonMessageConverter();
    }
    /** 使⽤基于配置类的⽅式定制消息中间件 */
    // 1.定义fanout类型的交换器
    @Bean
    public Exchange fanoutExchange() {
        //创建一个fanout交换机 (发布订阅模式)
        return ExchangeBuilder.fanoutExchange("fanout_exchange").build();
    }
    // 2.定义两个不同名称的消息队列
    @Bean
    public Queue fanoutQueueEmail() {
        return new Queue("fanout_queue_email");
    }
    @Bean
    public Queue fanoutQueueSms() {
        return new Queue("fanout_queue_sms");
    }
    // 3.将两个不同名称的消息队列与交换器进⾏绑定
    @Bean
    public Binding bindingEmail() {
                                 //消息队列------>绑定交换机 -------->有没有路由键---------->有没有其他参数
        return BindingBuilder.bind(fanoutQueueEmail()).to(fanoutExchange()).with("").noargs();
    }
    @Bean
    public Binding bindingSms() {
       return BindingBuilder.bind(fanoutQueueSms()).to(fanoutExchange()).with("").noargs();
    }
 }
2.创建名为 com.ytx.service 的包,并在该包下创建⼀个针对 RabbitMQ 消息中间件进⾏消息接收
和处理的业务类 RabbitMQService
package com.ytx.chapter08.service;
import org.springframework.amqp.core.Message;
import org.springframework.amqp.rabbit.annotation.RabbitListener;
import org.springframework.stereotype.Service;
/** RabbitMQ消息接收处理的业务类 */
@Service
public class RabbitMQService {
 /** Publish/Subscribe⼯作模式接收,处理邮件业务 */
 @RabbitListener(queues = "fanout_queue_email")
 public void subConsumerEmail(Message message) {
 byte[] body = message.getBody();
 String msg = new String(body);
 System.out.println("邮件业务接收到消息:" + msg);
 }
 /** Publish/Subscribe⼯作模式接收,处理短信业务 */
 @RabbitListener(queues = "fanout_queue_sms")
 public void subConsumerSms(Message message) {
 byte[] body = message.getBody();
 String msg = new String(body);
 System.out.println("短信业务接收到消息:" + msg);
 }
}

3.发送测试

 @Autowired
   private RabbitTemplate rabbitAvailable;
    @Test
   public  void  subPublisher(){
       User user = new User(6, "张三");
       /**
        *使用RabbitTemplate完成消息的发送:将消息指定发送给特性名称的交换机
        * 参数1: 将消息发送给哪一个交换机
        * 参数2:表示路由键
        * 参数3: 表示发送的消息数据是什么
        */
       rabbitAvailable.convertAndSend("fanout_exchange","",user);

   }

三.2基于注解的⽅式

package com.example.demo.collection.service;


import org.springframework.amqp.core.Message;
import org.springframework.amqp.rabbit.annotation.Exchange;
import org.springframework.amqp.rabbit.annotation.Queue;
import org.springframework.amqp.rabbit.annotation.QueueBinding;
import org.springframework.amqp.rabbit.annotation.RabbitListener;
import org.springframework.stereotype.Service;

@Service
public class RabbitService {
//    
    //发布订阅模式
    //监听队列
    @RabbitListener(bindings = @QueueBinding(
             value =@Queue("fanout_queue_email"),//指定队列
            exchange = @Exchange(value = "fanout_exchange",type ="fanout" )//指定交换机和类型
    ))
    public void subConsumerEmail(Message message) {  //Massage对象用来接收,也可以用Object,User
        byte[] body = message.getBody();
        String msg = new String(body);
        System.out.println("邮件到的消息 = " + msg);
    }


    @RabbitListener(bindings = @QueueBinding(
            value =@Queue("fanout_queue_sms"),//指定队列
            exchange = @Exchange(value = "fanout_exchange",type ="fanout" )//指定交换机和类型
    ))
    public void subConsumerSms(Message message) {  //Massage对象用来接收,也可以用Object,User
        byte[] body = message.getBody();
        String msg = new String(body);
        System.out.println("短信到的消息 = " + msg);
    }
}
使⽤ @RabbitListener 注解及其相关属性定制了两个消息组件的消费者,这两个消费者都接收实体类 User并消费。
@RabbitListener 注解中, bindings 属性⽤于创建并绑定交换器和消息队列组件,需要注意是,
为了能使两个消息组件的消费者接收到实体类 User ,需要我们在定制交换器时将交换器类型 type 设置为 fanout
另 外,bindings 属性的 @QueueBinding 注解除了有 value exchange 属性外,还有 key 属性⽤于定制路由键 routingKey(当前发布订阅模式不需要)。

二.路由模式

/** 2.1 路由模式消息接收,处理error级别⽇志信息 */
@RabbitListener(bindings = @QueueBinding(
 value = @Queue("routing_queue_error"),
 exchange = @Exchange(value = "routing_exchange", type = "direct"),
 key = "error_routing_key"))
public void routingConsumerError(String message) {
 System.out.println("接收到error级别⽇志消息:" + message);
}
/** 2.2 路由模式消息接收,处理info、error、warning级别⽇志信息 */
@RabbitListener(bindings = @QueueBinding(
 value = @Queue("routing_queue_all"),
 exchange = @Exchange(value = "routing_exchange", type = "direct"),
 key = {"error_routing_key", "info_routing_key", "warning_routing_key"}))
public void routingConsumerAll(String message) {
 System.out.println("接收到info、error、warning等级别⽇志消息:" + message);
}

三.Topics(主题模式)

/**
* 3.1 通配符模式消息接收,进⾏邮件业务订阅处理
*/
@RabbitListener(bindings = @QueueBinding(
 value = @Queue("topic_queue_email"),
 exchange = @Exchange(value = "topic_exchange", type = "topic"),
 key = "info.#.email.#"))
public void topicConsumerEmail(String message) {
 System.out.println("接收到邮件订阅需求处理消息:" + message);
}
/**
* 3.2 通配符模式消息接收,进⾏短信业务订阅处理
*/
@RabbitListener(bindings = @QueueBinding(
 value = @Queue("topic_queue_sms"),
 exchange = @Exchange(value = "topic_exchange", type = "topic"),
 key = "info.#.sms.#"))
public void topicConsumerSms(String message) {
 System.out.println("接收到短信订阅需求处理消息:" + message);
}

 四消息确认机制实现

# 配置RabbitMQ消息中间件连接配置
spring:
  rabbitmq:
    host: 192.168.48.67
    port: 5672
    username: admin
    password: 123456
    virtual-host: /zhengchunbo # 配置RabbitMQ虚拟主机路径(默认为"/"可以省略)
      # ACK消息确认
    publisher-confirm-type: simple # 发送者开启confirm确认机制
    publisher-returns: true # 发送者开启return确认机制
config 包下创建 PublisherConfirmAndReturnConfig 类,并实现 RabbitTemplate 提供的
ConfirmCallback ReturnsCallback 接⼝。
package com.example.demo.collection.config;

import org.springframework.amqp.core.ReturnedMessage;
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 javax.annotation.PostConstruct;

/**
 * RabbitTemplate消息确认机制相关接⼝介绍:
 * 1.ConfirmCallback接⼝实现消息发送到交换机(Exchange)的回调
 * 2.ReturnsCallback接⼝实现消息发送到队列(Queue)的回调
 */
@Component
public class PublisherConfirmAndReturnConfig implements RabbitTemplate.ConfirmCallback, RabbitTemplate.ReturnsCallback {
    @Autowired
    private RabbitTemplate rabbitTemplate;

    @PostConstruct
    public void initMethod() {
        rabbitTemplate.setConfirmCallback(this);
        rabbitTemplate.setReturnsCallback(this);
    }

    /**
     * @param correlationData 相关性数据。对象内⼜⼀个id属性,⽤来表示当前消息的唯⼀性
     * @param ack             消息投递到broker的状态,true表示成功
     * @param cause           表示投递失败的原因
     */
    @Override
    public void confirm(CorrelationData correlationData, boolean ack, String cause) {
        if (ack) {
            System.out.println("消息发送到交换机成功");
        } else {
            System.out.println("消息发送到交换机失败");
        }
    }

    /**
     * 消息在往队列发送时,如果消息发送成功,则不会调⽤此回调⽅法,如果消息发送失败,则会调⽤此回调⽅
     * 法。
     *
     * @param returnedMessage ReturnedMessage表示返回消息对象,该类中有5个属性,含义⻅下:
     *                        message:发送的消息内容
     *                        replyCode:回应码
     *                        replyText:回应信息
     *                        exchange:交换机
     *                        routingKey:路由键
     */
    @Override
    public void returnedMessage(ReturnedMessage returnedMessage) {
        System.out.println("消息发送到交换机但未分发到队列");
    }
}

消息限流机制实现

1.resource资源⽂件夹⾥application.yml⽂件中添加消费者限流处理的配置。

spring :
  rabbitmq :
     listener :
        simple :
          acknowledge-mode : manual # 开启⼿动签收 ( ⼿动 ACK)
          prefetch : 3 # ⼀次接收 3 条消息 ( 在单个请求中处理的消息个数 )
          concurrency : 1 # 消费者最⼩数量
          max-concurrency : 10 # 消费者最⼤数量
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值