RabbitMQ-三、Java使用--4、主题(Topic)

4、主题(Topic)

上一篇博客中,我们进步改良了我们的日志系统。我们使用direct类型转发器,使得接收者有能力进行选择性的接收日志,,而非fanout那样,只能够无脑的转发。

虽然使用direct类型改良了我们的系统,但是仍然存在一些局限性:它不能够基于多重条件进行路由选择。

接下来我们学习稍微复杂的主题类型的转发器(topic exchange)

1、主题转发(TopicExchange)

发往主题类型的转发器的消息不能随意的设置选择键(routing_key),必须是由点隔开的一系列的标识符组成。标识符可以是任何东西,但是一般都与消息的某些特性相关。一些合法的选择键的例子:"stock.usd.nyse","nyse.vmw","quick.orange.rabbit".你可以定义任何数量的标识符,上限为255个字节。

绑定键和选择键的形式一样。主题类型的转发器背后的逻辑和直接类型的转发器很类似:一个附带特殊的选择键将会被转发到绑定键与之匹配的队列中。需要注意的是:关于绑定键有两种特殊的情况。

*可以匹配一个标识符。
#可以匹配0个或多个标识符。

2、 图解:

我们准备发送关于动物的消息。消息会附加一个选择键包含3个标识符(两个点隔开)。第一个标识符描述动物的速度,第二个标识符描述动物的颜色,第三个标识符描述动物的物种:<speed>.<color>.<species>。

我们创建3个绑定键:Q1与*.orange.*绑定Q2与*.*.rabbit和lazy.#绑定。

可以简单的认为:
Q1对所有的橙色动物感兴趣。
Q2想要知道关于兔子的一切以及关于懒洋洋的动物的一切。

 

一个附带quick.orange.rabbit的选择键的消息将会被转发到两个队列,

附带lazy.orange.elephant的消息也会被转发到两个队列,

另一方面quick.orange.fox只会被转发到Q1,

lazy.brown.fox将会被转发到Q2,

lazy.pink.rabbit虽然与两个绑定键匹配,但是也只会被转发到Q2一次。

quick.brown.fox不能与任何绑定键匹配,所以会被丢弃。

 

注:主题类型的转发器非常强大,可以实现其他类型的转发器。
当一个队列与绑定键#绑定,将会收到所有的消息,类似fanout类型转发器。
当绑定键中不包含任何#与*时,类似direct类型转发器。

3、 完整的例子

发送端:

public class producer6 {

	private static final String EXCHANGE_NAME = "topic_logs";  
	  
    public static void main(String[] argv) throws Exception { 
        // 创建连接和频道  
        ConnectionFactory factory = new ConnectionFactory();  
        factory.setHost("localhost");  
        Connection connection = factory.newConnection();  
        Channel channel = connection.createChannel();  
  
        channel.exchangeDeclare(EXCHANGE_NAME, "topic");  
  
        String[] routing_keys = new String[] { "kernal.info", "cron.warning", "auth.info", "kernel.critical" };  
        for(String routing_key : routing_keys){  
            String msg = UUID.randomUUID().toString();  
            channel.basicPublish(EXCHANGE_NAME, routing_key, null, msg.getBytes());  
            System.out.println(" [x] Sent routingKey = "+routing_key+" ,msg = " + msg + ".");  
        }  
        channel.close();  
        connection.close();  
    }
  
}

接收端1

public class consumer6_1 {

	private static final String EXCHANGE_NAME = "topic_logs";  
	  
    public static void main(String[] argv) throws Exception { 
        // 创建连接和频道  
        ConnectionFactory factory = new ConnectionFactory();  
        factory.setHost("localhost");  
        Connection connection = factory.newConnection();  
        Channel channel = connection.createChannel();  
        // 声明转发器  
        channel.exchangeDeclare(EXCHANGE_NAME, "topic");  
        // 随机生成一个队列  
        String queueName = channel.queueDeclare().getQueue();  
          
        //接收所有与kernel相关的消息  
        channel.queueBind(queueName, EXCHANGE_NAME, "kernel.*");  
  
        System.out.println(" [*] Waiting for messages about kernel. To exit press CTRL+C");  
  
        QueueingConsumer consumer = new QueueingConsumer(channel);  
        channel.basicConsume(queueName, true, consumer);  
  
        while (true){  
            QueueingConsumer.Delivery delivery = consumer.nextDelivery();  
            String message = new String(delivery.getBody());  
            String routingKey = delivery.getEnvelope().getRoutingKey();  
  
            System.out.println(" [x] Received routingKey = " + routingKey+ ",msg = " + message + ".");  
        }  
    }
  
}

接收端2

channel.queueBind(queueName, EXCHANGE_NAME,"kernel.*");

其它代码同接收端1

运行结果:

[x] SentroutingKey = kernal.info ,msg = a7261f0d-18cc-4c85-ba80-5ecd9283dae7.
[x] Sent routingKey = cron.warning ,msg = 0c7e4484-66e0-4846-a869-a7a266e16281.
[x] Sent routingKey = auth.info ,msg = 3273f21f-6e6e-42f2-83df-1f2fafa7a19a.
[x] Sent routingKey = kernel.critical ,msg =f65d3e1a-0619-4f85-8b0d-59375380ecc9.

---------------------------------------------------

[*] Waiting formessages about kernel. To exit press CTRL+C
[x] Received routingKey = kernel.critical,msg =f65d3e1a-0619-4f85-8b0d-59375380ecc9.

---------------------------------------------------

[*] Waiting forcritical messages. To exit press CTRL+C
[x] Received routingKey = kernel.critical,msg =f65d3e1a-0619-4f85-8b0d-59375380ecc9.

可以看到,我们通过使用topic类型的转发器,成功实现了多重条件选择的订阅。


原文:http://blog.csdn.net/lmj623565791/article/details/37706355


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值