RabbitMQ实例教程:主题交换机

本文涉及的产品
日志服务 SLS,月写入数据量 50GB 1个月
简介:

  前面的例子中,尽管我们使用了direct路由代替fanout路由解决了盲目广播的问题,但direct路由也有它的缺陷,他不能基于多个标准做路由转发。


  在上面的日志系统中,如果不仅想基于日志等级做订阅,也想根据日志的发生源做订阅该怎么处理呢?这时候你可能想到了unix系统工具中的syslog服务,它不仅基于日志等级(info/warn/crit...)进行路由转发,也会根据操作(auth/cron/kern...)做路由转发。


  如果是那样的话,日志系统就灵活多了,它不仅能够监听来自‘cron’的关键错误,也能监听来自'kern'的所有日志。其实主题交换机(topic exchange)就能解决这种问题。


  主题交换机(Topic exchange)


  主题交换机的路由代码不能是任意写的,必须是小树点分隔开的一组单词列表。这些单词可以随便写,但通常是与连接消息特征有关的单词。有效地路由代码应该是这样的“stock.usd.nyse”,“nyse.vmw”,“quick.orange.rabbit”。路由代码可以随便写,但是长度限制在255字节。


  注意,绑定代码也必须在同一个表单中。topic交换机与direct交换机类似-具有特定路由代码的消息会传送给所有匹配绑定代码的队列,但有两个特殊的绑定代码:


  * :它能替代一个单词 


  #:它能替代0或多个单词

wKiom1YekEyRndmFAABl8iEOXGg312.jpg


  该例子中,我们给所有的动物发送消息,符合由三个单词(第一个单词描述速度;第二个单词描述颜色;第三个单词描述物种)组成的路由代码将会发送消息:“<speed>.<colour>.<species>”。

   

  我们创建了三个绑定:Q1使用“*.orange.*”绑定,Q2使用“*.*.rabbit”和“lazy.#”绑定。这些绑定的意义如下:

  

  Q1描述了所有颜色为橙色的动物。

  

  Q2描述了是兔子的动物和懒惰的动物。

  

  这样,“quick.orange.rabbit”消息通过路由转发给Q1、Q2两个队列。"lazy.orange.elephant"消息也会转发给Q1、Q2两个队列。“quick.orange.fox”消息只会转发给Q1队列,"lazy.brown.fox"也只会转发给Q2队列。"lazy.pink.rabbit"会转发给Q2队列一次,尽管它匹配两个绑定。"quick.brown.fox"并不匹配任何一个队列就会被废弃。

  

  如果我们打破规则,每次只发一个或四个单词的话,如“orange”或”quick.orange.male.rabbit“,这些消息不匹配任何绑定,就会被废弃。但如果发送”lazy.orange.male.rabbit“这样的消息的话,由于它匹配最后的绑定仍会被转发到Q2队列中。

    

  主题交换机是一种非常强大的交换机,当它只绑定”#“时,它会接收所有的消息,与fanout交换机类似。当没有使用”*“和”#“符号时,主题交换机的作用等同与direct交换机。


  源代码


EmitLogTopic.java

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
package  com.favccxx.favrabbit;
 
import  com.rabbitmq.client.Channel;
import  com.rabbitmq.client.Connection;
import  com.rabbitmq.client.ConnectionFactory;
 
public  class  EmitLogTopic {
 
     private  static  final  String EXCHANGE_NAME =  "topic_logs" ;
 
