Клиент WCF игнорирует значения тайм-аута при отключении службы

У меня есть приложение VB.NET, которое использует WCF. Я установил время ожидания для всего кода в коде:

    Dim oMastSrv As MastSvc.IclsIOXferClient = Nothing

    Dim binding As New ServiceModel.NetTcpBinding("NetTcpBinding_IclsIOXfer")
    Dim intTimeout As Integer = 2500
    binding.SendTimeout = New TimeSpan(0, 0, 0, 0, intTimeout)
    binding.ReceiveTimeout = New TimeSpan(0, 0, 0, 0, intTimeout)
    binding.OpenTimeout = New TimeSpan(0, 0, 0, 0, intTimeout)
    binding.CloseTimeout = New TimeSpan(0, 0, 0, 0, intTimeout)
    Dim address As New ServiceModel.EndpointAddress("net.tcp://" & GetSrvIP(intSrvID) & ":30000/MyMastSvc")

    oMastSrv = New MastSvc.IclsIOXferClient(binding, address)
    Try
        oMastSrv.ServiceConnect( ... )
        oMastSrv.InnerChannel.OperationTimeout = New TimeSpan(0, 0, 0, 0, intTimeout)
    Catch ex As Exception
        ...
    End Try

Когда служба, к которой я подключена к сбоям, исключение Endpoint Not Found занимает более 20 секунд, а не 2.5, которые я указал. Это действительно удручает с балансировкой нагрузки, мне нужно знать, что сервис ушел в течение 2,5 секунд. Есть ли способ получить это исключение в течение требуемого промежутка времени?

Кстати, исключение читает что-то вроде:

Не удалось подключиться к net.tcp://192.168.227.130: 30000/MXIOXfer. попытка соединения продолжалась в течение промежутка времени 00: 00: 02.4209684. TCP код ошибки 10060: попытка подключения не удалась, поскольку подключенный сторона не отвечала должным образом после определенного периода времени или соединение не удалось, поскольку подключенный хост не смог ответить 192.168.227.130:30000.

но это действительно занимает более двадцати секунд. Я включил трассировку WCF и вижу предупреждение о неудачной попытке TCP непосредственно перед исключением и имеет РЕАЛЬНОЕ время:

Не удалось подключиться к net.tcp://192.168.227.130: 30000/MXIOXfer. попытка подключения продолжалась в течение промежутка времени 00: 00: 21.0314092. TCP код ошибки 10060: попытка подключения не удалась, поскольку подключенный сторона не отвечала должным образом после определенного периода времени или соединение не удалось, поскольку подключенный хост не смог ответить 192.168.227.130:30000.

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

EDIT:

Этот поток, кажется, указывает, что тайм-ауты сокета заданы операционной системой. Есть ли параметр реестра для таких вещей?

Ответ 1

Объединяя детали, найденные в SO и MSDN Социальные потоки, на которые ссылаются мной и eol, привели меня к этим параметрам реестра:

HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\Tcpip\Parameters\Interfaces {XXXXXXXXXXXX-хххх-XXXXXXXXXXXX}\TcpInitialRTT

Тип значения: REG_DWORD-номер

Допустимый диапазон: 0-0xFFFF

По умолчанию: 3 секунды

Описание: Этот параметр управляет начальным тайм-аутом, используемым для Запрос TCP-соединения и повторная передача исходных данных на для каждого интерфейса. Соблюдайте осторожность при настройке с помощью этого параметра потому что используется экспоненциальная отсрочка. Установка этого значения больше, чем 3 приводит к значительно более длительным тайм-аутам к несуществующим адресам.

.

HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\Tcpip\Parameters\Interfaces {XXXXXXXXXXXX-хххх-XXXXXXXXXXXX}\TcpMaxConnectRetransmissions

Тип значения: REG_DWORD-номер

Допустимый диапазон: 0-255 (десятичный)

По умолчанию: 2

Описание: Этот параметр определяет количество раз, когда TCP ретранслирует запрос на соединение (SYN) перед отменой попытки. повторная передача времени удваивается с каждой последующей повторной передачей в заданной попытке подключения. Первоначальный тайм-аут контролируется Значение реестра TcpInitialRtt.

.

HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\Tcpip\Parameters\Interfaces {XXXXXXXXXXXX-хххх-XXXXXXXXXXXX}\TcpMaxDataRetransmissions

Тип значения: REG_DWORD-номер

Допустимый диапазон: 0-0xFFFFFFFF

По умолчанию: 5

Описание: Этот параметр управляет количество раз, когда TCP повторно передает отдельный сегмент данных (не сегменты запроса на соединение), прежде чем прерывать соединение. повторная передача времени удваивается с каждой последующей повторной передачей по соединению. Это reset, когда ответы возобновляются. Повторная передача Значение Timeout (RTO) динамически корректируется, используя исторический измеренное время прохождения в оба конца (сглаженное время разворота или SRTT) на каждом подключение. Начальный RTO на новом соединении контролируется Значение реестра TcpInitialRtt.

Поскольку значение тайм-аута при неудачном подключении удваивается для каждой попытки повторного запуска, значения по умолчанию делают первую попытку неудачной в течение 3 секунд, вторая неудачна в 6, а третья и последняя попытка не выполняются через 12 секунд или всего 21 секунду, BTW, ключ TcpMaxDataRetransmissions не имеет к этому никакого отношения, я включаю его для полноты и тех, кто приходит позже.

Ни одно из этих значений не присутствует по умолчанию, вы должны добавить их для их изменения. Выяснив, какой интерфейс для этого легко выполнить, каждый интерфейс имеет ключ, содержащий его текущий IP-адрес. (Там даже один для локального хоста). В моем случае просто установка TcpMaxConnectRetransmissions на ноль (0) на интерфейсах VM по умолчанию устанавливает мой тайм-аут сокета для них до 3 секунд, что достаточно близко к 2.5 для работы. Моя балансировка нагрузки работает при сбое службы WCF.

Ответ 2

Я считаю, что этот пост говорит о той же проблеме: wcf channelelfactory и opentimeout.

Проблема заключается в том, что базовые сокеты имеют по умолчанию 20 с или так, что WCF не переопределяет. Проверьте последний ответ, чтобы реализовать собственный таймаут, открыв асинхронно.