首页 > 其他分享 >RabbitMQ系列学习笔记(八)--发布订阅模式

RabbitMQ系列学习笔记(八)--发布订阅模式

时间:2024-10-18 21:18:12浏览次数:3  
标签:订阅 String -- RabbitMQ 队列 交换机 消息 系列学习 channel

文章目录

本文参考:
尚硅谷RabbitMQ教程丨快速掌握MQ消息中间件rabbitmq
RabbitMQ 详解
Centos7环境安装Erlang、RabbitMQ详细过程(配图)

一、发布订阅模式原理

image.png
在开发过程中,有一些消息需要不同消费者进行不同的处理,如电商网站的同一条促销信息需要短信发送、邮件发送、站内信发送等。此时可以使用发布订阅模式(Publish/Subscribe),其工作原理如下:

  • 生产者将消息发送给交换机,交换机将消息转发到绑定此交换机的 每个队列 中。
  • 工作队列模式的交换机只能将消息发送给一个队列,发布订阅模式的交换机能将消息发送给多个队列。
  • 发布订阅模式使用 fanout 交换机。

Fanout这种类型非常简单。它是将接收到的所有消息广播到它知道的所有队列中。在系统中可以查看到默认的一些exchange类型,其中就包括fanout类型交换机。
image.png

二、发布订阅模式实战

1、消费者代码

在发布订阅模式下,需要使用fanout类型的交换机,可以选择通过channel.exchangeDeclare()创建,指定类型为fanout,并且需要将交换机与队列进行绑定,形成绑定关系,这样生产者在发送消息到交换机以后,fanout交换机才会把该消息广播发送到各个具有绑定关系的队列。
消费者01代码如下:

/**
 * Description: 发布订阅模式消费者01
 */
public class ReceiveLogs01 {
    //设置要创建的交换机的名称
    private static final String EXCHANGE_NAME = "logs";

    public static void main(String[] args) throws Exception {
        Channel channel = RabbitMqUtil.getChannel();
    	//创建fanout交换机
        /**
         * 参数1:交换机名
         * 参数2:交换机类型
         * 参数3:交换机是否持久化
         */
        channel.exchangeDeclare(EXCHANGE_NAME, "fanout", false);
    	/** 
        * 生成一个临时的队列 队列的名称是随机的 
        * 当消费者断开和该队列的连接时,队列自动删除,防止无用队列占用空间
        */ 
        String queueName = channel.queueDeclare().getQueue();
    	//将交换机与队列进行绑定(binding)
        /**
         * 参数1:队列名
         * 参数2:交换机名
         * 参数3:路由关键字,发布订阅模式写""空串即可
         */
        channel.queueBind(queueName, EXCHANGE_NAME, "");
        System.out.println("等待接收消息,把接收到的消息打印在屏幕上......");
    	//接收消息
        channel.basicConsume(queueName, true, new DefaultConsumer(channel) {
            @Override
            public void handleDelivery(String consumerTag, Envelope envelope, AMQP.BasicProperties properties, byte[] body) throws IOException {
                String message = new String(body, "UTF-8");
                System.out.println("ReceiveLogs01控制台打印接收到的消息: " + message);
            }
        });
    }
}

消费者02代码如下:

/**
 * Description: 发布订阅模式消费者02
 */
public class ReceiveLogs02 {
    //设置要创建的交换机的名称
    private static final String EXCHANGE_NAME = "logs";

    public static void main(String[] args) throws Exception {
        Channel channel = RabbitMqUtil.getChannel();
    	
        channel.exchangeDeclare(EXCHANGE_NAME, "fanout", false);
    	
        String queueName = channel.queueDeclare().getQueue();
    	
        channel.queueBind(queueName, EXCHANGE_NAME, "");
        System.out.println("等待接收消息,把接收到的消息打印在屏幕上......");
    	//接收消息
        channel.basicConsume(queueName, true, new DefaultConsumer(channel) {
            @Override
            public void handleDelivery(String consumerTag, Envelope envelope, AMQP.BasicProperties properties, byte[] body) throws IOException {
                String message = new String(body, "UTF-8");
                System.out.println("ReceiveLogs02控制台打印接收到的消息: " + message);
            }
        });
    }
}

2、生产者代码

由于在消费者中已经完成交换机声明,队列创建及二者之间的绑定关系,因此生产者部分的代码较为简单,只需要在发送消息时指定好前面创建的交换机名称即可。

/**
 * Description: 发布订阅模式生产者
 */
public class EmitLog {
    //交换机名称
    private static final String EXCHANGE_NAME = "logs";

