C#RabbitMQ - EventingBasicConsumer.Received OutOfMemory

时间:2017-08-08 08:34:48

标签: c# rabbitmq

我想要一个有许多消费者收听新消息并处理它们的场景。当消息不为空时,消费者应该始终监听和处理消息。这是我写的代码:

        string msg = null;

        try
        {
            using (var connection = factory.CreateConnection())
            using (var channel = connection.CreateModel())
            {

                queueMessage = queue.getQueue("myQueue");
                channel.BasicQos(prefetchSize: 0, prefetchCount: 1, global: false);
                consumer = new EventingBasicConsumer(channel);
                channel.BasicConsume(queue: "myQueue", noAck: false, consumer: consumer);

                while (true)
                {


                    consumer.Received += (model, ea) =>
                    {
                        var body = ea.Body;
                        msg = Encoding.UTF8.GetString(body);
                        if (msg != null)
                        {
                            executeTask(msg);
                        }
                        channel.BasicAck(deliveryTag: ea.DeliveryTag, multiple: false);

                    };
                    channel.Dispose();
                    connection.Dispose();
                    consumer.Model.Dispose();
                }//while(true)
            }
        }
        catch (Exception e)
        { 
         e.printStackTrace();
        }

一段时间后,抛出OutOfMemoryException,很可能是因为没有“flush”机制且Received属性变满。一个粗略的解决方案可能是在while(true)中实例化连接,通道和消费者:

        while (true)
        {
        using (var connection = factory.CreateConnection())
            using (var channel = connection.CreateModel())
            {

                queueMessage = queue.getQueue("myQueue");
                channel.BasicQos(prefetchSize: 0, prefetchCount: 1, global: false);
                consumer = new EventingBasicConsumer(channel);
                channel.BasicConsume(queue: "myQueue", noAck: false, consumer: consumer);
                consumer.Received += (model, ea) =>
                {
                ...

我完全不相信这是一个很好的解决方案,因为多个线程不断打开和关闭。可能是处理这种行为的另一类,还是我错过了什么?

1 个答案:

答案 0 :(得分:0)

首先,应在一个对象中创建整个工厂连接和客户端,在您的服务/程序的生命周期继续进行时,您将始终对其进行引用,以使它们不会被GC。尤其不要将它们放在using([])中。想要多个客户? ->单独的线程和实例 其次,您不需要使用``while''和频道重新创建功能,因为一旦您向使用者注册了一些工作即可。接收并随后初始化频道.BasicConsume,工作调用将保存在内存中并在每个入站调用给消费者的信息