11

我有一个使用 WCF 的 VB .NET 应用程序。我已经为代码中的所有内容设置了客户端超时:

    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,建立连接失败。

但它确实需要超过 20 秒。我已经打开了 WCF 跟踪,并且可以在异常之前看到 TCP 操作失败警告,并且它具有实时时间:

无法连接到 net.tcp://192.168.227.130:30000/MXIOXfer。连接尝试持续了 00:00:21.0314092 的时间跨度。TCP错误码10060:连接尝试失败,因为连接的一方在一段时间后没有正确响应,或者连接的主机没有响应192.168.227.130:30000,建立连接失败。

如果有任何区别,服务的所有通信都在单独的线程上完成。

编辑:

该线程似乎表明套接字超时是由操作系统设置的。是否有此类事情的注册表设置?

4

2 回答 2

3

结合我和 eol 引用的 SO 和 MSDN Social 线程中的详细信息,我找到了以下注册表设置:

HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\Tcpip\Parameters\Interfaces{xxxxxxxx-xxxx-xxxx-xxxxxxxxxxxx}\TcpInitialRTT

值类型:REG_DWORD—数字

有效范围:0–0xFFFF

默认值:3 秒

说明:此参数控制用于 TCP 连接请求的初始超时和基于每个接口的初始数据重传。使用此参数进行调整时要小心,因为使用了指数退避。将此值设置为大于 3 会导致对不存在地址的超时时间更长。

.

HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\Tcpip\Parameters\Interfaces{xxxxxxxx-xxxx-xxxx-xxxxxxxxxxxx}\TcpMaxConnectRetransmissions

值类型:REG_DWORD—数字

有效范围:0–255(十进制)

默认值:2

说明:此参数确定 TCP 在中止尝试之前重新传输连接请求 (SYN) 的次数。在给定的连接尝试中,每次连续的重传都会使重传超时加倍。初始超时由 TcpInitialRtt 注册表值控制。

.

HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\Tcpip\Parameters\Interfaces{xxxxxxxx-xxxx-xxxx-xxxxxxxxxxxx}\TcpMaxDataRetransmissions

值类型:REG_DWORD—数字

有效范围:0-0xFFFFFFFF

默认值:5

说明:此参数控制 TCP 在中止连接之前重新传输单个数据段(不是连接请求段)的次数。连接上的每次连续重传,重传超时加倍。当响应恢复时它被重置。使用每个连接上的历史测量往返时间(平滑往返时间或 SRTT)动态调整重传超时 (RTO) 值。新连接上的起始 RTO 由 TcpInitialRtt 注册表值控制。

由于每次重试失败连接的超时值加倍,默认值使第一次尝试在 3 秒内失败,第二次在 6 秒内失败,第三次也是最后一次尝试在 12 秒内失败,或总共 21 秒。顺便说一句,TcpMaxDataRetransmissions键与此无关,我将其包括在内以保持完整性和稍后出现的人。

默认情况下,这些值都不存在,您必须添加它们才能更改它们。确定要在哪个接口上执行此操作很容易,每个接口都有一个包含其当前 IP 地址的密钥。(甚至 localhost 也有一个。)在我自己的情况下,只需将 VM 接口上的TcpMaxConnectRetransmissions设置为零 (0),我的套接字超时默认为 3 秒,这足够接近 2.5 来工作。当 WCF 服务现在崩溃时,我的负载平衡工作。

于 2012-08-15T13:24:50.147 回答
1

我相信这篇文章谈到了同样的问题:wcf channelfactory 和 opentimeout

问题是底层套接字有一个默认的 20 秒左右的超时,WCF 没有覆盖。检查最后一个答案,以通过异步打开来实现自己的超时。

于 2012-08-14T12:59:46.670 回答