     public  static  void  main(String[] argv) {
         Connection connection =  null ;
         Channel channel =  null ;
         try  {
             ConnectionFactory factory =  new  ConnectionFactory();
             factory.setHost( "localhost" );
 
             connection = factory.newConnection();
             channel = connection.createChannel();
 
             channel.exchangeDeclare(EXCHANGE_NAME,  "topic" );
 
             String[] routingKeys = {  "fast.orange.duck" "slow.orange.fish" "grey.rabbit" "fast.black.rabbit" ,
                     "quick.white.rabbit" "lazy.dog" "lazy.black.pig"  };
             String[] messages = {  "Hello" "Guys" "Girls" "Babies"  };
 
             for  ( int  i =  0 ; i < routingKeys.length; i++) {
                 for  ( int  j =  0 ; j < messages.length; j++) {
                     channel.basicPublish(EXCHANGE_NAME, routingKeys[i],  null , messages[j].getBytes( "UTF-8" ));
                     System.out.println( " [x] Sent '"  + routingKeys[i] +  "':'"  + messages[j] +  "'" );
                 }
             }
         catch  (Exception e) {
             e.printStackTrace();
         finally  {
             if  (connection !=  null ) {
                 try  {
                     connection.close();
                 catch  (Exception ignore) {
                 }
             }
         }
     }
}


ReceiveLogsTopic.java

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
package  com.favccxx.favrabbit;
 
import  java.io.IOException;
 
import  com.rabbitmq.client.AMQP;
import  com.rabbitmq.client.Channel;
import  com.rabbitmq.client.Connection;
import  com.rabbitmq.client.ConnectionFactory;
import  com.rabbitmq.client.Consumer;
import  com.rabbitmq.client.DefaultConsumer;
import  com.rabbitmq.client.Envelope;
 
public  class  ReceiveLogsTopic {
 
     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();
 
         String[] bindingKeys = {  "*.orange.*" "*.*.rabbit" "lazy.#"  };
         for  ( final  String bindingKey : bindingKeys) {
             channel.queueBind(queueName, EXCHANGE_NAME, bindingKey);
             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( "["  + bindingKey +  "] Received message :'"  + message +  "' from routingKey : "  + envelope.getRoutingKey());
                 }
             };
             channel.basicConsume(queueName,  true , consumer);
         }
 
     }
}


