RabbitMQ最常用的三种模式详解 Fanout Direct Topic 【消息中间件】


rabbit有direct路由模式,topic通配符主题订阅模式,fanout广播发布模式,下面将逐一详细的讲解三种模式的用法及应用场景。

Fanout Exchange——订阅模式
Direct Exchange——路由模式
Topic Exchange——通配符模式

Fanout模式

不处理路由键,只需要简单的将队列绑定到交换机上。一个发送到减缓及的消息,都会被转发到与该交换机绑定的所有队列上。
在这里插入图片描述
Fanout交换机转发消息是最快的。

代码示例:
发布者:

public class FanoutProducer {
 
  public static void main(String[] args) throws Exception {
    //1. 创建一个 ConnectionFactory 并进行设置
    ConnectionFactory factory = new ConnectionFactory();
    factory.setHost("localhost");
    factory.setVirtualHost("/");
    factory.setUsername("guest");
    factory.setPassword("guest");
 
    //2. 通过连接工厂来创建连接
    Connection connection = factory.newConnection();
 
    //3. 通过 Connection 来创建 Channel
    Channel channel = connection.createChannel();
 
    //4. 声明
    String exchangeName = "test_fanout_exchange";
    String routingKey1 = "item.update";
    String routingKey2 = "";
    String routingKey3 = "ookjkjjkhjhk";//任意routingkey
 
    //5. 发送
    String msg = "this is fanout msg";
    channel.basicPublish(exchangeName, routingKey1, null, msg.getBytes());
    channel.basicPublish(exchangeName, routingKey2, null, msg.getBytes());
    channel.basicPublish(exchangeName, routingKey3, null, msg.getBytes());
    System.out.println("发送消息 : " + msg);
 
    //6. 关闭连接
    channel.close();
    connection.close();
  }
}

订阅者:

public class FanoutConsumer {
  public static void main(String[] args) throws Exception {
    //1. 创建一个 ConnectionFactory 并进行设置
    ConnectionFactory factory = new ConnectionFactory();
    factory.setHost("localhost");
    factory.setVirtualHost("/");
    factory.setUsername("guest");
    factory.setPassword("guest");
    factory.setAutomaticRecoveryEnabled(true);
    factory.setNetworkRecoveryInterval(3000);
 
    //2. 通过连接工厂来创建连接
    Connection connection = factory.newConnection();
 
    //3. 通过 Connection 来创建 Channel
    Channel channel = connection.createChannel();
 
    //4. 声明
    String exchangeName = "test_fanout_exchange";
    String queueName = "test_fanout_queue";
    String routingKey = "item.#";
    channel.exchangeDeclare(exchangeName, "fanout", true, false, null);
    channel.queueDeclare(queueName, false, false, false, null);
 
    //一般不用代码绑定,在管理界面手动绑定
    channel.queueBind(queueName, exchangeName, routingKey);
 
    //5. 创建消费者并接收消息
    Consumer consumer = 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(" 收到消息 '" + message + "'");
      }
    };
 
    //6. 设置 Channel 消费者绑定队列
    channel.basicConsume(queueName, true, consumer);
  }
}

Direct 模式

所有发送到 Direct Exchange 的消息被转发到 RouteKey 中指定的 Queue。
Direct 模式可以使用 RabbitMQ 自带的 Exchange: default Exchange,所以不需要将 Exchange 进行任何绑定(binding)操作。
消息传递时,RouteKey 必须完全匹配才会被队列接收,否则该消息会被抛弃
在这里插入图片描述
生产者:

public class DirectProducer {
  public static void main(String[] args) throws Exception {
    //1. 创建一个 ConnectionFactory 并进行设置
    ConnectionFactory factory = new ConnectionFactory();
    factory.setHost("localhost");
    factory.setPort(5672);
    factory.setVirtualHost("/");
    factory.setUsername("guest");
    factory.setPassword("guest");
 
    //2. 通过连接工厂来创建连接
    Connection connection = factory.newConnection();
 
    //3. 通过 Connection 来创建 Channel
    Channel channel = connection.createChannel();
 
    //4. 声明
    String exchangeName = "test_direct_exchange";
    String routingKey = "item.direct";
 
    //5. 发送
    String msg = "this is direct msg";
    //6.发送消息给队列queue
    /*参数1: 交换机
      参数2:队列、路由key
      参数3:消息的状态控制
  	  参数4:消息主题
    */
    channel.basicPublish(exchangeName, routingKey, null, msg.getBytes());
    System.out.println("发送消息 : " + msg);
 
    //6. 关闭连接
    channel.close();
    connection.close();
  }
}

消费者:

public class DirectConsumer {
 
  public static void main(String[] args) throws Exception {
    //1. 创建一个 ConnectionFactory 并进行设置
    ConnectionFactory factory = new ConnectionFactory();
    factory.setHost("localhost");
    factory.setPort(5672);
    factory.setVirtualHost("/");
    factory.setUsername("guest");
    factory.setPassword("guest");
    factory.setAutomaticRecoveryEnabled(true);
    factory.setNetworkRecoveryInterval(3000);
    
    //2. 通过连接工厂来创建连接
    Connection connection = factory.newConnection();
 
    //3. 通过 Connection 来创建 Channel
    Channel channel = connection.createChannel();
 
    //4. 声明
    String exchangeName = "test_direct_exchange";
    String queueName = "test_direct_queue";
    String routingKey = "item.direct";
    channel.exchangeDeclare(exchangeName, "direct", true, false, null);
    //5.通过创建交换机,声明队列,绑定关系,路由key,发送消息和接受消息
    /*参数2: 是否持久化,非持久化消息会存盘吗?会存盘,但是会随着重启服务器而丢失
      参数3:是否独占队列 
      参数4:是否自动删除,随着最后一个消费者消息完毕消息以后是否把队列自动删除
  	  参数5:携带附属属性
    */
  channel.queueDeclare(queueName, false, false, false, null);
 
    //一般不用代码绑定,在管理界面手动绑定
    channel.queueBind(queueName, exchangeName, routingKey);
 
    //5. 创建消费者并接收消息
    Consumer consumer = 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(" 收到消息 '" + message + "'");
      }
    };
 
    //6. 设置 Channel 消费者绑定队列
    channel.basicConsume(queueName, true, consumer);
 
  }
}

