RabbitMQ--Routing(四)

路由

 在本教程中,我们将为其添加一个功能 - 我们将可以仅订阅一部分消息。例如,我们将能够仅将关键的错误消息引导到日志文件(以节省磁盘空间),同时仍然能够在控制台上打印所有日志消息。

绑定

在以前的例子中,我们已经创建了绑定。你可能会记得如下代码:

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

绑定是交换机和队列之间的关系。这可以简单地读为:队列对来自此交换机的消息感兴趣。

绑定占用额外的routingKey 参数。为了避免与basic_publish 参数混淆,我们将其称为 绑定键。这就是我们如何用一个键创建一个绑定:

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

绑定键的含义取决于交换类型。以前我们以前使用的广播交换机忽略了它的价值。

点对点交换(direct)

我们从上一个教程的日志记录系统向所有消费者广播所有消息。我们希望将其扩展为允许基于其严重性过滤消息。例如,我们可能需要一个将日志消息写入磁盘以仅接收关键错误的程序,而不会浪费警告或信息日志消息上的磁盘空间。

我们使用广播式的交换机,它没有给我们很大的灵活性 - 它只能无意识地广播。

我们将使用点对点交换机。点对点交换背后的路由算法很简单 - 消息传递到绑定密钥与消息的路由密钥完全匹配的队列 。

为了说明,请考虑以下设置:

12180908_ILmz.png

在这个设置中,我们可以看到点对点交换X与两个绑定的队列。第一个队列与绑定键橙色绑定,第二个队列有两个绑定,一个绑定键为黑色,另一个绑定为绿色。

在这样的设置中,发布到具有路由密钥橙色的交换机的消息 将被路由到队列Q1。具有黑色 或绿色路由密钥的消息将转到Q2。所有其他消息将被丢弃。

多重绑定

12180910_WICh.png

使用相同的绑定键绑定多个队列是完全合法的。在我们的示例中,我们可以在X和Q1之间添加绑定键黑色。在这种情况下,点对点交换将表现得像广播,并将消息广播到所有匹配的队列。具有路由密钥黑色的消息将传送到 Q1和Q2。

发出日志

我们将使用此模型进行日志记录系统。而不是广播,我们将发送消息到点对点交换。我们将提供日志严重性作为路由密钥。这样,接收程序将能够选择它想要接收的严重性。我们首先关注发送日志。

一如以往,我们首先要建立交流:

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);
}

把它们放在一起

12180911_LoKY.png

EmitLogDirect.java类的代码:

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);
  }
}

像往常一样编译(参见教程一编译和类路径建议)。为方便起见,我们将在运行示例时使用环境变量$ CP(Windows上的%CP%)作为类路径。

javac -cp $ CP ReceiveLogsDirect.java EmitLogDirect.java

如果您只想将“警告”和“错误”(而不是“信息”)保存到文件中,只需打开控制台并键入:

java -cp $CP ReceiveLogsDirect warning error > logs_from_rabbit.log

如果您想查看屏幕上的所有日志消息,请打开一个新终端,然后执行以下操作:

java -cp $CP ReceiveLogsDirect info warning error
# => [*] Waiting for logs. To exit press CTRL+C

而且,例如,要发出错误日志消息,只需键入:

java -cp $CP EmitLogDirect error "Run. Run. Or it will explode."
# => [x] Sent 'error':'Run. Run. Or it will explode.'

(EmitLogDirect.java源) 和(ReceiveLogsDirect.java源)的完整源代码)

转载于:https://my.oschina.net/flyUnique/blog/877611

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
RabbitMQ-C是一个轻量级的RabbitMQ客户端库,它是用C语言编写的,专为那些需要低级别控制或在资源受限的环境中操作AMQP(Advanced Message Queuing Protocol)的应用设计。它提供了直接访问RabbitMQ服务器的功能,包括发送和接收消息。 在RabbitMQ-C中发送消息的基本步骤如下: 1. **初始化连接**:首先,你需要创建一个连接到RabbitMQ服务器的连接实例,通常通过`amqp_connection_new()`创建。 ```c amqp_connection_t *connection = amqp_connection_new(amqp_uri_new("amqp://localhost"), NULL); ``` 2. **声明交换器和队列**:如果消息需要路由到特定的队列,你需要声明这些资源。 ```c amqp_exchange_t *exchange = amqp_exchange_declare(connection, "your_exchange", AMQP_EX_TYPE_DIRECT, 0, NULL, NULL, NULL); amqp_queue_t *queue = amqp_queue_declare(connection, "your_queue", 0, NULL, NULL, NULL, NULL); ``` 3. **绑定队列到交换器**:确保队列接收到来自交换器的消息,使用`amqp_queue_bind()`方法。 ```c amqp_queue_bind(connection, queue, exchange, "your_routing_key", NULL, NULL); ``` 4. **构建消息**:定义一个消息体(含数据、头部信息),例如使用`amqp_message_new()`创建一个新的AMQP消息。 ```c amqp_message_t *message = amqp_message_new(0, NULL); amqp_basic_publish_props_t *props = amqp_basic_publish_props_new(); ``` 5. **设置消息属性**:填充消息头,如交换器、路由键等,并设置消息持久化选项。 ```c amqp_message_set_properties(message, props, AMQP_CMSG_NONE, "your_exchange", "your_routing_key", NULL, 0, NULL); amqp_basic_publish(connection, exchange, message, AMQP_NOPARAM, NULL, NULL, NULL); ``` 6. **发送消息**:调用`amqp_basic_publish()`方法将消息发送到交换器。 7. **清理**:记得关闭连接、交换器、队列和消息资源。 ```c amqp_message_destroy(message); amqp_queue_delete(connection, queue); amqp_exchange_delete(connection, exchange); amqp_connection_close(connection); ```
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值