2013-10-15 3 views
2

Я видел очень странное поведение в моем обработчике ребуса, который сам размещен в exe. Сразу после отправки ответа с использованием метода bus.send он добавляет некоторую память, потребляемую процессом. Я попытался найти граф объектов с использованием профиля памяти и обнаружил, что ребус где-то размещает ответное сообщение в сериализованном формате. График объектов показывал ниже иерархию корня.
System.Message -> CachedBodyMessage -> streamУтечка памяти при отправке ответа от обработчика ребуса

Дайте мне несколько указателей, если кто-нибудь знает об этой вещи.

ответ

0

Я понимаю, что утечка памяти является серьезной проблемой, но я убежден, что маловероятно, что Rebus должен содержать утечку памяти.

Это убеждение коренится в том, что я работаю на конечных точках конечной точки Windows, обслуживаемых Windows Service в течение 1,5 лет, а некоторые из них (например, менеджеры тайм-аута) иногда работают в течение нескольких месяцев, не будучи перезапущен.

Я хотел бы быть абсолютно пуленепробиваемым, хотя, поэтому я готов исследовать проблему, о которой вы сообщаете.

Вы упоминаете «CachedBodyMessage» - судя по именам полей внутри System.Messaging.Message, похоже, что это что-то в MSMQ. Для того, чтобы попытаться воспроизвести проблему, я закодирован следующий тест:

[Test, Ignore("Only works in RELEASE mode because otherwise object references are held on to for the duration of the method")] 
public void DoesNotLeakMessages() 
{ 
    // arrange 
    const string inputQueueName = "test.leak.input"; 
    var queue = new MsmqMessageQueue(inputQueueName); 
    disposables.Add(queue); 

    var body = Encoding.UTF8.GetBytes(new string('*', 32768)); 
    var message = new TransportMessageToSend 
        { 
         Headers = new Dictionary<string, object> { { Headers.MessageId, "msg-1" } }, 
         Body = body 
        }; 

    var weakMessageRef = new WeakReference(message); 
    var weakBodyRef = new WeakReference(body); 


    // act 
    queue.Send(inputQueueName, message, new NoTransaction()); 
    message = null; 
    body = null; 

    GC.Collect(); 
    GC.WaitForPendingFinalizers(); 

    // assert 
    Assert.That(weakMessageRef.IsAlive, Is.False, "Expected the message to have been collected"); 
    Assert.That(weakBodyRef.IsAlive, Is.False, "Expected the body bytes to have been collected"); 
} 

, который проверяет, что отправленное транспортное сообщение собирается, как он должен (будет делать это только в режиме RELEASE, хотя, из-за режимом DEBUG пути держит на на объектные ссылки в пределах области)

Я попробую запустить образец TimePrinter и оставлю его работать некоторое время, чтобы увидеть, могу ли я воспроизвести проблему. Если вы наткнетесь на дополнительную информацию о, например, точно, какие объекты протекают, это было бы очень полезно.

Еще раз спасибо, что нашли время, чтобы сообщить свои заботы мне :)

Followup:

Я изменил образец TimePrinter так, что он посылает 50 Msg/с и включает в себя 64 KB случайную загрузку строки с каждым сообщением, и я отслеживал использование памяти почти четыре часа. Как вы можете видеть, это не похоже на утечку памяти.

Perfmon memory trace

Я оставлю это бегущий остальную часть дня, просто чтобы быть уверенным.

Возможно, вы еще можете рассказать мне, почему вы подозревали, что в первую очередь возникла утечка памяти?

Update:

Как вы можете видеть из следа, он теперь работает в течение 7 часов, и таким образом более 1200000 сообщений, содержащих более 70 ГБ данных было отправлено и потребляются тем же способом, , Если кэшированные тела сообщений течет, я уверен, что мы смогли бы увидеть что-то, растущее на графике.

Perfmon memory trace 2

Смежные вопросы