尚硅谷—RabbitMQ—2021-06-17

视频链接
在这里插入图片描述
在这里插入图片描述

一.:入门(1~12)

1:MQ 相关概念:

   1)什么是 MQ:(Message Queue)
    -1:MQ,从字面意思上来看,本质是个队列,FIFO 先进先出。只不过队列中存放的内容是 Message 而已。
    -2:还是一种跨进程的通信机制,用于上下游传递信息。
    -3::在互联网架构中,MQ 是一种非常常见的,上下游 “逻辑解耦 + 物理解耦” 的消息通信服务。
    -4::使用了 MQ 之后,消息发送上游,只需要依赖MQ,不用依赖其它服务。

   2)为什么要用 MQ:(3)(流量削峰、应用解耦、异步处理)
    -1:流量削峰:
在这里插入图片描述
    -2:应用解耦:
在这里插入图片描述
    -3:异步处理:
在这里插入图片描述

   3)MQ 的分类:
    -1:ActiveMQ:(老)
  优点:单机吞吐量 万级,实效性 ms 级,可用性高。基于主从架构可实现高可用性。消息可靠性高,丢失数据概率较低。
  缺点:官方社区现在对 ActiveMQ 5.x 维护越来越少,高吞吐量场景较少使用。

    -2:Kafka:
在这里插入图片描述
    -3:Rocket MQ:
在这里插入图片描述
    -4:RabbitMQ:
  1、介绍:是一个消息中间件(类似于快递站),用于 接收、存储、转发数据。 2007 年发布,是一个在 AMQP(高级消息队列协议)基础上完成的,可复用企业消息系统, 是当前最主流的消息中间件之一。
  2、优点:erlang 语言,性能较好,吞吐量万级。 RabbitMQ 功能比较完备、健壮、稳定、易用、跨平台。支持多种语言。文档较全和更新活跃。
  3、缺点:商业版需要收费,学习成本较高。

   4)MQ 的 选择:
在这里插入图片描述




2:RabbitMQ:

   1)RabbitMQ 的概念:见上

   2)四大核心概念:
    -1:生产者:产生数据,发送消息的程序。
    -2:交换机:
  a:接收来自生产者的消息,并将消息推送到队列中。
  b:交换机必须确切的知道,如何处理它接收到的消息。是将这些消息推送到多个队列,还是把消息丢弃。由交换机类型来决定。
    -3:队列:
  a:队列是 RabbitMQ 内部使用的一种数据结构。尽管消息流经 RabbitMQ 和 应用程序,但是它们只能存储在队列中。
  b:队列仅受 主机的内存 和 磁盘限制 的约束,本质上是一个大的消息缓冲区。
    -4:消费者:
  a:消费与接收,具有相同的含义。
  b:消费者大多时候,是一个等待接收消息的程序。
  c:同一个应用,既可以是生产者,也可以是消费者。
在这里插入图片描述

   3)RabbitMQ 核心部分:(六大模式)(后面介绍)
在这里插入图片描述
   4)各个名词介绍:
在这里插入图片描述
    -1:Broker:接收和分发消息的应用,RabbitMQ Server 就是 Message Broker。

    -2:Virtual Host:出于多租户和安全因素设计,把 AMQP 的基本组件,划分到一个虚拟分组中。  类似网络中的 namespace 概念。 当多个不用的用户,使用用一个 RabbitMQ Server 提供服务时,可以划分出多个 vhost,每个用户在自己的 vhost 创建 exchange / queue 等。

    -3:Connection:publisher / consumer 和 broker 之间的 TCP 连接。

    -4:Channel:
  a:如果每一次访问 RabbitMQ,都建立一个 Connection,在消息量大的时候建立 TCP Connection 的开销将是巨大的,效率也低。
  b:Channel 是在 Connection 内部建立的逻辑连接。 如应用程序支持多线程,通常每个 thread 创建单独的 channel 进行通讯,AMQP method 包含了 channel id 帮助客户端 和 message broker 识别 channel,所以 channel 之间是完全隔离的。
  c:Channel 作为轻量级的 Connection,极大减少了操作系统建立在 TCP Connection 的开销。

    -5:ExChange:
  a:message 到达 broker 的第一站。根据分发规则,匹配查询表中的 routing key,分发到 queue 中去。
  b:通常的类型有:
    direct(point-to-point)
    topic(publish-subscribe)
    fanout(multicast)

    -6:Queue:消息最终被送到这里,等待 consumer 取走。

    -7:Bingding:Exchange 和 Queue 之间的虚拟连接。binding 中,可以包含 routing key。binding 信息被保存到 exchange 中的查询表中,用于 message 的分发依据。

