RabbitMQ三:Publish-Subscribe

RabbitMQ三:Publish/Subscribe

Exchanges(交换机)

RabbitMQ的消息发送模型核心思想是生产者不直接把消息发送到消息队列中。事实上,生产者不知道自己的消息将会被缓存到哪个队列中。

生产者只像交换机发送消息。一方面,它接收来自生产者的消息,另一方面,将它们推送到队列。交换机必须确切知道如何处理收到的消息。它应该附加到特定队列吗?它应该附加到许多队列吗?或者它应该被丢弃。其规则由交换类型定义 。

交换机有以下几种:direct, topic, headers fanout

创建一个扇出(fanout)类型交换机:

channel.ExchangeDeclare(“logs”,“fanout”);

扇出交换非常简单。它只是将收到的所有消息广播到它知道的所有队列中。

列出所有交换机

sudo rabbitmqctl list_exchanges

默认交换机

前几部分中,我们对交换一无所知,但仍能够向队列发送消息。这是可能的,因为我们使用的是默认交换,我们通过空字符串(”“)来识别。

channel.BasicPublish(exchange: "", routingKey: "task_queue", basicProperties:properties, body: body);

第一个参数是交换的名称。空字符串表示默认或无名交换:消息被路由到具有routingKey指定名称的队列(如果存在)。

临时队列

之前的示例中都是指定名称的队列(hello,task_queue),对应的生产者和消费者之间都要使用相同的消息队列名称。

但是本文中使用的日志系统却不是这样,我们希望了解所有日志消息,而不仅仅是它们的一部分。我们也只对目前流动的消息感兴趣,而不是旧消息。要解决这个问题,我们需要两件事:

  1. 每当我们连接到Rabbit时,我们都需要一个新的空队列。为此,我们可以使用随机名称创建队列,或者让服务器为我们选择随机队列名称。
  2. 一旦我们断开消费者,就应该自动删除队列。

在.NET客户端中,当我们不向 QueueDeclare() 提供参数时,我们使用生成的名称创建一个非持久的,独占的自动删除队列:

var queueName = channel.QueueDeclare().QueueName;

此时,queueName包含一个随机队列名称,它可能看起来像amq.gen-JzTY20BRgKO-HjmUJj0wLg

绑定

我们已经创建了一个扇出交换和一个队列。现在我们需要告诉交换机将消息发送到我们的队列。交换和队列之间的关系称为绑定。

channel.QueueBind(queue: queueName,
                    exchange: "logs",
                    routingKey: "");

从现在开始,日志交换会将消息附加到我们的队列中。

列出所有绑定

rabbitmqctl list_bindings

示例

EmitLog

class EmitLog
{
    static void Main(string[] args)
    {
        var factory = new ConnectionFactory() { HostName = "127.0.0.1" };
        using (var connection = factory.CreateConnection())
        using (var channel = connection.CreateModel())
        {
            channel.ExchangeDeclare(exchange: "logs", type: "fanout");

            var message = GetMessage(args);
            var body = Encoding.UTF8.GetBytes(message);
            channel.BasicPublish(exchange: "logs", routingKey: "", basicProperties: null, body: body);
            Console.WriteLine($" [x] sent {message}");
        }
        Console.WriteLine($" Press [enter] to exit.");
        Console.ReadLine();
    }

    private static string GetMessage(string[] args)
    {
        return ((args.Length > 0) ? string.Join(" ", args) : "info: Hello World!");
    }
}

ReceiveLog


class ReceiveLog
{
    static void Main(string[] args)
    {
        var factory = new ConnectionFactory() { HostName = "127.0.0.1" };
        using (var conncetion = factory.CreateConnection())
        using (var channel = conncetion.CreateModel())
        {
            channel.ExchangeDeclare(exchange: "logs", type: "fanout");
            var queueName = channel.QueueDeclare().QueueName;
            channel.QueueBind(queue: queueName,
                exchange: "logs",
                routingKey: "");
            Console.WriteLine($" [*] Waiting for logs");

            var consumer = new EventingBasicConsumer(channel);
            consumer.Received += (model, ea) =>
            {
                var body = ea.Body;
                var message = Encoding.UTF8.GetString(body);
                Console.WriteLine($" [x] {message}");
            };
            channel.BasicConsume(queue: queueName,
                autoAck: true,
                consumer: consumer);
            Console.WriteLine(" Press [enter] to exit.");
            Console.ReadLine();
        }
    }
}

附:

Publish/Subscribe

Github

猜你喜欢

转载自blog.csdn.net/zhaobw831/article/details/81162232
今日推荐