Проблема утечки памяти: как избавиться от подключения к концентратору SignalR и когда создавать новое подключение

2

У меня есть два связанных вопроса, касающихся соединений с концентратором SignalR, но прежде чем я получу их, я просто расскажу о том, что я делаю.

контекст

У меня есть приложение, которое отправляет уведомления с сервера клиенту интерфейса (Javascript) с помощью SignalR. Тем не менее, есть и клиент back-end (.NET), который создает прокси-сервер для концентратора. Клиент back-end обрабатывает уведомления и отправляет их в концентратор, а концентратор отправляет эти уведомления клиенту переднего конца.

Чтобы быть более конкретным, у меня есть класс обработки уведомлений, позвольте ему назвать NotificationProcessor.cs. Каждый раз, когда создается новое уведомление, экземпляр NotificationProcessor создается. Когда экземпляр NotificationProcessor создается, устанавливается прокси-соединение с концентратором. У меня есть класс, HubProxyService.cs, который создает HubConnection объект и IHubProxy объект от этого. Его фрагмент выглядит следующим образом:

this.HubConnection = new HubConnection(serverUrl);
this.HubProxy = HubConnection.CreateHubProxy(hubName);
Task t = Task.Run(() => this.HubConnection.Start(new LongPollingTransport()));
t.WaitAndUnwrap();

Затем NotificationProcessor использует объект IHubProxy для вызова методов в концентраторе.

Я обнаружил, что создание объекта HubConnection каждый раз, когда NotificationProcessor HubConnection а не HubConnection когда это происходит, вызывает утечку памяти.

Вопросы

(1) Чтобы избежать утечки памяти, мне нужно как-то избавиться от HubConnection. Я читал, что могу сделать

Task.Run(() => this.HubConnection.Stop())

Проблема в том, что я не знаю, в какой момент я могу это назвать. Поскольку вызов метода хаба с прокси-сервером является асинхронным, могу ли я просто вызвать его сразу после вызова метода хаба? Или это вызовет проблемы в случае задержки отправки уведомления от концентратора переднему клиенту?

Я полагаю, что другой вариант заключается в том, чтобы обернуть инициализацию HubConnection в оператор using, например

using (HubConnection connection = new HubConnection(serverUrl))
{

}

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

Есть ли тот, который лучше другого? Последнее кажется более идиоматичным, в то время как первое является более явным и может работать лучше.

(2) HubConnection идея создать HubConnection для каждого созданного экземпляра NotificationProcessor? Есть ли способ сохранить эту связь (т.е. Сделать ее статической или что-то подобное)? У меня есть шаткое понимание жизни объектов и побочных эффектов, особенно потому, что это приложение развертывается в облаке, и я не знаю, что это значит, что один экземпляр HubConnection будет использоваться более одного раза. Разделяется ли он между потоками? Между узлами (я использую объединительную плату Redis)? Между пользователями? Имеет смысл держать соединение открытым, если дорого его поддерживать, когда оно нужно отправлять, но я просто не понимаю, как он работает, когда он развертывается в облаке на нескольких узлах. Мне просто кажется, что каждый раз нужно продолжать новую связь.

Теги:
memory-leaks
signalr
signalr-hub

1 ответ

3

Этот вопрос был опубликован некоторое время назад, но, не заметив ответа, я подумал, что буду звонить.

Учитывая то, что вы описали, я лично рекомендовал, чтобы статический экземпляр HubConnection был повторно использован для каждого процессора с новым HubProxy для каждого процессора. Просто убедитесь, что IHubProxy можно правильно утилизировать, когда процессор расположен.

Каждое соединение будет рассматриваться как отдельный клиент для концентратора SignalR, поэтому, если вам нужны отдельные уведомления или клиенты внутри одного и того же процесса, вам понадобятся отдельные подключения, но в вашем случае кажется, что все эти уведомления происходят от одного и того же клиента,

Слово предостережения

Обязательно ознакомьтесь с безопасностью потока HubConnection.

Безопасность резьбы

Любые публичные статические (Shared in Visual Basic) члены этого типа являются потокобезопасными. Любые члены экземпляра не гарантируют безопасность потоков.

Ещё вопросы

Сообщество Overcoder
Наверх
Меню