Erlang RMQ服务器不停止运行。
假设我有一个RMQ接收器和RMQ发送器,它们从一开始就发送消息。
当我启动它们时:首先是收件人,然后是发件人,则发送消息,然后服务器将其提取。
但是,当我首先启动发件人,然后在它发送其消息之后,立即启动接收者,接收者看不到该消息。
我的问题是RMQ是否能够在第二种情况下处理(读取)消息,如果可以,需要哪些选项?交换已经很持久了,但是没有帮助。
答案 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();
}
}
}