首页 新闻 会员 周边

关于RabbitMq direct类型发送消息的时候的疑问。

0
[待解决问题]

有一个发送消息的程序,发送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();  

        }
yzy的主页 yzy | 菜鸟二级 | 园豆:317
提问于:2016-06-24 17:55
< >
分享
所有回答(2)
0

channel.BasicQos(0, 1, false);

注释去掉

还有你的消息消费端任务好像没有时间消耗,当一个客户端连接进来的时候,马上把所有的任务都处理完了,这时候第二个连接还没有进来,看到的现象就好像是只有一个队列把所有的消息的消费了,你可以在

 method(message);

中加入Thread.Slee(500) 模拟一下耗时任务处理

应该就可以看到正常的轮询处理了。

GrayGuo | 园豆:202 (菜鸟二级) | 2016-06-24 18:05

我消费端的程序以及进行了耗时处理。500毫秒

支持(0) 反对(0) yzy | 园豆:317 (菜鸟二级) | 2016-06-27 10:28

@yzy:好像是有这个问题,当队列中有消息且没有客户端连接的时候,会把当前队列中已有的消息优先绑定到第一个连接的客户端中,之后再进来的消息才会进行轮询,估计跟RabbitMQ的轮询机制有关。

支持(0) 反对(0) GrayGuo | 园豆:202 (菜鸟二级) | 2016-06-29 16:43
0

所以推荐用easyq客户端.用过都说好.

 

吴瑞祥 | 园豆:29449 (高人七级) | 2016-06-25 05:18
清除回答草稿
   您需要登录以后才能回答,未注册用户请先注册