RabbitMQ六种通信模式介绍——路由模式(Routing)


一。简介

本篇博客所讲的为RabbitMQ六种通信模式之一的路由模式。

模式说明

路由模式特点:

  • 队列与交换机的绑定,不能是任意绑定了,而是要指定一个RoutingKey(路由key)
  • 消息的发送方在 向 Exchange发送消息时,也必须指定消息的 RoutingKey。
  • Exchange不再把消息交给每一个绑定的队列,而是根据消息的Routing
  • Key进行判断,只有队列的Routingkey与消息的 Routing key完全一致,才会接收到消息

官网给出的图如下所示:

在这里插入图片描述
图解:

P:生产者,向Exchange发送消息,发送消息时,会指定一个routing key。
X:Exchange(交换机),接收生产者的消息,然后把消息递交给 与routing key完全匹配的队列
C1:消费者,其所在队列指定了需要routing key 为 error 的消息
C2:消费者,其所在队列指定了需要routing key 为 info、error、warning 的消息

二。代码实现

在编码上与 Publish/Subscribe发布与订阅模式 的区别是交换机的类型为:Direct,还有队列绑定交换机的时候需要指定routing key。

1.连接工具类:

import com.rabbitmq.client.Connection;
import com.rabbitmq.client.ConnectionFactory;

/**
 * 创建连接工具类
 */
public class ConnectionUtil {

    public static Connection getConnection() throws Exception {
        //创建连接工厂
        ConnectionFactory connectionFactory = new ConnectionFactory();
        //主机地址;默认为 localhost
        connectionFactory.setHost("localhost");
        //连接端口;默认为 5672
        connectionFactory.setPort(5672);
        //虚拟主机名称;默认为 /
        connectionFactory.setVirtualHost("hello");
        //连接用户名;默认为guest
        connectionFactory.setUsername("guest");
        //连接密码;默认为guest
        connectionFactory.setPassword("guest");

        //创建连接
        return connectionFactory.newConnection();
    }

}

2.消息生产者:

import com.rabbitmq.client.BuiltinExchangeType;
import com.rabbitmq.client.Channel;
import com.rabbitmq.client.Connection;

/**
 * 路由模式的交换机类型为:direct
 */
public class Producer {

   //交换机名称
   static final String DIRECT_EXCHAGE = "direct_exchange";
   //队列名称
   static final String DIRECT_QUEUE_INSERT = "direct_queue_insert";
   //队列名称
   static final String DIRECT_QUEUE_UPDATE = "direct_queue_update";

   public static void main(String[] args) throws Exception {

       //创建连接
       Connection connection = ConnectionUtil.getConnection();

       // 创建频道
       Channel channel = connection.createChannel();

       /**
        * 声明交换机
        * 参数1:交换机名称
        * 参数2:交换机类型,fanout、topic、direct、headers
        */
       channel.exchangeDeclare(DIRECT_EXCHAGE, BuiltinExchangeType.DIRECT);

       // 声明(创建)队列
       /**
        * 参数1:队列名称
        * 参数2:是否定义持久化队列
        * 参数3:是否独占本次连接
        * 参数4:是否在不使用的时候自动删除队列
        * 参数5:队列其它参数
        */
       channel.queueDeclare(DIRECT_QUEUE_INSERT, true, false, false, null);
       channel.queueDeclare(DIRECT_QUEUE_UPDATE, true, false, false, null);

       //队列绑定交换机
       channel.queueBind(DIRECT_QUEUE_INSERT, DIRECT_EXCHAGE, "insert");
       channel.queueBind(DIRECT_QUEUE_UPDATE, DIRECT_EXCHAGE, "update");

       // 发送信息
       String message = "新增了商品。路由模式;routing key 为 insert " ;
       /**
        * 参数1:交换机名称,如果没有指定则使用默认Default Exchage
        * 参数2:路由key,简单模式可以传递队列名称
        * 参数3:消息其它属性
        * 参数4:消息内容
        */
       channel.basicPublish(DIRECT_EXCHAGE, "insert", null, message.getBytes());
       System.out.println("已发送消息:" + message);

       // 发送信息
       message = "修改了商品。路由模式;routing key 为 update" ;
       /**
        * 参数1:交换机名称,如果没有指定则使用默认Default Exchage
        * 参数2:路由key,简单模式可以传递队列名称
        * 参数3:消息其它属性
        * 参数4:消息内容
        */
       channel.basicPublish(DIRECT_EXCHAGE, "update", null, message.getBytes());
       System.out.println("已发送消息:" + message);

       // 关闭资源
       channel.close();
       connection.close();
    }
}

3.消息消费者1:

