#c# #rabbitmq #autofac #event-bus #asp.net5
#c# #кролик #автофак #автобус для мероприятий #asp.net5
Вопрос:
Я пытаюсь понять, почему в моем приложении возникают следующие проблемы
- после работы в течение часа или около того использование памяти превышает 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"); } }
Вышеприведенный обработчик срабатывает чаще, чем любой другой, и я считаю, что отчасти в этом заключается самая большая проблема, у меня есть следующие вопросы
- Должен ли обработчик (в данном случае) иметь общедоступную асинхронную задачу и возвращать что-то вроде _repository.UpdateAsync(контекст)?
- было бы разумно заменить _репозицию.UpdateAsync и _репозиционный.Добавить синхронизацию с командами посредника?
Я относительно новичок в Autofac/DI/RabbitMQ, поэтому буду признателен за любые советы
Комментарии:
1. Есть много вещей, которых я не понимаю в этой реализации. Почему вы используете Task. Yield и почему вы используете отражение для вызова дескриптора? Разве вы не должны быть в состоянии разрешить обработчик из вашего контейнера на основе типа
T
?2. Вам действительно нужно прикрепить профилировщик памяти к чему-то, чтобы выяснить, что содержит ссылки. Здесь определенно недостаточно, чтобы иметь возможность воспроизводить или устранять неполадки.