    public static void main(String[] args) throws Exception {
        Channel channel = RabbitMqUtil.getChannel();
        
        //发送消息
        Scanner scanner = new Scanner(System.in);
        while (scanner.hasNext()) {
            String message = sc.nextLine();
            
            //参数1:指定交换机名称
            //参数2:指定routingkey,发布订阅模式写""空串即可
            channel.basicPublish(EXCHANGE_NAME, "", null, message.getBytes("UTF-8"));
            System.out.println("生产者发出消息" + message);
        }
        //关闭资源
        channel.close();
    }
}

3、查看运行结果

将ReceiveLogs01和ReceiveLogs02启动,等待接收消息,再启动生产者,通过控制台发送消息。
image.png
消息发送完毕以后,查看两个消费者都接收到了同样的消息,类似广播,而非之前的互斥接收。
image.png
image.png

标签:订阅,String,--,RabbitMQ,队列,交换机,消息,系列学习,channel
From: https://blog.csdn.net/m0_51621836/article/details/143062534

相关文章

  • RabbitMQ系列学习笔记(十)--通配符模式
    文章目录一、通配符模式原理二、通配符模式实战1、消费者代码2、生产者代码3、查看运行结果本文参考:尚硅谷RabbitMQ教程丨快速掌握MQ消息中间件rabbitmqRabbitMQ详解Centos7环境安装Erlang、RabbitMQ详细过程(配图)一、通配符模式原理通配符模式(Topics)是在路......
  • 递推数列的极限(上)------单调有界部分
    不管怎么样,求极限之前都要先证明极限存在,即数列收敛。证明数列收敛两种方法:一种是单调有界准则,一种是夹逼准则。一.单调有界准则例1上面这道题的心路历程:先在草稿纸用上帝视角求出‘极限’,虽然是猜的,但是一定是对的。然后根据这个极限,以及题目给的条件,比如这道题给......
  • Java方法使用的细节
    在Java中,方法是一段可重用的逻辑代码块,用于执行特定的任务。以下是关于Java方法使用的一些细节:方法声明:方法应该先声明,再调用。方法的声明包括方法名、参数列表、返回类型和方法体。方法名应该以小写字母开头,并采用驼峰命名法。参数列表包括参数的类型和名称,多个参数之间用逗......
  • 八,Lambda表达式
    JavaLambda表达式与枚举Lambda表达式概述Java从JDK1.8开始引入了Lambda表达式,以简化代码开发并支持函数式编程。Lambda表达式可以避免面向对象编程中的一些繁琐问题,但同时也是一把双刃剑。Lambda表达式的使用场景必须有相应的函数接口,即内部有且仅有一个抽象方法的接口。......
  • 浅谈 tarjan
    就是记录两个数组:dfn[]和low[]其中dfn[]表示访问的顺序,low[u]用来存储\(u\)不经过其父亲能到达的最小时间戳。。。搬一下wiki的图。。。我们发现\(low[v]\gedfn[u]\)可以表示不能回到祖先,则\(u\)点位割点。。。直接上代码P3388------>#include<bits/stdc++.h>usi......
  • zyx是猫娘。每当她脾气暴躁的时候其实就是她发情了。还因为她的熙缺水补火导致整个人上火了。哦我的天哪,zyx怎么是这样的呢?但小编也很惊讶,接下来我们就来看看zyx为什么是猫娘吧。zyx是怎么变成的猫娘呢,其实是因为zyx是catgirl所以她就是猫娘。......
  • linux命令
    cd 进入目录cd/ 进入根目录cd.. 返回上一级cd../.. 返回上两级cd../../.. 返回上三级pwd 显示当前路径mkdir 创建目录mkdir-pa/b/c/d 创建层级目录ls 横向显示所有文件ll 纵向显示所有文件ll-a 显示隐藏文件ping 查看网络touch 创建文档vim 编辑文档cat 查......
  • cm
    CTH使我假完了!都怪CTH!!!后天再调#include<bits/stdc++.h>#defineintlonglong#defineme(a)memset(a,0,sizeofa)#definelsonls[rt]#definersonrs[rt]#defineAqrfre(x,y)freopen(#x".in","r",stdin),freopen(#y".out",......
  • ES数据聚合
    1.什么是数据聚合聚合(aggregations)可以让我们极其方便的实现对数据的统计、分析、运算。例如:什么品牌的手机最受欢迎?这些手机的平均价格、最高价格、最低价格?这些手机每月的销售情况如何?实现这些统计功能的比数据库的sql要方便的多,而且查询速度非常快,可以实现近实时......
  • 104. 建造最大岛屿(kamacoder)
    https://kamacoder.com/problempage.php?pid=1176importjava.util.*;publicclassMain{staticint[]dx={0,1,0,-1};staticint[]dy={1,0,-1,0};staticintn;staticintm;staticint[][]grid;staticboolean[][]vis;statici......