3:安装:

安装参考文档
   1)下载 & 上传:
    -1:下载地址 :
  a:Erlang:(https://www.erlang.org/downloads)
  b:RabbitMQ:(https://www.rabbitmq.com/download.html)
  c:版本对应关系:(https://www.erlang.org/downloads)

    -2:文件上传到:(/usr/local/software/rabbitmq/)

   2)安装:erlang:

// 安装依赖
yum -y install gcc glibc-devel make ncurses-devel openssl-devel xmlto perl wget gtk2-devel binutils-devel

// 解压 erlang
tar -zxvf otp_src_24.2.2.tar.gz

// 新建 erlang 安装目录(bin 目录)
mkdir /usr/local/bin/erlang

// 回到解压后目录,编译安装
./configure --prefix=/usr/local/bin/erlang
make & make install

// 配置环境变量 & 刷新
vim /etc/profile
“export PATH=$PATH:/usr/local/bin/erlang/bin”
source /etc/profile

// 测试
erl  :(进入)
halt().  :(退出)

   3)安装 RabbitMQ:

// 解压
xz -d rabbitmq-server-generic-unix-3.9.13.tar.xz
tar -xvf rabbitmq-server-generic-unix-3.9.13.tar

// 由于是tar.xz格式的所以需要用到xz,没有的话就先安装 
yum install -y xz

// 配置环境
"export PATH=$PATH:/usr/local/rabbitmq/rabbitmq/sbin"

   4)启动:

// 启动
./rabbitmq-server detached // ./rabbitmq-server start
// 停止
./rabbitmqctl stop
// 状态
./rabbitmqctl status

   5)开启web插件 & 访问:

./rabbitmq-plugins enable rabbitmq_management
// 访问
http://192.168.124.11:15672/。(默认 guest,权限不足不可登陆)

   6)用户管理:(添加用户并设置权限)
在这里插入图片描述

// 查看所有用户
./rabbitmqctl list_users

// 添加一个用户
./rabbitmqctl add_user admin 123

// 设置用户权限
./rabbitmqctl set_permissions -p "/" admin ".*" ".*" ".*"
// 表示:用户 admin ,具有 vhost1 这个 virtual host 中所有资源的 (配置、写、读)权限。

// 查看用户权限
./rabbitmqctl list_user_permissions admin

// 设置tag
./rabbitmqctl set_user_tags admin administrator
 
// 删除用户(安全起见,删除默认用户)
./rabbitmqctl delete_user admin





二.:核心部分(13~48)

Hello World:(简单模式)
Work queues:(工作队列模式)
Publish / Subscribe:(发布/订阅模式)
Routing:(路由模式)
Topics:(主题模式)
Publisher Confirms:(发布确认模式)

1:Hello World:(简单模式):

   1)说明:
在这里插入图片描述
   2)依赖:

<dependency>
    <groupId>com.rabbitmq</groupId>
    <artifactId>amqp-client</artifactId>
    <version>5.4.3</version>
</dependency>
<dependency>
    <groupId>commons-io</groupId>
    <artifactId>commons-io</artifactId>
    <version>2.11.0</version>
</dependency>

   3)消息生产者:

/**
 * @author zhangxudong@chunyu.me
 * @date 2022/3/7 3:09 下午
 */
public class Producer01 {
   

    public static final String QUEUE_NAME = "hello_world";

    public static void main(String[] args) throws IOException, TimeoutException {
   
        ConnectionFactory factory = new ConnectionFactory();
        factory.setHost("192.168.124.11");
        factory.setUsername("admin");
        factory.setPassword("123");
        // 创建连接
        Connection connection = factory.newConnection();
        System.out.println("连接:" + connection);
        // 创建信道
        Channel channel = connection.createChannel();
        // 生成一个队列(exclusive:true可以多个消费者消费,false只能一个消费者消费)
        Map<String, Object> map = new HashMap<>();
        AMQP.Queue.DeclareOk declareOk = channel.queueDeclare(QUEUE_NAME, true, false, true, map);
        // 发消息
        String message = "hello world";
        channel.basicPublish("", QUEUE_NAME, null, message.getBytes(StandardCharsets.UTF_8));
        System.out.println("消息发送完毕");
    }
}

在这里插入图片描述
   4)消息消费者:

/**
 * @author zhangxudong@chunyu.me
 * @date 2022/3/7 3:29 下午
 */
public class comsumer01 {
   

    public static final String QUEUE_NAME = "hello_world";

