Тайм-ауты WCF - это кошмар
У нас есть множество служб WCF, которые работают почти все время, используя различные привязки, порты, максимальные размеры и т. Д. В WCF очень расстраивает то, что когда он (редко) выходит из строя, мы бессильны выяснить, почему не удалось. Иногда вы получите сообщение, которое выглядит так:
System.ServiceModel.CommunicationException: соединение с сокетом было прервано. Это может быть вызвано ошибкой обработки вашего сообщения или превышением тайм-аута приема удаленным хостом, или проблемой основного сетевого ресурса. Тайм-аут локального сокета был "01:00:00". ---> System.IO.IOException: невозможно прочитать данные из транспортного соединения: существующее соединение было принудительно закрыто удаленным хостом.
Проблема в том, что тайм-аут локального сокета, который он вам дает, является просто попыткой быть удобной. Это может или не может быть причиной проблемы. Но хорошо, иногда у сетей есть проблемы. Ничего страшного. Мы можем повторить или что-то еще. Но вот огромная проблема. Вдобавок к невозможности сообщить вам, какой именно тайм-аут (если таковой имеется) привел к сбою ("превышен тайм-аут приема на стороне сервера" или что-то в этом роде), WCF, по-видимому, имеет два типа тайм-аутов.
Timeout Type #1) Тайм- аут, который, если его увеличить, увеличит вероятность успеха вашей операции. Таким образом, соответствующий тайм-аут составляет час, вы загружаете огромный файл, который займет час и двадцать минут. Это не удается. Вы увеличиваете время ожидания, это успешно. У меня нет проблем с этим типом тайм-аута.
Тип тайм-аута № 2) Тайм- аут, который просто определяет, как долго вы должны ждать, чтобы служба фактически перестала работать, и выдает ошибку, но изменение значения этого тайм-аута не влияет на вероятность успеха. По сути, что-то происходит в течение первой секунды запроса на обслуживание, что портит все. Это никогда не восстановится. WCF волшебным образом не повторяет для вас сетевое соединение. Хорошо, иногда установление сетевого соединения не проходит хорошо. Но, если ваш тайм-аут составляет 2 часа, вы должны подождать 2 часа без каких-либо шансов, что он когда-либо сработает, прежде чем он, наконец, признает, что он не работает, и выдает ошибку.
Но ошибка, которую вы видите в обоих случаях, выглядит одинаково. С типом тайм-аута №2 все равно выглядит, что у вас тайм-аут. Но вы могли бы увеличить все свои тайм-ауты до 4 лет, и все, что нужно было бы сделать, - это сделать 4 года, чтобы получить сообщение об ошибке. Я знаю, что Тип № 2 существует, потому что я могу выполнить операцию, которая, как известно, завершается менее чем за минуту, если она успешна, и для ее завершения требуется 2 часа. Но, если я убью его и попытаюсь повторить, это удастся быстро. (Если вам интересно, почему для операции, которая занимает менее минуты, может потребоваться 2 часа, иногда я запускаю операцию со значительно большим файлом, и это может занять более часа.)
Таким образом, для борьбы с проблемой типа 2 вы бы хотели, чтобы ваш тайм-аут был очень быстрым, чтобы вы сразу знали, есть ли проблема. Тогда вы можете повторить попытку. Но непреодолимая проблема заключается в том, что, поскольку я не знаю, какие таймауты являются причиной сбоя, я не знаю, какие тайм-ауты относятся к типу № 1, а какие к типу № 2. Может быть один тайм-аут (скажем, тайм-аут отправки на стороне клиента), который в некоторых случаях действует как Тип № 1, а в других - Тип № 2. Я понятия не имею, и у меня нет никакого способа узнать.
Кто-нибудь знает, как отследить тайм-ауты типа #2, чтобы я мог установить для них низкие значения, не сокращая фактические (читай: тип #1) тайм-ауты и снижая вероятность успеха?
Спасибо.
Разъяснение тайм-аутов типа 2 в ответ на комментарий Эндрю Андерсона:
Я считаю, что что-то идет не так между запросом клиента и кодом, который начинает выполняться на сервере. Во всех случаях, когда у нас есть серверный код, указывающий на частичный прогресс, некоторые операции не завершаются без завершения всего процесса. Таким образом, серверный код никогда не запускается, и то, сколько времени потребуется для его выполнения, не имеет значения (кроме того, что оно влияет на то, на что мы устанавливаем наши значения тайм-аута, в первую очередь, чтобы приспособить его).
4 ответа
Я всегда помещаю сообщение "сердцебиение" в мои давно работающие службы WCF. Затем вы можете установить для тайм-аутов типа 1 низкое значение (в 2-3 раза больше частоты сердцебиения), и тайм-ауты типа 2 станут очевидными.
Чтобы узнать, какой именно тайм-аут вызвал тайм-аут или другую ошибку, настройте и используйте трассировку.
У меня та же проблема, и она была связана с плохим оборудованием, и это было действительно трудно отладить, также с Wireshark (tcp sniffer) пакеты не показывали никаких особых ошибок, мы нашли некоторые tcp-повторы, и это это могло быть симптомом, но на самом деле пакеты просто застревали где-то внутри модем-маршрутизатора, который был телекоммуникационным модемом (pirelli gate 2 plus), после смены модема / маршрутизатора проблема полностью исчезла.
В любом случае мы выяснили, что wsHttpBinding через http более надежен для интернет-соединения, где у вас нет контроля, и вы не можете быть уверены в том, какое оборудование установлено на сайте.
Надеюсь, что это может помочь и кому-то еще:)
Убедитесь, что вы правильно обрабатываете исключения службы. Вы будете часто получать соединения, которые пропадают без причины, если исключения обрабатываются неправильно. Кроме того, если они это делают, и они обрабатываются правильно, вы обычно можете получить более полезную информацию:
https://msdn.microsoft.com/en-us/library/ms733721(v=vs.110).aspx
Кроме того, используйте "Heartbeat" или обычный метод ping, который вы можете вызвать из клиента. Я обнаружил, что клиентские маршрутизаторы имеют автоматический тайм-аут, встроенный в TCP-соединения, который он использует для завершения незанятых соединений. Без метода heartbeat клиентский маршрутизатор может преждевременно завершить соединение, на которое не влияют настройки службы WCF.