运行消息发送器,在消息接收平台输出内容如下

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
[*.orange.*] Received message : 'Hello'  from routingKey : fast.orange.duck
[*.*.rabbit] Received message : 'Guys'  from routingKey : fast.orange.duck
[lazy. #] Received message :'Girls' from routingKey : fast.orange.duck
[*.orange.*] Received message : 'Babies'  from routingKey : fast.orange.duck
[*.*.rabbit] Received message : 'Hello'  from routingKey : slow.orange.fish
[lazy. #] Received message :'Guys' from routingKey : slow.orange.fish
[*.orange.*] Received message : 'Girls'  from routingKey : slow.orange.fish
[*.*.rabbit] Received message : 'Babies'  from routingKey : slow.orange.fish
[lazy. #] Received message :'Hello' from routingKey : fast.black.rabbit
[*.orange.*] Received message : 'Guys'  from routingKey : fast.black.rabbit
[*.*.rabbit] Received message : 'Girls'  from routingKey : fast.black.rabbit
[lazy. #] Received message :'Babies' from routingKey : fast.black.rabbit
[*.orange.*] Received message : 'Hello'  from routingKey : quick.white.rabbit
[*.*.rabbit] Received message : 'Guys'  from routingKey : quick.white.rabbit
[lazy. #] Received message :'Girls' from routingKey : quick.white.rabbit
[*.orange.*] Received message : 'Babies'  from routingKey : quick.white.rabbit
[*.*.rabbit] Received message : 'Hello'  from routingKey : lazy.dog
[lazy. #] Received message :'Guys' from routingKey : lazy.dog
[*.orange.*] Received message : 'Girls'  from routingKey : lazy.dog
[*.*.rabbit] Received message : 'Babies'  from routingKey : lazy.dog
[lazy. #] Received message :'Hello' from routingKey : lazy.black.pig
[*.orange.*] Received message : 'Guys'  from routingKey : lazy.black.pig
[*.*.rabbit] Received message : 'Girls'  from routingKey : lazy.black.pig
[lazy. #] Received message :'Babies' from routingKey : lazy.black.pig




本文转自 genuinecx 51CTO博客,原文链接:http://blog.51cto.com/favccxx/1703031,如需转载请自行联系原作者
相关实践学习
消息队列RocketMQ版:基础消息收发功能体验
本实验场景介绍消息队列RocketMQ版的基础消息收发功能,涵盖实例创建、Topic、Group资源创建以及消息收发体验等基础功能模块。
消息队列 MNS 入门课程
1、消息队列MNS简介 本节课介绍消息队列的MNS的基础概念 2、消息队列MNS特性 本节课介绍消息队列的MNS的主要特性 3、MNS的最佳实践及场景应用 本节课介绍消息队列的MNS的最佳实践及场景应用案例 4、手把手系列:消息队列MNS实操讲 本节课介绍消息队列的MNS的实际操作演示 5、动手实验:基于MNS,0基础轻松构建 Web Client 本节课带您一起基于MNS,0基础轻松构建 Web Client
目录
相关文章
|
2月前
|
消息中间件 Java Spring
SpringBoot实现RabbitMQ的广播交换机(SpringAMQP 实现Fanout广播交换机)
SpringBoot实现RabbitMQ的广播交换机(SpringAMQP 实现Fanout广播交换机)
31 2
|
2月前
|
消息中间件 Java RocketMQ
RocketMQ实战教程之RocketMQ安装
这是一篇关于RocketMQ安装的实战教程,主要介绍了在CentOS系统上使用传统安装和Docker两种方式安装RocketMQ。首先,系统需要是64位,并且已经安装了JDK 1.8。传统安装包括下载安装包,解压并启动NameServer和Broker。Docker安装则涉及安装docker和docker-compose,然后通过docker-compose.yaml文件配置并启动服务。教程还提供了启动命令和解决问题的提示。
|
2月前
|
消息中间件 前端开发 数据库
RocketMQ实战教程之MQ简介与应用场景
RocketMQ实战教程介绍了MQ的基本概念和应用场景。MQ(消息队列)是生产者和消费者模型,用于异步传输数据,实现系统解耦。消息中间件在生产者发送消息和消费者接收消息之间起到邮箱作用,简化通信。主要应用场景包括:1)应用解耦,如订单系统与库存系统的非直接交互;2)异步处理,如用户注册后的邮件和短信发送延迟处理,提高响应速度;3)流量削峰,如秒杀活动限制并发流量,防止系统崩溃。
|
2月前
|
消息中间件 存储 Apache
RocketMQ实战教程之常见概念和模型
Apache RocketMQ 实战教程介绍了其核心概念和模型。消息是基本的数据传输单元,主题是消息的分类容器,支持字节、数字和短划线命名,最长64个字符。消息类型包括普通、顺序、事务和定时/延时消息。消息队列是实际存储和传输消息的容器,是主题的分区。消费者分组是一组行为一致的消费者的逻辑集合,也有命名限制。此外,文档还提到了一些使用约束和建议,如主题和消费者组名的命名规则,消息大小限制,请求超时时间等。RocketMQ 提供了多种消息模型,包括发布/订阅模型,有助于理解和优化消息处理。
|
20天前
|
消息中间件
02.交换机RabbitMQ交换机
02.交换机RabbitMQ交换机
14 0
|
2月前
|
消息中间件 存储 Java
RocketMQ实战教程之NameServer与BrokerServer
这是一个关于RocketMQ实战教程的概要,主要讨论NameServer和BrokerServer的角色。NameServer负责管理所有BrokerServer,而BrokerServer存储和传输消息。生产者和消费者通过NameServer找到合适的Broker进行交互,不需要直接知道Broker的具体信息。工作流程包括生产者向NameServer查询后发送消息到Broker,以及消费者同样通过NameServer获取消息进行消费。这种设计类似于服务注册中心的概念,便于系统扩展和集群管理。
|
24天前
|
消息中间件 Java Spring
最新spingboot整合rabbitmq详细教程
最新spingboot整合rabbitmq详细教程
|
2月前
|
消息中间件 Cloud Native 自动驾驶
RocketMQ实战教程之MQ简介
Apache RocketMQ 是一个云原生的消息流平台,支持消息、事件和流处理,适用于云边端一体化场景。官网提供详细文档和下载资源:[RocketMQ官网](https://rocketmq.apache.org/zh/)。示例中提到了RocketMQ在物联网(如小米台灯)和自动驾驶等领域的应用。要开始使用,可从[下载页面](https://rocketmq.apache.org/zh/download)获取软件。
|
2月前
|
消息中间件 中间件 Java
RocketMQ实战教程之几种MQ优缺点以及选型
该文介绍了几种主流消息中间件,包括ActiveMQ、RabbitMQ、RocketMQ和Kafka。ActiveMQ和RabbitMQ是较老牌的选择,前者在中小企业中常见,后者因强大的并发能力和活跃社区而流行。RocketMQ是阿里巴巴的开源产品,适用于大规模分布式系统,尤其在数据可靠性方面进行了优化。Kafka最初设计用于大数据日志处理,强调高吞吐量。在选择MQ时,考虑因素包括性能、功能、开发语言、社区支持、学习难度、稳定性和集群功能。小型公司推荐使用RabbitMQ,而大型公司则可在RocketMQ和Kafka之间根据具体需求抉择。
|
1月前
|
消息中间件 存储 Java
RocketMQ下载安装、集群搭建保姆级教程
RocketMQ下载安装、集群搭建保姆级教程
40 0

热门文章

最新文章