Как мне автоматически восстановить дуплексный канал в случае неисправности?

Я разрабатываю клиент-серверное приложение в .Net 3.5 с использованием WCF. По сути, долго работающая клиентская служба (на нескольких машинах) устанавливает дуплексное соединение с сервером через netTcpBinding. Затем сервер использует контракт обратного вызова клиента для выполнения определенных операций по требованию, на которые клиент отвечает асинхронно (я думаю, довольно стандартная вещь). Я создаю подкласс класса DuplexClientBase для обработки большей части взаимодействия.

К сожалению, когда что-то идет не так на обоих концах (например, сбой сети, неожиданное исключение и т. Д.), Канал становится неисправным / прерывается, и все последующие операции терпят неудачу. Я обошел это ограничение в недуплексных каналах, создав класс RecoveringClientBase, который автоматически выбирает, когда клиент дает сбой, и повторяет операцию.

Итак, мой вопрос: существует ли установленный способ определения неисправности дуплексного канала? Где это проверить, на сервере или на клиенте? В противном случае, какие варианты у меня есть, чтобы убедиться, что соединение будет восстановлено?

Обновление. Мне нужен совет, касающийся дуплексных каналов, когда сервер может попытаться использовать канал обратного вызова, в котором произошел сбой. Таким образом, мне нужно что-то, что будет немедленно переподключаться / повторно подписываться, когда что-то случится с каналом. В настоящий момент я слушаю событие закрытия канала и воссоздаю его, если состояние не закрыто. Вроде работает, но кажется хакерским ...


person Jacob    schedule 15.10.2008    source источник


Ответы (4)


Я испытывал слабость во время длительных тренировок (минуты-часы). Я не могу быть уверен, что это WCF, я почти уверен, что это сетевой уровень.

Думаю вообще отказаться от дуплекса. Попытка управлять состоянием соединения - настоящая неприятность.

Я думаю о размещении конечной точки службы на клиенте для операций, которые в настоящее время являются частью контракта обратного вызова. Клиент свяжется с сервером и сообщит сведения о конечной точке, сервер может хранить их где-нибудь (постоянно или где-то еще). Когда серверу необходимо связаться с клиентом, он открывает соединение с клиентом через сохраненные сведения о конечной точке. По сути, превращение дуплексного соединения в 2 соединения клиент-сервер.

Не отвечает на ваш вопрос, но я чувствую вашу боль.

person Jimmy McNulty    schedule 09.01.2009
comment
я полагаю, этот метод нельзя использовать для клиентов за NAT - person Sam Sch; 15.06.2018

У Николаса Аллена из команды WCF есть предложения по этому поводу:

http://blogs.msdn.com/drnick/archive/2007/11/05/custom-transport-retry-logic.aspx

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

person jezell    schedule 15.10.2008
comment
Можете ли вы привести пример этого? Статья просто предлагает идею, но не дает никаких подсказок относительно ее реализации. - person Jacob; 16.10.2008
comment
+1 Джейкоб. У кого-нибудь есть информация о том, как заставить это работать? В настоящее время мне пришлось прибегнуть к использованию динамического прокси-сервера Castle для реализации моего поведения при повторном подключении, но я бы предпочел добавить это поведение через Wcf. Я читаю различные блоги Wcf, но это непонятно, и я понятия не имею, с чего начать - кажется, даже простые расширения требуют создания множества классов и множества конфигураций - это сбивает с толку. - person Mark Simpson; 14.09.2010
comment
Добавьте обработчик событий к событию Faailed через явный интерфейс ICommunicationObject в своей службе. В обработчике событий Abort () канал и создайте новый канал. - person Jakub Keller; 04.08.2014

У меня были похожие проблемы, и мне кажется, что эти длительные вызовы более или менее не поддерживаются.

Кажется, что WCF предназначен для использования для коротких вызовов. Службы, которые вызываются, делают некоторые мелочи, и все готово.

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

person Sam    schedule 07.01.2009

Я думаю, вам действительно стоит прислушиваться к ошибочному событию. Вы можете слушать его на обоих концах, на стороне клиента, я думаю, вы уже обрабатываете, на стороне сервера OperationContext.Current.Channel.events.

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

В конечном итоге клиенты получат отказ, и им следует повторить рукопожатие с сервером, то есть точечный сервер должен отправлять неотправленные вызовы.

По сути, единственный способ восстановить неисправный / закрытый канал - это заменить его новым, однако наиболее важной частью является то, что вы действительно должны обнаруживать отключение ВРЕМЯ, я обнаружил, что включение надежного сеанса вызовет сбойное событие вовремя большую часть кейс. В качестве альтернативы вы можете отправлять контрольные сообщения на обоих концах для «проверки» неисправного канала.

person Yuan    schedule 18.01.2011