有一个发送消息的程序,发送10条消息到指定的消息队列里面。
另外写了一个处理消息的客户端,专门接收该队列中的消息。
问题:当我先启动发送程序,将消息发送到队列里面去,然后再同时启动两个客户端来接收的时候,无论如何他都只能够在最先启动的客户端里面能接收到消息,另外一个后启动的客户端无法接收到消息。但是如果当我先启动两个客户端,然后在启动发送程序的时候,这个时候消息会分发到两个客户端。
简单一点说就是,如果先发送消息,那么消息无法分发到多个处理端,如果是先启动处理端,在发送消息,则一切正常。
不知道是我的程序代码写的有问题,还是本身是这样。
发送 接收代码如下。
/// <summary> /// 主动获取消息 /// </summary> public static void Pull(Action<string> method, string ExchangeName, string QueueName="",string RoutingKey="", RabbitMQExchangeType type = RabbitMQExchangeType.direct) { using (var connection = CreateConnection()) { using (var channel = connection.CreateModel()) { channel.QueueDeclare(QueueName, durable: true, exclusive: false, autoDelete: false, arguments: null); channel.ExchangeDeclare(ExchangeName, type.ToString()); //channel.BasicQos(0, 1, false);//这样告诉RabbitMQ不要在同一时间给一个消费者超过一条消息。换句话说,只有在消费者空闲的时候会发送下一条信息。 //创建一个非持久的、唯一的且自动删除的队列 //String queueName = channel.QueueDeclare().QueueName; if (string.IsNullOrEmpty(QueueName)) { QueueName = channel.QueueDeclare().QueueName; ; } //为转发器指定队列,设置binding channel.QueueBind(QueueName, ExchangeName, RoutingKey); QueueingBasicConsumer consumer = new QueueingBasicConsumer(channel); //指定接收者,第二个参数为自动应答,无需手动应答 channel.BasicConsume(QueueName, true, consumer); while (true) { try { var delivery = consumer.Queue.Dequeue(); String message = (Encoding.UTF8.GetString(delivery.Body)); method(message); } catch (Exception ex) { throw ex; } } } } }
/// <summary> /// 发送消息 /// </summary> public static void Push(List<string> messages, string ExchangeName, string QueueName="", string RoutingKey = "", RabbitMQExchangeType type = RabbitMQExchangeType.direct) { // 创建连接和频道 var connection = CreateConnection(); var channel = connection.CreateModel(); //声明转发器和类型 channel.ExchangeDeclare(ExchangeName, type.ToString()); channel.QueueDeclare(QueueName, durable: true, exclusive: false, autoDelete: false, arguments: null); var props = channel.CreateBasicProperties(); props.DeliveryMode = 2; foreach (var msg in messages) { var msgBody = Encoding.UTF8.GetBytes(msg); channel.BasicPublish(ExchangeName, RoutingKey, props, body: msgBody); } channel.Dispose(); connection.Dispose(); }
channel.BasicQos(0, 1, false);
注释去掉
还有你的消息消费端任务好像没有时间消耗,当一个客户端连接进来的时候,马上把所有的任务都处理完了,这时候第二个连接还没有进来,看到的现象就好像是只有一个队列把所有的消息的消费了,你可以在
method(message);
中加入Thread.Slee(500) 模拟一下耗时任务处理
应该就可以看到正常的轮询处理了。
我消费端的程序以及进行了耗时处理。500毫秒
@yzy:好像是有这个问题,当队列中有消息且没有客户端连接的时候,会把当前队列中已有的消息优先绑定到第一个连接的客户端中,之后再进来的消息才会进行轮询,估计跟RabbitMQ的轮询机制有关。
所以推荐用easyq客户端.用过都说好.