RabbitMQ基础-工作模式

提示:RabbitMQ五种工作模式及应用(官方是7种)


前言

RabbitMQ官方文档


一、RabbitMQ安装(Docker)

  1. 下载镜像:

    docker pull rabbitmq
    
  2. 运行容器:

    docker run -d --name rabbitmq -p 5672:5672 -p 15672:15672 -e RABBITMQ_DEFAULT_USER=admin -e RABBITMQ_DEFAULT_PASS=123456 rabbitmq:latest
    

    账号admin,密码123456 用于登录MQ后台

  3. 打开访问界面

    进入容器:
    docker exec -it a64bbac6d26f bash
    执行:
    rabbitmq-plugins enable rabbitmq_management
    输出:
    Enabling plugins on node rabbit@a64bbac6d26f:
    rabbitmq_management
    The following plugins have been configured:
    rabbitmq_management
    rabbitmq_management_agent
    rabbitmq_prometheus
    rabbitmq_web_dispatch
    Applying plugin configuration to rabbit@a64bbac6d26f...
    The following plugins have been enabled:
    rabbitmq_management
    started 1 plugins
    
  4. 即可在浏览器中通过 http://127.0.0.1:15672/ 访问,可通过上面设置的账号密码进行登录。

二、MQ中相关概念

KEY VALUE
Broker 接收和分发消息的应用
Virtual host 出于多租户和安全因素设计的,把 AMQP 的基本组件划分到一个虚拟的分组中,类似于网络中的 namespace 概念。当多个不同的用户使用同一个 RabbitMQ server 提供的服务时,可以划分出多个vhost,每个用户在自己的 vhost 创建 exchange/queue 等
Connection publisher/consumer 和 broker 之间的 TCP 连接
Channel 如果每一次访问 RabbitMQ 都建立一个 Connection,在消息量大的时候建立 TCP Connection的开销将是巨大的,效率也较低。Channel 是在 connection 内部建立的逻辑连接,如果应用程序支持多线程,通常每个thread创建单独的 channel 进行通讯,AMQP method 包含了channel id 帮助客户端和message broker 识别 channel,所以 channel 之间是完全隔离的。Channel 作为轻量级的 Connection 极大减少了操作系统建立 TCP connection 的开销
Exchange message 到达 broker 的第一站,根据分发规则,匹配查询表中的 routing key,分发消息到queue 中去。常用的类型有:direct (定向,把消息交给符合指定routing key 的队列), topic (通配符,把消息交给符合routing pattern(路由模式) 的队列) and fanout (广播,将消息交给所有绑定到交换机的队列)
Queue 消息最终被送到这里等待 consumer 取走
Binding exchange 和 queue 之间的虚拟连接,binding 中可以包含 routing key。Binding 信息被保存到 exchange 中的查询表中,用于 message 的分发依据

每个Virtual Hosts相当于一个相对独立的RabbitMQ服务器,每个VirtualHost之间是相互隔离的。exchange、queue、message不能互通。 相当于mysql的db。Virtual Name一般以/开头
Exchange(交换机)只负责转发消息,不具备存储消息的能力,因此如果没有任何队列与Exchange绑定,或者没有符合路由规则的队列,那么消息会丢失!

三、工作模式

