Rabbitmq(三)

本文详细介绍了RabbitMQ中的三种主要模式:Publish/Subscribe的Fanout模式,路由模式(使用direct类型交换机),以及RPC模式的应用。通过示例展示了消费者和生产者的代码实现,以及每种模式的工作原理和适用场景。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

订阅与发布模式(Publish/Subscribe)

Fanout这种类型非常简单。正如从名称中猜到的那样,它是将接收到的所有消息广播到它知道的所有队列中。系统中默认有该交换机的类型

在这里插入图片描述

如下图,我们将fanout类型交换机绑定到两个临时队列中,并通过该交换机将消息发布给两个消费者(消息依旧只能被消费一次)

在这里插入图片描述

消费者代码

 /*
 * 消费者01
 * 消息接收
 * */
 public class ReceiveLogs01 {
 
     //交换机名称
     public static final String EXCHANGE_NAME = "logs";
 
     public static void main(String[] args) throws Exception{
         Channel channel = RabbitMqUtils.getChannel();
         channel.exchangeDeclare(EXCHANGE_NAME, "fanout");
     //声明一个队列,名称随机,当消费者断开与队列的连接时,队列自动删除
     String queueName = channel.queueDeclare().getQueue();

     //把该临时队列绑定我们的 exchange,其中 routingkey(也称之为 binding key)为空字符串
     channel.queueBind(queueName,EXCHANGE_NAME,"");
     System.out.println("等待接受消息,把接受到的消息打印在屏幕上...");
     DeliverCallback deliverCallback = (consumerTag,message) -> {
         System.out.println("ReceiveLogs01控制台打印接受到的消息:" + new String(message.getBody()));
     };

     channel.basicConsume(queueName,true,deliverCallback,consumerTag -> {});
 }
}

 /*
 * 消费者02
 * 消息接收
 * */
 public class ReceiveLogs02 {
 
     //交换机名称
     public static final String EXCHANGE_NAME = "logs";
 
     public static void main(String[] args) throws Exception{
         Channel channel = RabbitMqUtils.getChannel();
         channel.exchangeDeclare(EXCHANGE_NAME, "fanout");
     //声明一个临时队列,名称随机,当消费者断开与队列的连接时,队列自动删除(临时队列的特性)
     String queueName = channel.queueDeclare().getQueue();

     //绑定交换机与队列
     channel.queueBind(queueName,EXCHANGE_NAME,"");
     System.out.println("等待接受消息,把接受到的消息打印在屏幕上...");
     DeliverCallback deliverCallback = (consumerTag,message) -> {
         System.out.println("ReceiveLogs02控制台打印接受到的消息:" + new String(message.getBody()));
     };

     channel.basicConsume(queueName,true,deliverCallback,consumerTag -> {});
 }
}

生产者代码

 /*
 *  生产者
 *  发消息 交换机
 * */
 public class Emitlog {
     // 交换机的名称
     public  static  final String EXCHANGE_NAME = "logs";
 
     public static void main(String[] args) throws  Exception{
         Channel channel = RabbitMqUtils.getChannel();
         /**
        * 声明一个 exchange
        * 1.exchange 的名称
        * 2.exchange 的类型
        */
         channel.exchangeDeclare(EXCHANGE_NAME,"fauout");

     Scanner scanner = new Scanner(System.in);
     while (scanner.hasNext()){
         String message = scanner.next();
         channel.basicPublish(EXCHANGE_NAME,"",null,message.getBytes(StandardCharsets.UTF_8));
         System.out.println("生产者发出的消息:"+ message);
     }
 }
}


路由模式(Routing)

路由模式是指我们的队列能够接收交换机传来的指定的消息,而不是所有的消息,所以路由模式采用 direct 这种类型的交换机来进行替换,这种类型的工作方式是,消息只去到它绑定的 routingKey 队列中去。

在这里插入图片描述

在上面这张图中,我们可以看到 X 绑定了两个队列,绑定类型是 direct。队列Q1 绑定键为 orange, 队列 Q2 绑定键有两个:一个绑定键为 black,另一个绑定键为 green.。

在这种绑定情况下,生产者发布消息到 exchange 上,绑定键为 orange 的消息会被发布到队列 Q1。绑定键为 black / green 的消息会被发布到队列 Q2,其他消息类型的消息将被丢弃。

如果交换机的绑定类型是是direct,但是它绑定的多个队列的 key 如果都相同,在这种情况下虽然绑定类型是 direct 但是它表现的就和 fanout 有点类似了,就跟广播差不多

