阅读开始之前发送的消息?

时间:2019-05-17 06:22:12

标签: c# rabbitmq

Erlang RMQ服务器不停止运行

假设我有一个RMQ接收器和RMQ发送器,它们从一开始就发送消息。

当我启动它们时:首先是收件人,然后是发件人,则发送消息,然后服务器将其提取。

但是,当我首先启动发件人,然后在它发送其消息之后,立即启动接收者,接收者看不到该消息。

我的问题是RMQ是否能够在第二种情况下处理(读取)消息,如果可以,需要哪些选项?交换已经很持久了,但是没有帮助。

2 个答案:

答案 0 :(得分:2)

,RabbitMQ能够保留这些消息,直到您的消费者可以使用为止。只需何时声明队列以及队列配置即可。

简而言之;如果您在发布消息之前 声明并绑定了队列,则无论是否有使用者,消息都将保留在该队列中。

explained in the documentation一样,某些参数在声明队列时会影响此行为:

  • exclusive(如果为true)将在使用者断开连接时删除队列(和消息)。
  • durable(如果为true),即使RabbitMQ重新启动也将保留消息。

当使用者在启动时创建并建立自己的队列时,情况与您所描述的完全相同;如果使用者从未运行过,则消息“丢失”。

这是一种常见的做法,您可以通过教程进行验证,尤其是在a pub-sub scenario (see tutorial #3)中,发布商不了解消费者或他们需要什么队列。

如果您真的想确保收到所有消息,则需要采取一些预先声明队列的方法。

答案 1 :(得分:1)

简单的制作人

    // producer
    static void Main( string[] args )
    {
        var factory = new ConnectionFactory() 
        { 
            HostName = "localhost"                
        };
        using ( var connection = factory.CreateConnection() )
        {
            using ( var channel = connection.CreateModel() )
            {
                channel.QueueDeclare( "hello", true, false, false, null );

                string message = "Hello World!";
                var body = Encoding.UTF8.GetBytes( message );

                while ( true )
                {
                    Console.WriteLine( "Press key to send message" );
                    Console.ReadLine();

                    channel.BasicPublish( "", "hello", null, body );

                    Console.WriteLine( " [x] Sent {0}", message );
                }
            }
        }

我运行了此消息,发布了几则消息,然后在RMQ的队列中看到了所有消息。

然后我运行这个简单的消费者

    // consumer
    static void Main( string[] args )
    {
        var factory = new ConnectionFactory() { HostName = "localhost" };
        using (var connection = factory.CreateConnection())
        {
            using (var channel = connection.CreateModel())
            {
                channel.QueueDeclare("hello", true, false, false, null);

                var consumer = new QueueingBasicConsumer(channel);
                channel.BasicConsume("hello", true, consumer);

                Console.WriteLine(" [*] Waiting for messages." +
                                         "To exit press CTRL+C");
                while (true)
                {
                    var ea = (BasicDeliverEventArgs)consumer.Queue.Dequeue();

                    var body    = ea.Body;
                    var message = Encoding.UTF8.GetString(body);
                    Console.WriteLine(" [x] Received {0}", message);
                }
            }
        }
    }

即使在生产者完成后运行,我仍然可以在消费者中得到消息。

请验证这与您的设置有何不同。

编辑:如果生产者中有交换支持队列,这也将起作用:

    // producer
    static void Main( string[] args )
    {
        var factory = new ConnectionFactory() 
        { 
            HostName = "localhost"                
        };
        using ( var connection = factory.CreateConnection() )
        {
            using ( var channel = connection.CreateModel() )
            {
                channel.QueueDeclare( "hello", true, false, false, null );
                channel.ExchangeDeclare( "helloe", "fanout", true );
                channel.QueueBind( "hello", "helloe", "" );

                string message = "Hello World!";
                var body = Encoding.UTF8.GetBytes( message );

                while ( true )
                {
                    Console.WriteLine( "Press key to send message" );
                    Console.ReadLine();

                    channel.BasicPublish( "helloe", "", null, body );

                    Console.WriteLine( " [x] Sent {0}", message );
                }
            }
        }

        Console.WriteLine( "finished" );
        Console.ReadLine();
    }

(无需更改消费者)

编辑2 :这在使用事件使用者时也适用:

    static void Main( string[] args )
    {
        var factory = new ConnectionFactory() { HostName = "localhost" };
        using (var connection = factory.CreateConnection())
        {
            using (var channel = connection.CreateModel())
            {
                channel.QueueDeclare("hello", true, false, false, null);

                var consumer = new EventingBasicConsumer(channel);
                consumer.Received += (s, e) =>
                {
                    var message = Encoding.UTF8.GetString(e.Body);
                    Console.WriteLine(" [x] Received {0}", message);
                };
                channel.BasicConsume("hello", true, consumer);

                Console.WriteLine(" [*] Waiting for messages." +
                                         "To exit press CTRL+C");

                Console.ReadLine();
            }
        }
    }