Проблемы с медленной обработкой событий и использованием памяти с RabbitMQ и AutoFac

#c# #rabbitmq #autofac #event-bus #asp.net5

#c# #кролик #автофак #автобус для мероприятий #asp.net5

Вопрос:

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

  1. после работы в течение часа или около того использование памяти превышает 2 ГБ
  2. после работы в течение часа или около того обработка событий замедляется с ~100 м/с до ~6-10 м/с

Я использую Dotnet 5 с Autofac. Вот метод, который запускается событием Consumer_Received

 private async Task ProcessEvent(string eventName, string message) {  if (_subsManager.HasSubscriptionsForEvent(eventName))  {  await using var scope = _autofac.BeginLifetimeScope(AUTOFAC_SCOPE_NAME);  var subscriptions = _subsManager.GetHandlersForEvent(eventName);  foreach (var subscription in subscriptions)  {  var handler = scope.ResolveOptional(subscription.HandlerType);  if (handler == null) continue;  var eventType = _subsManager.GetEventTypeByName(eventName);  var integrationEvent = JsonConvert.DeserializeObject(message, eventType);  var concreteType = typeof(IIntegrationEventHandlerlt;gt;).MakeGenericType(eventType);   await Task.Yield();  await ((Task) concreteType.GetMethod("Handle")?  .Invoke(handler, new[] {integrationEvent}))  .ConfigureAwait(false);    }  } }  

Это событие

 public class MPTEvent {  public string M {get;set;}  public string Number {get;set;}  public string Type {get;set;}  public bool T {get;set;}  public bool A {get;set;}  public bool LB {get;set;} }  

Описанный выше метод запускается для КАЖДОГО события, хранящегося в очереди. у меня есть несколько обработчиков «инотификации», которые обрабатывают события (т. Е. Ручка), вот пример одного (отредактирован для краткости)

 public async Task Handle(MPTEvent tEvent) {  try  {  // try to get the tag and device  var contextD = await _repository.GetByNumber(tEvent.M);  if (contextD == null)  {  _logger.LogError("Detailed Error Message");  return;  }    var contextT = await _repository.GetByNumber(tEvent.Number);  if (contextT == null)  {  _logger.LogWarning("Detailed Warning Message");  return;  }   if (tEvent.T == 1 amp;amp; tEvent.A == 0 amp;amp; tEvent.LB == 0)  {  contextT?.TriggerTEvent(contextD, tEvent.R, tEvent.CreatedDate);  }   await _repository.UpdateAsync(contextT);  }  catch (Exception ex)  {  _logger.LogCritical(ex, "Detailed Exception Message");  } }  

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

  1. Должен ли обработчик (в данном случае) иметь общедоступную асинхронную задачу и возвращать что-то вроде _repository.UpdateAsync(контекст)?
  2. было бы разумно заменить _репозицию.UpdateAsync и _репозиционный.Добавить синхронизацию с командами посредника?

Я относительно новичок в Autofac/DI/RabbitMQ, поэтому буду признателен за любые советы

Комментарии:

1. Есть много вещей, которых я не понимаю в этой реализации. Почему вы используете Task. Yield и почему вы используете отражение для вызова дескриптора? Разве вы не должны быть в состоянии разрешить обработчик из вашего контейнера на основе типа T ?

2. Вам действительно нужно прикрепить профилировщик памяти к чему-то, чтобы выяснить, что содержит ссылки. Здесь определенно недостаточно, чтобы иметь возможность воспроизводить или устранять неполадки.