在这里插入图片描述

生产者代码

public class DirectLogs {
 // 交换机的名称
 public  static  final String EXCHANGE_NAME = "direct_logs";

 public static void main(String[] args) throws  Exception{
     Channel channel = RabbitMqUtils.getChannel();
     //BuiltinExchangeType.DIRECT 交换机的枚举类型
     channel.exchangeDeclare(EXCHANGE_NAME, BuiltinExchangeType.DIRECT);
     //创建多个 bindingKey
     Map<String, String> bindingKeyMap = new HashMap<>();
     bindingKeyMap.put("info","普通 info 信息");
     bindingKeyMap.put("warning","警告 warning 信息");
     bindingKeyMap.put("error","错误 error 信息");
     
     //debug 没有消费这接收这个消息 所有就丢失了
     bindingKeyMap.put("debug","调试 debug 信息");
     for (Map.Entry<String, String> bindingKeyEntry: bindingKeyMap.entrySet())
     {
         String bindingKey = bindingKeyEntry.getKey();
         String message = bindingKeyEntry.getValue();
         
         channel.basicPublish(EXCHANGE_NAME,bindingKey, null,message.getBytes("UTF-8"));
         System.out.println("生产者发出消息:" + message);
     }
 }
}

消费者代码

public class ReceiveLogsDirect01 {
    public static final String EXCHANGE_NAME = "direct_logs";

    public static void main(String[] args) throws Exception {
        Channel channel = RabbitMqUtils.getChannel();
        channel.exchangeDeclare(EXCHANGE_NAME, BuiltinExchangeType.DIRECT);
        //声明一个队列
        channel.queueDeclare("console",false,false,false,null);

        //绑定交换机与队列
        channel.queueBind("console",EXCHANGE_NAME,"info");
        channel.queueBind("console",EXCHANGE_NAME,"warning");
        
        DeliverCallback deliverCallback = (consumerTag, message) -> {
            System.out.println("ReceiveLogsDirect01控制台打印接受到的消息:" + new String(message.getBody()));
        };
        channel.basicConsume("console",true,deliverCallback,consumerTag -> {});
    }
}

public class ReceiveLogsDirect02 {
 public static final String EXCHANGE_NAME = "direct_logs";

 public static void main(String[] args) throws Exception {
     Channel channel = RabbitMqUtils.getChannel();
     channel.exchangeDeclare(EXCHANGE_NAME, BuiltinExchangeType.DIRECT);
     //声明一个队列
     channel.queueDeclare("disk",false,false,false,null);

     //绑定交换机与队列
     channel.queueBind("disk",EXCHANGE_NAME,"error");


     DeliverCallback deliverCallback = (consumerTag, message) -> {
         System.out.println("ReceiveLogsDirect02控制台打印接受到的消息:" + new String(message.getBody()));
     };

     channel.basicConsume("disk",true,deliverCallback,consumerTag -> {});
 }
}


RPC模式

RPC即客户端远程调用服务端的方法,使用MQ可以实现RPC的异步调用,基于Direct交换机实现。

在这里插入图片描述

  • 在RabbitMQ中,使用RPC通信方式的应用程序被称为RPC客户端,而提供服务的应用程序被称为RPC服务器。

  • 服务端监听RPC请求队列的消息,收到消息后执行服务端的方法,得到方法返回结果。

  • 服务端将RPC方法的结果发送到RPC响应队列

  • 客户端接收Reply队列的消息

虽然RabbitMQ的RPC通信方式可以实现客户端和服务端之间的解耦,实现远程调用,但也会涉及一些缺点:

性能开销:RPC通信方式需要在客户端和服务端之间进行多次网络通信,而每次网络通信都会带来一定的性能开销,因此在高并发场景下,RPC通信可能会影响系统的性能。

实现复杂度:RPC通信方式需要客户端和服务端共同定义一套RPC协议,包括消息格式、参数类型和返回值类型等,这需要一定的实现复杂度,尤其是在跨语言和跨平台的场景中。

依赖可靠的消息代理:RPC通信需要可靠的消息代理来实现消息传递和消息保证,而RabbitMQ等消息代理的可靠性需要进行专门的配置和管理,增加了运维成本。

安全性:由于RPC通信涉及到网络传输,可能会面临数据被劫持、篡改和窃听等安全风险,因此需要采取相应的安全措施,如加密、认证和授权等。

该模式作为了解即可,实际应用并不广泛。具体详见官网:https://www.rabbitmq.com/tutorials

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值