模式 特点 场景 图解
简单 (Simple) 一个生产者、一个消费者,不需要设置交换机(使用默认的交换机) 单个生产者和单个消费者(日志记录,订单处理) 在这里插入图片描述
工作(Work Queue) 一个生产者、多个消费者(竞争关系),不需要设置交换机(使用默认的交换机) 需要多个消费者共同处理任务(异步处理,短信通知) ![在这里插入图片描述](https://i-blog.csdnimg.cn/direct/66e086e2a7f044ef89150f21e15baaa6.png
发布/订阅(Publish/Subscribe) 需要设置类型为fanout的交换机,并且交换机和队列进行绑定,当发送消息到交换机后,交换机会将消息发送到绑定的队列 需要消息被多个消费者同时接收(实时通知,广播) 在这里插入图片描述
路由(Routing) 需要设置类型为direct的交换机,交换机和队列进行绑定,并且指定routingkey,当发送消息到交换机后,交换机会根据routing key将消息发送到对应的队列 需要根据特定条件匹配路由消息(消息分类处理) 在这里插入图片描述
通配符(Topics) 需要设置类型为topic的交换机,交换机和队列进行绑定,并且指定通配符方式的routing key,当发送消息到交换机后,交换机会根据routing key将消息发送到对应的队列 适用于需要根据模式匹配分发消息的场景 在这里插入图片描述

四、Java操作MQ

依赖:

<dependency>
     <groupId>com.rabbitmq</groupId>
     <artifactId>amqp-client</artifactId>
     <version>5.21.0</version>
 </dependency>

工具类:

package com.rabbitmq.utils;
import com.rabbitmq.client.ConnectionFactory;
import com.rabbitmq.client.Connection;
import java.io.IOException;
import java.util.concurrent.TimeoutException;
public class ConnectionUntils {
   
    public static Connection getConnection() throws IOException, TimeoutException {
   
        //创建连接工厂
        ConnectionFactory factory = new ConnectionFactory();
        factory.setHost("127.0.0.1");
        factory.setPort(5672);
        factory.setVirtualHost("/");
        factory.setUsername("admin");
        factory.setPassword("123456");
        //创建连接
        Connection connection = factory.newConnection();
        return connection;
    }
}
  1. 简单模式
package com.rabbitmq.simple;
import com.rabbitmq.client.Channel;
import com.rabbitmq.client.Connection;
import com.rabbitmq.client.ConnectionFactory;
import com.rabbitmq.utils.ConnectionUntils;
/**
 * 简单模式
 * 生产者
 */
public class Producer {
   
    static final String QUEUE_NAME = "simple_name";
    public static void main(String[] args) throws Exception {
   
        Connection connection = ConnectionUntils.getConnection();
        Channel channel = connection.createChannel();
        /**
         * 声明队列
         * 参数1:队列名称
         * 参数2:是否定义持久化队列
         * 参数3:是否独占本次连接
         * 参数4:是否在不使用的时候自动删除队列
         * 参数5:队列其它参数
         */
        channel.queueDeclare(QUEUE_NAME, true, false, false, null);
        /**
         * 发送消息
         * 参数1:交换机名称,如果没有指定则使用默认Default Exchage
         * 参数2:路由key,简单模式可以传递队列名称
         * 参数3:消息其它属性
         * 参数4:消息内容
         */
        String message = "Hello World!7";
        channel.basicPublish("", QUEUE_NAME, null, message.getBytes());
        System.out.println(" [x] Sent '" + message + "'");
        //释放资源
        channel.close();
        connection.close();
    }
}
package com.rabbitmq.simple;
import com.rabbitmq.client.*;
import com.rabbitmq.utils.ConnectionUntils;
import java.io.IOException;
/**
 * 消费者
 */
public class Consumer {
   
    public static void main(String[] args) throws Exception {
   
        Connection conection = ConnectionUntils.getConnection();
        //通道
        Channel channel = conection.createChannel();
        /**
         * 声明队列
         * 参数1:队列名称
         * 参数2:是否定义持久化队列
         * 参数3:是否独占本次连接
         * 参数4:是否在不使用的时候自动删除队列
         * 参数5:队列其它参数
         */
        channel.queueDeclare(Producer.QUEUE_NAME, true, false, false, null);
        //接受消息
        DefaultConsumer consumer = new DefaultConsumer(channel) {
   
            /**
             * 接受消息 处理消息的回调函数
             * @param consumerTag 消费者标签 channel.basicConsume() 指定使用什么标签的消费者消费消息
             * @param envelope 消息包的信息:消息id routingkey exchange
             * @param properties 属性信息
             * @param body 消息
             * @throws IOException
             */
            @Override
            public void handleDelivery(String consumerTag, Envelope envelope, AMQP.BasicProperties properties, byte[] body) throws IOException {
   
                System.out.println("路由:" + envelope.getRoutingKey());
                System.out.println("交换机:" + envelope.getExchange());
                System.out.println("消息ID:" + envelope.getDeliveryTag());
                System.out.println("消息" + new String(body, "UTF-8"));
                super.handleDelivery(consumerTag, envelope, properties, body);
            }
        };
        /**
         * 1.队列名称
         * 2.是否确认,true 消息消费后,mq自动回复消息已消费 mq收到回复后删除消息
         * 3.消费者对象,消息消费的回调函数
         */
        channel.basicConsume(Producer.QUEUE_NAME, true, consumer);
    }
}
  1. 工作模式:在一个队列中如果有多个消费者,那么消费者之间对于同一个消息的关系是竞争的关系。
package com.rabbitmq.work;
import com.rabbitmq.client.Channel;
import com.rabbitmq.client.Connection;
import com.rabbitmq.utils.ConnectionUntils;
/**
 * 工作模式
 * 生产者
 */
public class Producer {
   
    static final String QUEUE_NAME = "work_name";
    public static void main(String[] args) throws Exception {
   
        Connection connection = ConnectionUntils.getConnection();
        Channel channel = connection.
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值