C# 正在阅读启动前发送的消息?
Erlang RMQ服务器不间断地运行 假设我有一个RMQ接收器和RMQ发送器,它从一开始就发送消息 当我启动它们时:接收者第一,发送者第二,消息被发送,服务器接收它 但当我首先启动发送方,在它发送消息之后,我启动接收方,接收方并没有看到那个消息 我的问题是RMQ是否能够处理(读取)第二种情况下的消息,如果是,需要哪些选项?交换已经是持久的,但它没有帮助。简单的生产者C# 正在阅读启动前发送的消息?,c#,rabbitmq,C#,Rabbitmq,Erlang RMQ服务器不间断地运行 假设我有一个RMQ接收器和RMQ发送器,它从一开始就发送消息 当我启动它们时:接收者第一,发送者第二,消息被发送,服务器接收它 但当我首先启动发送方,在它发送消息之后,我启动接收方,接收方并没有看到那个消息 我的问题是RMQ是否能够处理(读取)第二种情况下的消息,如果是,需要哪些选项?交换已经是持久的,但它没有帮助。简单的生产者 // producer static void Main( string[] args ) {
// 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);
}
}
}
}
我在消费者中得到了我的信息,即使它是在生产者完成后运行的
请验证这与您的设置有何不同
编辑:如果生产者中有支持队列的exchange,此操作也有效:
// 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();
}
}
}
是,RabbitMQ能够保留这些消息,直到您的消费者可用为止。这只是您何时声明队列和队列配置的问题 简言之;如果在发布消息之前声明并绑定队列,则消息将保留在该队列中,而不管是否有使用者 例如,在声明队列时,某些参数会影响此行为:
,如果为true,将在使用者断开连接时删除队列(和消息)exclusive
,如果为true,则即使RabbitMQ重新启动,也会保留消息持久性
如果您确实想确保所有消息都已收到,则需要一些事先声明队列的方法。如果客户机先启动并尝试发送消息,但没有服务器侦听TCP 5672,那么客户机将如何成功传递消息?从客户机的角度来看,没有通信的另一端——服务器可以在一秒钟、一分钟、一年内启动,甚至永远不会启动。如果我理解正确,客户端将必须维护自己的未送达邮件日志,当服务器启动时,客户端应首先发送未送达的邮件,然后才发送连续的邮件。@WiktorZychla,啊,对不起,选择我的文字是不幸的,在最初的问题中我使用了名称“服务器/客户端”在我的程序中这些部分的角色。我改变了问题,改为使用“receiver/sender”,另一方面,RMQ(Erlang服务器)的核心/引擎不间断运行,这就是我知道消息正确发送的原因。再一次为困惑感到抱歉。另一方面,这似乎很容易,而且对我来说总是有效的。我甚至有一个简单的例子,我运行生产者,发布消息,我看到消息在队列中等待,我关闭生产者。我运行consumer,它会使用队列中的所有消息。@WiktorZychla,好吧,好消息,它应该可以工作了。您还记得此场景中的任何特定选项吗?将发布一个简短的答案供您验证。很好,我看到了第一个区别,您不声明交换,另一方面,我声明为持久交换,但不是队列。测试时间!:-)非常感谢。当我有一个交易所支持队列时,这也起作用。事实上,我已经去掉了我原来的例子。编辑了我的答案。到目前为止,唯一的区别是使用
QueueingBasicConsumer
vsEventingBasicConsumer
,在后一种情况下,初始消息(在消费者启动之前发送)丢失。仍在调查…@astrowalker:有趣的是,当我切换到EventingBasicConsumer
时,这似乎仍然有效。非常感谢你的帮助,这一次是我愚蠢的改变顺序,我写了消费然后订阅:-(再次感谢你,谜团解决了,现在一切都在我这边工作了。