rabbitmq 主题交换机java 实现

主题交换机

扇形(fanout)exchange 会把所有的消息发送到绑定的queue,只是做一个广播。
直连(direct)exchange 把消息发送到绑定的queue 的 routing key与消息的routing key相同的queue。
尽管直连交换机能够改善我们的系统,但是它也有它的限制 —— 没办法基于多个标准执行路由操作。

在日志系统中我们不会单独订阅只基于级别(error,info,warning)的日志,还会希望订阅设备或者不同服务(web ,service,email等服务)的日志。这样的话就要求有很大的灵活性,这样就可以订阅邮件服务的error 日志,也可以订阅所有的error 日志。

发送到主题交换机(topic exchange)的消息不可以携带随意什么样子的路由键(routing_key),它的路由键必须是一个由.分隔开的词语列表。这些单词随便是什么都可以,但是最好是跟携带它们的消息有关系的词汇。以下是几个推荐的例子:"stock.usd.nyse", "nyse.vmw", "quick.orange.rabbit"。词语的个数可以随意,但是不要超过255字节。
绑定键也必须拥有同样的格式。主题交换机背后的逻辑跟直连交换机很相似 —— 一个携带着特定路由键的消息会被主题交换机投递给绑定键与之想匹配的队列。但是它的绑定键和路由键有两个特殊应用方式:

* (星号) 用来表示一个单词.
# (井号) 用来表示任意数量(零个或多个)单词。

主题交换机是很强大的,它可以表现出跟其他交换机类似的行为
当一个队列的绑定键为 "#"(井号) 的时候,这个队列将会无视消息的路由键,接收所有的消息。
当 * (星号) 和 # (井号) 这两个特殊字符都未在绑定键中出现的时候,此时主题交换机就拥有的直连交换机的行为。

示例
将主题交换机应用到我们的日志系统中。在开始工作前,我们假设日志的路由键由两个单词组成,路由键看起来是这样的:service.severity代码跟上一篇教程差不多
假设有 order,user,email 服务,日志级别有error,info,warning。
生产者:服务和日志级别的排列组合作为routing key(如 order.email,order.info,order.warning,user.error,user.info .....),分别发送3条日志。
消费者:定义消费者,A、接收所有error 级别日志( *.error);B、接收 order 服务的日志(order.*),C、接收user服务和info级别的日志(user.* *.info),D、接收所有的日志(#)
rabbitmq 主题交换机java 实现_第1张图片

代码
代码和路由(http://blog.csdn.net/convict_eva/article/details/52312435)的代码没有多大区别,只是把exchange 的名称和类型修改为logs_topic 和 topic,
发送消息的routingKey值为:order.error ,order.info,order.warning 等等
消息接收绑定的路由时根据上面“消费者”定义的设置routing key 的值。
代码结构如下:

rabbitmq 主题交换机java 实现_第2张图片

Send 生产者发送消息:

//级别
private static String[] LOG_LEVELS={"error","info","warning","other"};
//服务
private static String[] SERVERS = {"order","user","email"};

发送消息

for(String server : SERVERS){
    for(String level:LOG_LEVELS){
        String routingKey = server+"."+level;//组合路由键,如 order.error
        String message = "";
        for(int i=0;i<3;i++){//每一种路由键发送3条消息
            message="hello.."+i+"___"+routingKey;
            //发送消息指定routing_key
            channel.basicPublish(RabbitmqConfigure.EXCHANGE_NAME, routingKey, null, message.getBytes());
            System.out.println(" [x] Sent '" + message + "'");
        }
    }
}


接收消息,队列和routing key的绑定修改:

        A:channel.queueBind(queueName, RabbitmqConfigure.EXCHANGE_NAME,"*.error");
        B:channel.queueBind(queueName, RabbitmqConfigure.EXCHANGE_NAME,"order.*");
        C:channel.queueBind(queueName, RabbitmqConfigure.EXCHANGE_NAME,"user.*");
               channel.queueBind(queueName, RabbitmqConfigure.EXCHANGE_NAME,"*.info");
        D:channel.queueBind(queueName, RabbitmqConfigure.EXCHANGE_NAME,"#");


测试
先运行RecvA,RecvB,RecvC,RecvD  再运行Send 发送消息。

发送消息:

    rabbitmq 主题交换机java 实现_第3张图片

        A、接收所有error 级别日志( *.error)

            rabbitmq 主题交换机java 实现_第4张图片

        B、接收 order 服务的日志(order.*)

            rabbitmq 主题交换机java 实现_第5张图片

        C、接收user服务和info级别的日志(user.* *.info)

            rabbitmq 主题交换机java 实现_第6张图片

        D、接收所有的日志(#)

            rabbitmq 主题交换机java 实现_第7张图片


不指定发送消息的routing key( routing key 设置为空字符串,channel.basicPublish(RabbitmqConfigure.EXCHANGE_NAME, "", null, "路由键为空字符串".getBytes()); ),绑定路由键为 “*” 的队列到消息,绑定为“#” 的队列可以收到。

绑定键为 #.* 的队列会获取到一个名为..的路由键的消息,它会取到一个路由键为单个单词的消息


rabbitmq官网:http://www.rabbitmq.com/tutorials/tutorial-five-java.html

rabbitmq中文:http://rabbitmq.mr-ping.com/tutorials_with_python/[5]Topics.html

code: http://download.csdn.net/detail/convict_eva/9612865




你可能感兴趣的:(rabbitmq)