Topic 模式

可以使用通配符进行模糊匹配

符号’#" 匹配一个或多个词
符号"*”匹配不多不少一个词

例如

'log.#“能够匹配到’log.info.oa”
"log.*"只会匹配到"log.erro“
在这里插入图片描述
生产者:

public class TopicProducer {
 
  public static void main(String[] args) throws Exception {
    //1. 创建一个 ConnectionFactory 并进行设置
    ConnectionFactory factory = new ConnectionFactory();
    factory.setHost("localhost");
    factory.setVirtualHost("/");
    factory.setUsername("guest");
    factory.setPassword("guest");
 
    //2. 通过连接工厂来创建连接
    Connection connection = factory.newConnection();
 
    //3. 通过 Connection 来创建 Channel
    Channel channel = connection.createChannel();
 
    //4. 声明
    String exchangeName = "test_topic_exchange";
    String routingKey1 = "item.update";
    String routingKey2 = "item.delete";
    String routingKey3 = "user.add";
 
    //5. 发送
    String msg = "this is topic msg";
    channel.basicPublish(exchangeName, routingKey1, null, msg.getBytes());
    channel.basicPublish(exchangeName, routingKey2, null, msg.getBytes());
    channel.basicPublish(exchangeName, routingKey3, null, msg.getBytes());
    System.out.println("发送消息 : " + msg);
 
    //6. 关闭连接
    channel.close();
    connection.close();
  }
}

消费者:

public class TopicConsumer {
 
  public static void main(String[] args) throws Exception {
    //1. 创建一个 ConnectionFactory 并进行设置
    ConnectionFactory factory = new ConnectionFactory();
    factory.setHost("localhost");
    factory.setVirtualHost("/");
    factory.setUsername("guest");
    factory.setPassword("guest");
    factory.setAutomaticRecoveryEnabled(true);
    factory.setNetworkRecoveryInterval(3000);
 
    //2. 通过连接工厂来创建连接
    Connection connection = factory.newConnection();
 
    //3. 通过 Connection 来创建 Channel
    Channel channel = connection.createChannel();
 
    //4. 声明
    String exchangeName = "test_topic_exchange";
    String queueName = "test_topic_queue";
    String routingKey = "item.#";
    channel.exchangeDeclare(exchangeName, "topic", true, false, null);
    channel.queueDeclare(queueName, false, false, false, null);
 
    //一般不用代码绑定,在管理界面手动绑定
    channel.queueBind(queueName, exchangeName, routingKey);
 
    //5. 创建消费者并接收消息
    Consumer consumer = 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(" 收到消息 '" + message + "'");
      }
    };
    //6. 设置 Channel 消费者绑定队列
    channel.basicConsume(queueName, true, consumer);
 
  }
}

补充
生产者也可以定义队列,例如简单模式生产:

//简单模式
public class Producer{
    //1.创建连接工厂
    ConnectionFactory connectionFactory = new ConnectionFactory();
    connectionFactory.setHost("10.15.0.9");
    connectionFactory.setPort(5672);
    connectionFactory.setUsername("admin");
    connectionFactory.setPassword("admin");
    connectionFactory.setVirtualHost("/");
    Connection connection = connectionFactory.newConnection("生产者");
    //2.创建通道
    Channel channel = connection.createChannel();
    //3.通过创建交换机,声明队列,绑定关系,路由key,发送消息和接受消息
    /*参数1: 是否持久化,非持久化消息会存盘吗?会存盘,但是会随着重启服务器而丢失
      参数2:是否独占队列 
      参数3:是否自动删除,随着最后一个消费者消息完毕消息以后是否把队列自动删除
  	  参数4:携带附属属性
    */
    String queueName = "queue1";
    channel.queueDeclare(queueName,false,false,false,null);
    //4.发送消息给队列queue
    /*参数1: 交换机
      参数2:队列、路由key
      参数3:消息的状态控制
  	  参数4:消息主题
    */
    //面试题:可以存在没有交换机的队列吗?不可能,虽然没有指定交换机但是一定会存在一个默认的交换机
    String message = "Hello";
    channel.basicPublish("",message, null,message.getBytes());
    //5.关闭
    channel.close();
    connection.close();
}

消费:

//简单模式
public class Consumer{
    //1.创建连接工厂
    ConnectionFactory connectionFactory = new ConnectionFactory();
    connectionFactory.setHost("10.15.0.9");
    connectionFactory.setPort(5672);
    connectionFactory.setUsername("admin");
    connectionFactory.setPassword("admin");
    connectionFactory.setVirtualHost("/");
    Connection connection = connectionFactory.newConnection("生产者");
    //2.创建通道
    Channel channel = connection.createChannel();
	//3.接受内容
    channel.basicConsume("queue1",true,new DefaultConsumer(){
        public void handle(String consumerTag, Delivery message) throws IOException {
          System.out.println(new String("收到消息是" + new String(meassage.getBody()),"UTF-8"));
        },new CancelCallback(){
            public void handle(String consumerTag) throws IOException {
                System.out.println("接受失败了");
        }
      });
    //4.关闭
    channel.close();
    connection.close();
}
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

杵意

谢谢金主打赏呀!!

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值