【RabbitMQ】-SpringAMQP以及Work模型_发送消息

介绍和安装

安装部署

利用docker

docker run \
 -e RABBITMQ_DEFAULT_USER=orange \
 -e RABBITMQ_DEFAULT_PASS=123321 \
 -v mq-plugins:/plugins \
 --name mq \
 --hostname mq \
 -p 15672:15672 \
 -p 5672:5672 \
 --network hm-net\
 -d \
 rabbitmq:3.8-management

【RabbitMQ】-SpringAMQP以及Work模型_虚拟主机_02

基本介绍

RabbitMQ的整体架构及核心概念:

  • publisher:生产者,也就是发送消息的一方
  • consumer:消费者,也就是消费消息的一方
  • queue:队列,存储消息。生产者投递的消息会暂存在消息队列中,等待消费者处理
  • exchange:交换机,负责消息路由。生产者发送的消息由交换机决定投递到哪个队列。
  • virtual host:虚拟主机,起到数据隔离的作用。每个虚拟主机相互独立,有各自的exchange、queue

【RabbitMQ】-SpringAMQP以及Work模型_发送消息_03

快速入门

添加队列

【RabbitMQ】-SpringAMQP以及Work模型_发送消息_04

【RabbitMQ】-SpringAMQP以及Work模型_虚拟主机_05

在交换机里模拟发消息

【RabbitMQ】-SpringAMQP以及Work模型_发送消息_06

【RabbitMQ】-SpringAMQP以及Work模型_RabbitMQ_07

但是在此之前需要先让交换机绑定队列

【RabbitMQ】-SpringAMQP以及Work模型_虚拟主机_08

【RabbitMQ】-SpringAMQP以及Work模型_RabbitMQ_09

【RabbitMQ】-SpringAMQP以及Work模型_发送消息_10

注意

  • 交换机只能路由消息,无法存储消息
  • 交换机只会路由消息给与其绑定的队列,因此队列必须与交换机绑定

数据隔离

添加一个新用户

【RabbitMQ】-SpringAMQP以及Work模型_RabbitMQ_11

然后切换用户,创建自己的虚拟主机

【RabbitMQ】-SpringAMQP以及Work模型_RabbitMQ_12

Java客户端

【RabbitMQ】-SpringAMQP以及Work模型_虚拟主机_13

将来我们开发业务功能的时候,肯定不会在控制台收发消息,而是应该基于编程的方式。由于RabbitMQ采用了AMQP协议,因此它具备跨语言的特性。任何语言只要遵循AMQP协议收发消息,都可以与RabbitMQ交互。并且RabbitMQ官方也提供了各种不同语言的客户端。

但是,RabbitMQ官方提供的Java客户端编码相对复杂,一般生产环境下我们更多会结合Spring来使用。而Spring的官方刚好基于RabbitMQ提供了这样一套消息收发的模板工具:SpringAMQP。并且还基于SpringBoot对其实现了自动装配,使用起来非常方便。

快速入门

1.引入spring-amqp依赖

在父工程中引入spring-amqp依赖,这样publisher和consumer服务都可以使用: .

  <!--AMQP依赖,包含RabbitMQ-->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-amqp</artifactId>
        </dependency>

2.配置RabbitMQ服务端地址

在每个微服务中引入MQ服务端信息,这样微服务才能连接到RabbitMQ

spring:
  rabbitmq:
    host: 192.168.21.129 # 你的虚拟机IP
    port: 5672 # 端口
    virtual-host: /hmall # 虚拟主机
    username: hamll # 用户名
    password: 123 # 密码

3.发送消息

SpringAMQP提供了RabbitTemplate工具类,方便我们发送消息。发送消息代码如下:

@SpringBootTest
public class SpringAmqpTest {

    @Autowired
    private RabbitTemplate rabbitTemplate;

    @Test
    public void testSimpleQueue() {
        // 队列名称
        String queueName = "simple.queue";
        // 消息
        String message = "hello, spring amqp!";
        // 发送消息
        rabbitTemplate.convertAndSend(queueName, message);
    }
}

【RabbitMQ】-SpringAMQP以及Work模型_发送消息_14

【RabbitMQ】-SpringAMQP以及Work模型_发送消息_15

4.接受消息

SpringAMQP提供声明式的消息监听,我们只需要通过注解在方法上声明要监听的队列名称,将来SpringAMQP就会把消息传递给当前方法:

public class SpringRabbitListener {

    @RabbitListener(queues = "simple.queue")
    public void listenSimpleQueue(String message){
        log.info("监听到simple.queue的消息:【{}】",message);
    }
}

【RabbitMQ】-SpringAMQP以及Work模型_RabbitMQ_16


WorkQueue

Work queues,任务模型。简单来说就是让多个消费者绑定到- -个队列,共同消费队列中的消息。

【RabbitMQ】-SpringAMQP以及Work模型_虚拟主机_17

    @RabbitListener(queues = "work.queue")
    public void listenWorkQueue1(String message){
        System.out.println("消费者1接受到消息:"+message+" "+ LocalTime.now());
    }

    @RabbitListener(queues = "work.queue")
    public void listenWorkQueue2(String message){
        System.err.println("消费者2.......接受到消息:"+message+" "+ LocalTime.now());
    }
    @Test
    public void testWorkQueue(){

        //队列名
        String queueName = "work.queue";
        for (int i = 1; i <=50; i++) {
            //消息
            String message = "hello,spring amqp_" +i;
            //发送消息
            rabbitTemplate.convertAndSend(queueName,message);
        }

    }

【RabbitMQ】-SpringAMQP以及Work模型_RabbitMQ_18

消费者消息推送限制

默认情况下,RabbitMQ的会将消息依次轮询投递给绑定在队列上的每一个消费者。 但这并没有考虑到消费者是否已经处理完消息,可能出现消息堆积。

因此我们需要修改application.yml,设置preFetch值为1,确保同一时刻最多投递给消费者1条消息: 

【RabbitMQ】-SpringAMQP以及Work模型_RabbitMQ_19