RabbitMQ Java官方教程(四)----Routing

本文介绍RabbitMQ的Routing模式,通过Direct交换器实现消息的精确路由,仅将消息发送给感兴趣的队列。展示了如何配置Direct交换器及绑定键,并提供了发送与接收日志消息的示例代码。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

RabbitMQ Java官方教程(----Routing

Routing(定位发送)

在前面的教学中我们创建了一个简单的日志系统。我们可以广播日志消息给很多个接收者。

在本次教程中,我们将给它添加一个新的特性——我们将使它可以只订阅消息的一部分,而不是全部接收。例如,我们将只是把关键的错误消息直接发送到日志文件(以节省磁盘空间),同时我们还能够自啊控制台上打印出所有消息。

 

Bindings(绑定)

在之前的例子中我们已经创建了一个绑定关系。代码是这样的:

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

所谓绑定,是建立交换器和队列之间的关系。这个绑定关系可以简单的理解为:这个队列对来自这个交换器的消息感兴趣。

绑定过程中可以使用一个routingKey(个人理解为特定的路径表示)参数。避免与basic_publish参数混淆,我们将它称为绑定键。下面是我们如何用键创建绑定关系:

channel.queueBind(queueName, EXCHANGE_NAME, "black");

绑定键的意义依赖于交换器的类型,像之前用的fanout交换器就会直接忽略这个值。

 

指向交换器

我们之前教学中的日志系统是广播所有的消息给所有的消费者。我们现在要扩展这个功能,允许程序按照轻重缓急过滤消息。就比如说,我们想要一个程序,它将只把严重性的错误日志消息写入磁盘,而不在警告或普通日志信息上浪费磁盘空间。

我们之前用的fanout交换器,它的灵活性太差了。它只是无脑的广播消息。

我们将用direct类型的交换器代替它。direct交换器的路径匹配规则很简单——就是将消息传递到绑定键和routingKey完全匹配的队列。

下面是一个图示:

                        

在这个设置中,我们看到direct交换器绑定了两个队列。第一个队列是用orange最为绑定键,而第二个队列有连个绑定关系,一个键是black还有一个green

在这个设置里,一个推送给routing keyorange的交换器的消息将被定向发送给队列Q1.routing keyblack或者green的将被定向发送给Q2。剩下的所有消息都将直接被舍弃。

 

多重绑定

                          

 

用相同的绑定键绑定多个队列是完全可以。在这个例子中,我们在交换器XQ1之间添加black绑定键。在这种情况中,direct交换器就类似于之前的fanout交换器了,相当于将消息广播到了所有的匹配队列。带有routingkeyblack的消息消息被发送到Q1Q2

 

发送日志

我们将使用这种模式到我们的日志系统中。用direct交换器代替之前的fanout类型交换器。我们将提供一个状态来作为routing key(路由密钥)。这样,接收程序就能够选择它想要接收的严重程度。让我们首先看一下日志。

一如既往的,我们先要建立一个交换器:

channel.exchangeDeclare(EXCHANGE_NAME, "direct");

然后我们准备发送一条消息:

channel.basicPublish(EXCHANGE_NAME, severity, null, message.getBytes());

为了简化问题,我们假设状态有“信息”“警告”“错误”。

 

订阅

接收消息就像前面的教程一样,但有一个例外——我们将为我们感兴趣的每个严重程度创建一个新的绑定关系

String queueName=channel.queueDeclare().getQueue();

for(String severity : argv){

  channel.queueBind(queueName, EXCHANGE_NAME, severity);

}

 

整合程序

                            

 EmitLogDirect.java class:

import com.rabbitmq.client.*;

import java.io.IOException;

public class EmitLogDirect {

 

    private static final String EXCHANGE_NAME = "direct_logs";

 

    public static void main(String[] argv)

                  throws java.io.IOException {

 

        ConnectionFactory factory = new ConnectionFactory();

        factory.setHost("localhost");

        Connection connection = factory.newConnection();

        Channel channel = connection.createChannel();

 

        channel.exchangeDeclare(EXCHANGE_NAME, "direct");

 

        String severity = getSeverity(argv);

        String message = getMessage(argv);

 

        channel.basicPublish(EXCHANGE_NAME, severity, null, message.getBytes());

        System.out.println(" [x] Sent '" + severity + "':'" + message + "'");

 

        channel.close();

        connection.close();

    }

    //..

}

 

ReceiveLogsDirect.java:

import com.rabbitmq.client.*;

import java.io.IOException;

public class ReceiveLogsDirect {

 

  private static final String EXCHANGE_NAME = "direct_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, "direct");

    String queueName = channel.queueDeclare().getQueue();

 

    if (argv.length < 1){

      System.err.println("Usage: ReceiveLogsDirect [info] [warning] [error]");

      System.exit(1);

    }

 

    for(String severity : argv){

      channel.queueBind(queueName, EXCHANGE_NAME, severity);

    }

    System.out.println(" [*] Waiting for messages. To exit press CTRL+C");

 

    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(" [x] Received '" + envelope.getRoutingKey() + "':'" + message + "'");

      }

    };

    channel.basicConsume(queueName, true, consumer);

  }

}

 

(源码:EmitLogDirect.java  ReceiveLogsDirect.java 

下一篇教程我们将了解如何根据模式侦听消息

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值