Как правильно распоряжаться клиентским потоком, если соединение отключено? - PullRequest
0 голосов
/ 24 октября 2018

Я использую Microsoft.AspNetCore.SignalR 2.1 v1.0.4, и поток ChannelReader используется клиентом машинописи с использованием v1.0.4.

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

Теперь у меня есть вопросы о том, как лучше всего отписаться от потока, а также в целом, каков срок службыпотока для клиента в сценариях остановки / запуска хаб-соединения, и если сервер явно прерывает соединение (из-за тайм-аутов access_token и, таким образом, для запуска клиента обновить свое соединение)?

Похоже, что некоторые состояния соединения не отображаются из API, поэтому в настоящее время я использую RxJs Subject для отображения некоторого состояния соединения с моими компонентами / сервисами пользовательского интерфейса, т. Е. Когда начальный вызов соединения концентратора успешен, я выхожу«истина», и когда обратный вызов onclose называется I, поверхность «ложь».Это позволяет мне пытаться вызвать dispose в ранее подписанном потоке, чтобы очистить вещи во время разъединения / остановки соединения, а затем при необходимости снова подписаться на поток при успешном начальном вызове.

Я попытался вызватьраспоряжаться потоком, что нормально, если подключен концентратор, но выдает ошибки, если соединение находится в отключенном состоянии.Мне интересно, если это ошибка или нет.Должен ли я иметь возможность распоряжаться потоком, даже если концентратор отключен?

Можно ли просто выполнить delete streamsubscription и затем воссоздать его по мере необходимости, или эта утечка будет каким-либо образом?

1 Ответ

0 голосов
/ 24 октября 2018

каково время жизни потока для клиента в сценариях остановки / запуска хаб-соединения, и если сервер явно прерывает соединение (из-за тайм-аутов access_token и, следовательно, из-за того, что клиент обновляет свое соединение).

Когда соединение разорвано (либо из-за того, что stop вызывается на клиенте или сервере, прерывающем соединение), метод error вашего подписчика будет вызван с ошибкой, указывающей, что поток имеетбыло прервано, потому что соединение было разорвано.В общем случае вы должны обработать метод error и считать его терминальным событием (т. Е. Поток никогда не даст дополнительных объектов).На сервере токен Context.ConnectionAborted будет запущен, если соединение разорвано (любой стороной), и вы можете прекратить запись в свой поток.

Если вы уже используете RxJS, я настоятельно рекомендуюсоздание небольшой оболочки для преобразования объекта, который вы возвращаете из SignalR, в правильный RxJS Observable.Объект, который мы возвращаем, не является на самом деле и Observable, но он имеет все те же основные методы (метод subscribe, который принимает объект с помощью методов complete, next и error), поэтому это должно быть тривиально, чтобы обернуть его.

Я попытался вызвать dispose в потоке, что нормально, если концентратор подключен, но он ошибается, если соединение находится в отключенном состоянии.Мне интересно, если это ошибка или нет.

Да, это, вероятно, ошибка.Мы не должны бросать, если вы утилизируете после отключения концентратора.Можете ли вы подать это на https://github.com/aspnet/SignalR?Чтобы обойти это, вы можете довольно безопасно просто try...catch сообщить об ошибке и устранить ее (или, может быть, зарегистрировать ее, если вы параноик).

Можно ли просто удалить подписку streams затем и заново создатьпо мере необходимости, или эта утечка будет каким-либо образом?

Вы должны всегда dispose подписку.Если вы просто delete это сделаете, мы не сможем узнать, что с вами покончено, и мы никогда не скажем серверу остановиться.Если вы звоните dispose (и подключены), мы отправляем сообщение на сервер, «отменяя» поток.В ASP.NET Core 2.1 мы не предоставляем эту отмену вам, но мы прекращаем чтение с ChannelReader.В ASP.NET Core 2.2 мы разрешаем вам принять CancellationToken в вашем методе Hub, а метод dispose на клиенте вызовет этот токен в методе Hub.Я настоятельно рекомендую вам попробовать последний предварительный просмотр ASP.NET Core 2.2 и использовать CancellationToken в методе Hub для остановки потока:

public ChannelReader<object> MyStreamingMethod(..., CancellationToken cancellationToken) {
    // pass 'cancellationToken' over to whatever process is writing to the channel
    // and stop writing when the token is triggered
}

Примечание. Если вы сделаете это, вы неДля отслеживания Context.ConnectionAborted токен, передаваемый в ваш метод Hub, будет охватывать все случаи отмены.

В связанной заметке вы должны всегда использовать Channel.CreateBounded<T>(size) для создания своего канала,Если вы используете неограниченный канал, утечка памяти будет намного проще, так как писатель может продолжать писать бесконечно.Если вы используете ограниченный канал, устройство записи будет остановлено (WriteAsync и WaitToWriteAsync заблокируют), если в канале будет size непрочитанных элементов (потому что, например, клиент отключился и мыперестал читать).

...