简体   繁体   English

RabbitMQ:多个消费者如何从同一个队列接收消息?

[英]RabbitMQ: How multiple consumers can receive messages from the same queue?

I run the producer, it generates N messages, i see them on the dashboard.我运行生产者,它生成 N 条消息,我在仪表板上看到它们。 When I run a receiver it receive all messages from the queue and the queue is an empty.当我运行接收器时,它会接收来自队列的所有消息,并且队列是空的。

    static void Receive(string QueName)
    {
        ConnectionFactory connectionFactory = new ConnectionFactory
        {
            HostName = HostName,
            UserName = UserName,
            Password = Password,
        };
        var connection = connectionFactory.CreateConnection();
        var channel = connection.CreateModel();
        channel.BasicQos(0, 1, false);
        MessageReceiver messageReceiver = new MessageReceiver(channel);
        channel.BasicConsume(QueName, false, messageReceiver);
        Console.WriteLine(" Press [enter] to exit.");
        Console.ReadLine();
    }

// Receiver
 public class MessageReceiver : DefaultBasicConsumer
    {
        private readonly IModel _channel;
        public MessageReceiver(IModel channel)
        {
            _channel = channel;
        }
        public override void HandleBasicDeliver(string consumerTag, ulong deliveryTag, bool redelivered, string exchange, string routingKey, IBasicProperties properties, ReadOnlyMemory<byte> body)
        {
            Console.WriteLine($"------------------------------");
            Console.WriteLine($"Consuming Message");
            Console.WriteLine(string.Concat("Message received from the exchange ", exchange));
            Console.WriteLine(string.Concat("Consumer tag: ", consumerTag));
            Console.WriteLine(string.Concat("Delivery tag: ", deliveryTag));
            Console.WriteLine(string.Concat("Routing tag: ", routingKey));
            //Console.WriteLine(string.Concat("Message: ", Encoding.UTF8.GetString(body)));

            var message = Encoding.UTF8.GetString(body.ToArray());
            Console.WriteLine(string.Concat("Message: ", message));
            Console.WriteLine($"------------------------------");
            _channel.BasicAck(deliveryTag, false);
        }
    }

I need to have multiple producers which generate messages to the same queue.我需要有多个生产者向同一个队列生成消息。 And multiple customers receive messages from the queue.并且多个客户从队列中接收消息。 And messages will be deleted by queue TTL.并且消息将被队列 TTL 删除。 But now the 1st receiver gets all messages from the queue.但是现在第一个接收者从队列中获取所有消息。 How can I do this?我怎样才能做到这一点?

The best solution is: every client should have its own queue, may be with TTL, may be with expiration parameter.最好的解决方案是:每个客户端都应该有自己的队列,可能带有 TTL,可能带有过期参数。

We use “exchange” here, just to show the exchange mechanics in same sample, it's not really needed for the task (check Worker2 project, it works with another queue, which is binded to the same exchange):我们在这里使用“exchange”,只是为了展示同一个示例中的交换机制,它并不是任务真正需要的(检查 Worker2 项目,它与绑定到同一个交换的另一个队列一起工作):

channel.ExchangeDeclare(exchange: “logs”, type: ExchangeType.Fanout);

Full sample of consumption消费全样本

using RabbitMQ.Client;
using RabbitMQ.Client.Events;
using System.Text;
using System.Timers;

class Worker
{
    public static void Main()    
    {
        // Test of timer handler
        System.Timers.TimeraTimer = new System.Timers.Timer();
        aTimer.Elapsed += new ElapsedEventHandler((source, e) 
                                => Console.Write("Timer Test"));
        aTimer.Interval=3000;
        // Test timer
        // aTimer.Enabled = true;
        
        var factory = new ConnectionFactory()        
        {
            HostName = "localhost", UserName="user", Password="password",
            // DispatchConsumersAsync = true        
        };
        var connection = factory.CreateConnection();
        
        // Add multiple consumers, so that queue can be processed "in 
        parallel"
        for (int i=1; i<10; i++)        
        {
            var j=i;
            var channel = connection.CreateModel();
            
            channel.ExchangeDeclare(exchange: "logs", type: 
                                    ExchangeType.Fanout);
            var queueName=channel.QueueDeclare("test1", durable: true, 
                            autoDelete: false, exclusive: false); 
            
            // take 1 message per consumer
            channel.BasicQos(0, 1, false);
            
            channel.QueueBind(queue: queueName,
                    exchange: "logs",
                    routingKey: "");
            Console.WriteLine($" [*] Waiting for messages in {j}");
            
            var consumer = new EventingBasicConsumer(channel);
            
            consumer. Received+= (model, ea) =>            
            {
                byte[] body = ea.Body.ToArray();
                var message = Encoding.UTF8.GetString(body);
                Console.WriteLine($" [x] Received in {j} -> {message} at 
                                                    {DateTime.Now}");
                
                // Thread.Sleep(dots * 1000);
                
                // await Task.Delay(3000);
                Thread.Sleep(10000); 
                // async works too
                
                if (j==5)                
                {
                    // Test special case of returning item to queue: in 
                    this case we received the message, but did not process 
                    it because of some reason.
                    // QOS is 1, so our consumer is already full. We need 
                    to return the message to the queue, so that another 
                    consumer can work with it
                    Console.WriteLine($"[-] CANT PROCESS {j} consumer! 
                                        Error with -> {message}"); 
                    channel.BasicNack(deliveryTag: ea.DeliveryTag, 
                                            multiple: false, true);                
                }
                else                
                {
                    Console.WriteLine($" [x] Done {j} -> {message} at 
                                        {DateTime.Now}");
                    
                    // here channel could also be accessed as 
                    ((EventingBasicConsumer)sender).Model
                    channel.BasicAck(deliveryTag: ea.DeliveryTag, 
                                                multiple: false);                
                }            
            };
            channel.BasicConsume(queue: queueName, autoAck: false, 
                                consumer: consumer);        
        }
        
        Console.WriteLine(" Press [enter] to exit.");
        Console.ReadLine();    
    }
}

full example in link 链接中的完整示例

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 如何在.Net中与不同类型的使用者一起使用RabbitMq消息? - How can I consume RabbitMq messages with different type of consumers in .Net? 有条件的处理和删除多个使用者从MSMQ队列中的消息 - Conditionally handle and remove messages by multiple consumers from a MSMQ queue MassTransit - 多个消费者都可以收到相同的消息吗? - MassTransit - Can Multiple Consumers All Receive Same Message? 如何使用 C# 从 RabbitMQ 中的队列接收单个消息 - How to receive single message from the queue in RabbitMQ using C# 是否可以使用 MassTransit 为 RabbitMQ 队列注册多个消费者? - Is it possible to register multiple consumers for a RabbitMQ queue using MassTransit? 如何使用MassTransit订阅多个消费者的一个队列? - How I can subscribe to one queue by multiple consumers using MassTransit? 如何使用 MassTransit 从 RabbitMQ DeadLetter 队列中检索消息? - How to retrieve messages from RabbitMQ DeadLetter queue using MassTransit? RabbitMQ-在微服务中使用队列中的消息 - RabbitMQ - Consuming messages from queue in microservices MassTransit/RabbitMq 错误队列 - 如何删除消息? - MassTransit/RabbitMq Error queue - how to delete messages? 频道:是否可以从单个生产者的多个消费者广播/接收相同的消息? - Channels: Is it possible to broadcast/receive same message by multiple consumers from single producer?
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM