Подтвердить что ты не робот

Тайманы WCF - это кошмар

У нас есть куча сервисов WCF, которые работают почти все время, используя различные привязки, порты, максимальные размеры и т.д. Супер-разочаровывающая вещь о WCF заключается в том, что когда она (редко) терпит неудачу, мы бессильны найти почему он потерпел неудачу. Иногда вы получите сообщение, которое выглядит так:

System.ServiceModel.CommunicationException: Соединение сокета было прервано. Это может быть вызвано ошибкой обработки вашего сообщения или получения превышение тайм-аута с помощью пульта дистанционного управления хост или базовая сеть проблема с ресурсами. Локальный тайм-аут был '01: 00: 00 '. --- > System.IO.IOException: невозможно прочитать данные от транспортного соединения: существующее соединение было принудительно закрыт удаленным хостом.

Проблема в том, что локальный тайм-аут сокета, который он дает вам, - это просто попытка быть удобной. Это может быть или не быть причиной проблемы. Но хорошо, иногда сети имеют проблемы. Ничего страшного. Мы можем повторить или что-то еще. Но вот огромная проблема. Помимо того, что вы не указали, какой именно тайм-аут (если таковой имеется) привел к сбою ( "ваш тайм-аут приема на стороне сервера был превышен" или что-то еще, было бы полезно), WCF, похоже, имеет два типа тайм-аутов.

Timeout Type # 1) Тайм-аут, который, если увеличится, увеличит вероятность успеха вашей операции. Итак, соответствующий тайм-аут - час, вы загружаете огромный файл, который займет час и двадцать минут. Это не удается. Вы увеличиваете таймаут, он преуспевает. У меня нет никаких проблем с этим типом таймаута.

Timeout Type # 2) Тайм-аут, который просто определяет, сколько времени вам придется ждать, пока служба действительно не сработает, и вы получите сообщение об ошибке, но изменение значения этого таймаута не влияет на шанс успеха. В основном, что-то происходит в течение первой секунды запроса на обслуживание, которое заманивает вещи. Он никогда не восстановится. WCF не волшебным образом повторяет подключение к сети. Прекрасно, иногда установление сетевого соединения идет не так. Но если ваш тайм-аут составляет 2 часа, вы должны подождать 2 целых часа без каких-либо шансов на его работу, прежде чем он наконец признает, что он не работает и дает вам ошибку.

Но ошибка, которую вы видите в обоих случаях, выглядит одинаково. С таймаутом Type # 2 все еще выглядит так, как будто вы запускаете тайм-аут. Но вы можете увеличить все ваши таймауты до 4 лет, и все, что он сделал бы, - это сделать 4 года, чтобы получить сообщение об ошибке. Я знаю, что Type # 2 существует, потому что я могу выполнить операцию, которая, как известно, завершается менее чем за минуту, когда она удалась, и потребовалось 2 часа, чтобы сработаться. Но, если я убью его и повторю, он быстро завершается. (Если вам интересно, почему может потребоваться 2-часовой тайм-аут для операции, которая занимает меньше минуты, иногда я запускаю операцию с гораздо большим файлом, и это может занять более часа.)

Итак, чтобы бороться с проблемой с типом # 2, вы хотите, чтобы ваш тайм-аут был действительно быстрым, чтобы вы сразу узнали, есть ли проблема. Затем вы можете повторить попытку. Но непреодолимой проблемой является то, что, поскольку я не знаю, какие таймауты являются причиной сбоя, я не знаю, какие тайм-ауты являются Type # 1, а какие - Type # 2. Может быть один тайм-аут (скажем, тайм-аут отправки на стороне клиента), который действует как тип # 1 в некоторых случаях и тип # 2 в других. Я понятия не имею, и у меня нет способа узнать.

Кто-нибудь знает, как отслеживать таймауты Type # 2, чтобы я мог установить их на низкие значения без необходимости сокращать фактические (читай: Type # 1) таймауты и понижать вероятность успеха?

Спасибо.

Уточнение тайм-аутов типа № 2 в ответ на комментарий Эндрю Андерсона:

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

4b9b3361

Ответ 1

Я всегда добавляю сообщение "heartbeat" в своих давно работающих службах WCF. Затем вы можете установить таймауты Type # 1 на низкое значение (в 2-3 раза больше частоты звонка), а таймауты Type # 2 становятся очевидными.

Ответ 2

Чтобы узнать, какой конкретный тайм-аут вызвал тайм-аут или другую ошибку, настройте и используйте трассировку.

Ответ 3

У меня такая же проблема, и это было связано с плохой аппаратурой, и ее было очень сложно отлаживать, а также с wirehark (tcp sniffer), пакеты не отображали каких-либо конкретных ошибок, мы обнаружили некоторые tcp- повторные попытки, и это могло быть симптомом, но на самом деле пакеты просто застряли где-то внутри модема-маршрутизатора, который был модемом связи (pirelli gate 2 plus), после изменения модема/маршрутизатора проблема полностью исчезла.

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

Надеюсь, это поможет и кому-то другому:)

Ответ 4

Убедитесь, что вы правильно обрабатываете исключения служб. Вы часто получаете соединения, которые выпадают без причины, если исключения неправильно обрабатываются. Кроме того, если они это делают, и они обрабатываются правильно, вы можете получить дополнительную полезную информацию:

https://msdn.microsoft.com/en-us/library/ms733721(v=vs.110).aspx

Кроме того, используйте "Heartbeat" или обычный метод ping, который вы можете вызывать от клиента. Я обнаружил, что у маршрутизаторов клиентов есть автоматический тайм-аут, встроенный в TCP-соединения, которые он использует для завершения простоя соединений. Без метода heartbeat клиентский маршрутизатор может преждевременно прекратить соединение, на которое не будут влиять настройки службы WCF