import com.rabbitmq.client.*;
import java.io.IOException;

/**
 * 消费者1
 */
public class Consumer1 {

   public static void main(String[] args) throws Exception {
       Connection connection = ConnectionUtil.getConnection();

       // 创建频道
       Channel channel = connection.createChannel();

       //声明交换机
       channel.exchangeDeclare(Producer.DIRECT_EXCHAGE, BuiltinExchangeType.DIRECT);

       // 声明(创建)队列
       /**
        * 参数1:队列名称
        * 参数2:是否定义持久化队列
        * 参数3:是否独占本次连接
        * 参数4:是否在不使用的时候自动删除队列
        * 参数5:队列其它参数
        */
       channel.queueDeclare(Producer.DIRECT_QUEUE_INSERT, true, false, false, null);

       //队列绑定交换机
       channel.queueBind(Producer.DIRECT_QUEUE_INSERT, Producer.DIRECT_EXCHAGE, "insert");

       //创建消费者;并设置消息处理
       DefaultConsumer consumer = new DefaultConsumer(channel){
           @Override
           /**
            * consumerTag 消息者标签,在channel.basicConsume时候可以指定
            * envelope 消息包的内容,可从中获取消息id,消息routingkey,交换机,消息和重传标志(收到消息失败后是否需要重新发送)
            * properties 属性信息
            * body 消息
            */
           public void handleDelivery(String consumerTag, Envelope envelope, AMQP.BasicProperties properties, byte[] body) throws IOException {
               //路由key
               System.out.println("路由key为:" + envelope.getRoutingKey());
               //交换机
               System.out.println("交换机为:" + envelope.getExchange());
               //消息id
               System.out.println("消息id为:" + envelope.getDeliveryTag());
               //收到的消息
               System.out.println("消费者1-接收到的消息为:" + new String(body, "utf-8"));
           }
       };
       //监听消息
       /**
        * 参数1:队列名称
        * 参数2:是否自动确认,设置为true为表示消息接收到自动向mq回复接收到了,mq接收到回复会删除消息,设置为false则需要手动确认
        * 参数3:消息接收到后回调
        */
       channel.basicConsume(Producer.DIRECT_QUEUE_INSERT, true, consumer);
   }
}

4.消息消费者2:

import com.rabbitmq.client.*;
import java.io.IOException;

/**
 * 消费者2
 */
public class Consumer2 {

   public static void main(String[] args) throws Exception {
       Connection connection = ConnectionUtil.getConnection();

       // 创建频道
       Channel channel = connection.createChannel();

       //声明交换机
       channel.exchangeDeclare(Producer.DIRECT_EXCHAGE, BuiltinExchangeType.DIRECT);

       // 声明(创建)队列
       /**
        * 参数1:队列名称
        * 参数2:是否定义持久化队列
        * 参数3:是否独占本次连接
        * 参数4:是否在不使用的时候自动删除队列
        * 参数5:队列其它参数
        */
       channel.queueDeclare(Producer.DIRECT_QUEUE_UPDATE, true, false, false, null);

       //队列绑定交换机
       channel.queueBind(Producer.DIRECT_QUEUE_UPDATE, Producer.DIRECT_EXCHAGE, "update");

       //创建消费者;并设置消息处理
       DefaultConsumer consumer = new DefaultConsumer(channel){
           @Override
           /**
            * consumerTag 消息者标签,在channel.basicConsume时候可以指定
            * envelope 消息包的内容,可从中获取消息id,消息routingkey,交换机,消息和重传标志(收到消息失败后是否需要重新发送)
            * properties 属性信息
            * body 消息
            */
           public void handleDelivery(String consumerTag, Envelope envelope, AMQP.BasicProperties properties, byte[] body) throws IOException {
               //路由key
               System.out.println("路由key为:" + envelope.getRoutingKey());
               //交换机
               System.out.println("交换机为:" + envelope.getExchange());
               //消息id
               System.out.println("消息id为:" + envelope.getDeliveryTag());
               //收到的消息
               System.out.println("消费者2-接收到的消息为:" + new String(body, "utf-8"));
           }
       };
       //监听消息
       /**
        * 参数1:队列名称
        * 参数2:是否自动确认,设置为true为表示消息接收到自动向mq回复接收到了,mq接收到回复会删除消息,设置为false则需要手动确认
        * 参数3:消息接收到后回调
        */
       channel.basicConsume(Producer.DIRECT_QUEUE_UPDATE, true, consumer);
   }
}

三。程序运行效果

1.启动消息生产者,生成交换机direct_exchange,并绑定两个消息队列direct_queue_insert和direct_queue_update,分别发送一条消息进入这两个队列中:

在这里插入图片描述
生成交换机direct_exchange:
在这里插入图片描述

绑定两个消息队列direct_queue_insert和direct_queue_update:
在这里插入图片描述
direct_queue_insert队列中的消息:

在这里插入图片描述
direct_queue_update中的消息:

在这里插入图片描述
2.启动消费者1,声明交换机以及队列并绑定队列,消费direct_queue_insert队列中的消息:

在这里插入图片描述

在这里插入图片描述

3.启动消费者2,声明交换机以及队列并绑定队列,消费direct_queue_update中的消息:

在这里插入图片描述

在这里插入图片描述
结论:

Routing模式要求队列在绑定交换机时要指定routing key,消息会转发到符合routing key的队列。

四。模式总结

1、简单模式 HelloWorld

一个生产者、一个消费者,不需要设置交换机(使用默认的交换机)

2、工作队列模式 Work Queue

一个生产者、多个消费者(竞争关系),不需要设置交换机(使用默认的交换机)

3、发布订阅模式 Publish/subscribe

需要设置类型为fanout的交换机,并且交换机和队列进行绑定,当发送消息到交换机后,交换机会将消息发送到绑定的队列

4、路由模式 Routing

需要设置类型为direct的交换机,交换机和队列进行绑定,并且指定routing key,当发送消息到交换机后,交换机会根据routing key将消息发送到对应的队列

5、通配符模式 Topic

需要设置类型为topic的交换机,交换机和队列进行绑定,并且指定通配符方式的routing key,当发送消息到交换机后,交换机会根据routing key将消息发送到对应的队列

Key Features, Learn to administer, configure, and manage RabbitMQ instancesDiscover ways to secure and troubleshoot RabbitMQ instancesThis book is fully up-to-date with all the latest changes to version 3.5, Book Description, RabbitMQ is Open Source Message Queuing software based on the Advanced Message Queue Protocol Standard written in the Erlang Language. RabbitMQ is an ideal candidate for large-scale projects ranging from e-commerce and finance to Big Data and social networking because of its ease of use and high performance. Managing RabbitMQ in such a dynamic environment can be a challenging task that requires a good understanding not only of how to work properly with the message broker but also of its best practices and pitfalls., Learning RabbitMQ starts with a concise description of messaging solutions and patterns, then moves on to concrete practical scenarios for publishing and subscribing to the broker along with basic administration. This knowledge is further expanded by exploring how to establish clustering and high availability at the level of the message broker and how to integrate RabbitMQ with a number of technologies such as Spring, and enterprise service bus solutions such as MuleESB and WSO2. We will look at advanced topics such as performance tuning, secure messaging, and the internals of RabbitMQ. Finally we will work through case-studies so that we can see RabbitMQ in action and, if something goes wrong, we'll learn to resolve it in the Troubleshooting section., What you will learn, Apply messaging patterns using the message brokerAdminister RabbitMQ using the command line, management Web console, or management REST servicesCreate a cluster of scalable, and highly-available, RabbitMQ instancesUse RabbitMQ with the Spring Framework, MuleESB, WSO2, and Oracle databasesDeploy RabbitMQ using Puppet, Vagrant, or DockerFine-tune the performance of RabbitMQMonitor RabbitMQ using Nagios, Munin, or MonitSecure, troubleshoot, and extend RabbitMQ, About the Author, Martin Toshev is a software developer and Java enthusiast with more than eight years of experience and vast expertise originating from projects in areas such as enterprise Java, social networking, source code analysis, Internet of Things, and investment banking in companies such as Cisco and Deutsche Telekom. He is a graduate of computer science from the University of Sofia. He is also a certified Java professional (SCJP6) and a certified IBM cloud computing solution advisor. His areas of interest include a wide range of Java-related technologies (Servlets, JSP, JAXB, JAXP, JMS, JMX, JAX-RS, JAX-WS, Hibernate, Spring Framework, Liferay Portal, and Eclipse RCP), cloud computing technologies, cloud-based software architectures, enterprise application integration, and relational and NoSQL databases. Martin is one of the leaders of the Bulgarian Java Users group (BGJUG), a regular speaker at Java conferences, and one of the organizers behind the jPrime conference in Bulgaria (http://jprime.io/)., Table of Contents, Introducing RabbitMQDesign Patterns with RabbitMQAdministration, Confi guration, and ManagementClusteringHigh AvailabilityIntegrationsPerformance Tuning and MonitoringTroubleshootingSecurityInternalsContributing to RabbitMQ
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

Keson Z

你的鼓励将是我创作的最大动力

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

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

打赏作者

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

抵扣说明:

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

余额充值