为什么发布到扇出交换也发布到直接交换?

时间:2019-04-10 03:55:29

标签: c# .net .net-core rabbitmq

我正在尝试获得RabbitMQ设置,在这里我可以选择将消息发布为服务,以扇出或直接发布。但是,当我发布到扇出交换时,我看到了传递给所有服务的消息,而且还以循环方式传递。因此,其中一项服务总是两次看到相同的消息。

这是完整的副本:

using System;
using RabbitMQ.Client;
using RabbitMQ.Client.Events;

namespace rabbitmq_exchanges_repro
{
    class Program
    {
        static void Main(string[] args)
        {
            var hostName = "localhost";
            var factory = new ConnectionFactory
            {
                AutomaticRecoveryEnabled = true,
                HostName = hostName,
            };

            var connection = factory.CreateConnection();
            var model = connection.CreateModel();

            var serviceName = "service1";

            // This queue is for round-robin messages distributed to instances of the service with the specified service name.
            var directExchangeName = $"{serviceName}-direct";
            model.QueueDeclare(
                serviceName,
                durable: true,
                exclusive: false,
                autoDelete: false);
            model.ExchangeDeclare(
                exchange: directExchangeName,
                type: "direct",
                durable: true,
                autoDelete: false);
            model.QueueBind(
                queue: serviceName,
                exchange: directExchangeName,
                routingKey: string.Empty);

            // This is for fanout messages distributed to all services with the specified service name.
            var fanoutExchangeName = $"{serviceName}-fanout";
            model.ExchangeDeclare(
                exchange: fanoutExchangeName,
                type: "fanout",
                durable: true,
                autoDelete: false);
            var fanoutQueueName = model
                .QueueDeclare()
                .QueueName;
            model.QueueBind(
                queue: fanoutQueueName,
                exchange: fanoutExchangeName,
                routingKey: string.Empty);

            var directConsumer = new EventingBasicConsumer(model);
            var fanoutConsumer = new EventingBasicConsumer(model);
            var workItemConsumerTag = model.BasicConsume(
                queue: serviceName,
                autoAck: true,
                consumer: directConsumer);
            var fanoutConsumerTag = model.BasicConsume(
                queue: fanoutQueueName,
                autoAck: true,
                consumer: fanoutConsumer);

            directConsumer.Received += (o, e) =>
            {
                Console.WriteLine("Received message (direct)");
            };
            fanoutConsumer.Received += (o, e) =>
            {
                Console.WriteLine("Received message (fanout)");
            };

            Console.WriteLine("[P]ublish");
            Console.WriteLine("E[x]it");
            var exit = false;

            while (!exit)
            {
                var key = Console.ReadKey();

                switch (key.Key)
                {
                    case ConsoleKey.P:
                        model
                            .BasicPublish(
                                exchange: fanoutExchangeName,
                                routingKey: string.Empty,
                                body: new byte[] { 1, 2, 3 });
                        break;
                    case ConsoleKey.X:
                        exit = true;
                        break;
                }
            }

            model.BasicCancel(workItemConsumerTag);
            model.BasicCancel(fanoutConsumerTag);

            model.Close();
            model.Dispose();

            connection.Close();
            connection.Dispose();
        }
    }
}

在两个单独的控制台窗口中运行以上代码。如果在一个窗口中按P,您会看到一个实例输出了我期望的值:

Received message (fanout)

但是另一个窗口输出:

Received message (fanout)
Received message (direct)

尽管事实是PublishBasic调用指定了扇出交换名称。这里发生了什么?如何确保在这种情况下不涉及直接交换?

1 个答案:

答案 0 :(得分:1)

我无法使用RabbitMQ 3.7.14和您的代码进行复制。我只在每个终端窗口中收到“收到的消息(扇出)”消息。也许RabbitMQ中有旧的绑定?您应该重置实例并重试。


注意: RabbitMQ团队监视rabbitmq-users mailing list,并且有时仅在StackOverflow上回答问题。