    public static void main(String[] args) throws IOException, TimeoutException {
   
        ConnectionFactory factory = new ConnectionFactory();
        factory.setHost("192.168.124.11");
        factory.setUsername("admin");
        factory.setPassword("123");
        // 创建新的连接
        Connection connection = factory.newConnection();
        // 创建信道
        Channel channel = connection.createChannel();
        /**
         *  消费者 接收消息
         */
        // 声明接收消息
        DeliverCallback deliverCallback = (consumerTag, message) -> {
   
            System.out.println("--message:" + new String(message.getBody()));
        };
        // 取消消息时回掉
        CancelCallback cancelCallback = consumerTag -> {
   
            System.out.println("consumerTag:" + consumerTag);
        };
        channel.basicConsume(QUEUE_NAME, true, deliverCallback, cancelCallback);
    }
}



2:Work queues:(工作队列模式)

在这里插入图片描述
   1):轮询分发消息:(1 生产者、2消费者,查看他们如何工作)
    -1:抽取工具类:

/**
 * @author zhangxudong@chunyu.me
 * @date 2022/3/7 4:17 下午
 */
public class Utils {
   
    public static Channel getChannel() throws IOException, TimeoutException {
   
        ConnectionFactory factory = new ConnectionFactory();
        factory.setHost("192.168.124.11");
        factory.setUsername("admin");
        factory.setPassword("123");
        Connection connection = factory.newConnection();
        return connection.createChannel();
    }
}

    -2:启动两个消费者线程:
在这里插入图片描述

/**
 * @author zhangxudong@chunyu.me
 * @date 2022/3/7 4:20 下午
 */
public class Consumer01 {
   

    public static final String QUEUE_NAME = "work_queue";

    public static void main(String[] args) {
   
        Channel channel = Utils.getChannel();
        new Thread(() -> {
   
            try {
   
                channel.basicConsume(QUEUE_NAME, false,
                        (consumerTag, message) -> System.out.println(Thread.currentThread().getName() + ":消费者 接收消息:" + new String(message.getBody())),
                        consumerTag -> System.out.println("消息被取消回掉逻辑:" + consumerTag));
            } catch (IOException e) {
   
                e.printStackTrace();
            }
        }).start();
    }
}

    -3:启动一个发送线程:

/**
 * @author zhangxudong@chunyu.me
 * @date 2022/3/7 4:19 下午
 */
public class Produce01 {
   

    public static final String QUEUE_NAME = "work_queue";

    public static void main(String[] args) throws IOException {
   
        Channel channel = Utils.getChannel();
        // 生成一个队列(exclusive:true可以多个消费者消费,false只能一个消费者消费)
        Map<String, Object> map = new HashMap<>();
        channel.queueDeclare(QUEUE_NAME, true, false, true, map);
        // 发消息
        String message = "work_queue:";
        for (int i = 0; i < 100; i++) {
   
            channel.basicPublish("", QUEUE_NAME, null, String.valueOf(message + i).getBytes(StandardCharsets.UTF_8));
        }
        System.out.println("消息发送完毕");
    }
}

    -4:结果展示:(两个消费者,轮询消费)
在这里插入图片描述

   2)消息应答:
    -1:概念:
在这里插入图片描述
    -2:自动应答:
在这里插入图片描述
    -3:消息应答方法:
在这里插入图片描述
在这里插入图片描述
    -4:Multiple 解释:(批量)(建议 false)
在这里插入图片描述
    -5:消息自动重新入队:
在这里插入图片描述
    -6:消息手动应答代码:(消息在手动应答中是不丢失的)(1生产者 & 2消费者)

/**
 * @author zhangxudong@chunyu.me
 * @date 2022/3/7 4:19 下午
 */
public class Produce01 {
   

    public static final String QUEUE_NAME = "work_queue1";

    public static void main(String[] args) throws IOException {
   
        Channel channel = Utils.getChannel();
        // 生成一个队列(exclusive:true可以多个消费者消费,false只能一个消费者消费)
        Map<String, Object> map = new HashMap<>();
        channel.queueDeclare(QUEUE_NAME, false, false, false, map);
        // 发消息
        String message = "work_queue:";
        for (int i = 0; i < 100; i++) {
   
            channel.basicPublish("", QUEUE_NAME, null, String.valueOf(message + i).getBytes(StandardCharsets.UTF_8));
        }
        System.out.println("消息发送完毕");
    }
}
/**
 * @author zhangxudong@chunyu.me
 * @date 2022/3/8 10:24 上午
 */
public class Consumer02 {
   

    public static final String QUEUE_NAME = "work_queue1";

    public static void main(String[] args) {
   
        Channel channel = 
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值