【问题标题】:WCF Client ignores timeout values when service downWCF 客户端在服务关闭时忽略超时值
【发布时间】:2012-08-07 20:00:31
【问题描述】:

我有一个使用 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。

如果有什么不同,服务的所有通信都在单独的线程上完成。

编辑:

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

【问题讨论】:

  • 该代码示例看起来像是在打开通道后设置了 OperationTimeout。如果将它移到 ServiceConnect() 之前会发生什么?
  • @ErnieL - 同样的事情,就像在之前和之后设置它一样。 After 需要超时才能正常运行,所以这是我留下的。

标签: .net vb.net wcf wcf-client


【解决方案1】:

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

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

【讨论】:

  • 那个解决方案是打开频道,我的问题是成功打开频道后超时但服务崩溃。每次打开频道以确保服务仍然正常运行会很麻烦;当通道已经启动时,是否有等效的技术?
  • 关于这个长时间延迟的另一篇文章:stackoverflow.com/a/5989738/1539015。似乎套接字层把事情搞砸了。您必须以异步方式对服务进行每次调用并自己跟踪超时……至少从我目前发现的情况来看是这样。
【解决方案2】:

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

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 重新传输单个数据段的次数(不是 连接请求段)在中止连接之前。这 每次连续重传时,重传超时加倍 在一个连接上。当响应恢复时它被重置。重传 超时 (RTO) 值是动态调整的,使用历史 测量的往返时间(平滑往返时间,或 SRTT) 联系。新连接上的起始 RTO 由 TcpInitialRtt 注册表值。

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

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

【讨论】:

  • 很好地找到了根本原因。对未来读者的一些警告:这是一个低级修复,可能会影响同一台计算机上的其他程序。当您的机器用途有限时最好使用。此外,我看到一些关于此的帖子可能在某些较新版本的 Windows 中已被弃用。马克,您能告诉我们您使用的是哪个 Windows 操作系统吗?
  • @eol - 当然,我的目标是 XP->7 (.NET 4),MS KBA support.microsoft.com/kb/170359 说它受 NT 支持。有 RFC 涵盖了这种行为;如果停产,MS 将不得不在其他地方为其提供支持。 (恕我直言,这首先是一种糟糕的方式。)你能指出表明贬值的帖子吗?
  • 我一开始就应该这样做。我回去拿列表,发现我在大约 4 个不同的地方看到过这个,当我仔细观察时,它们都是一个讨论线程的克隆/副本(social.technet.microsoft.com/Forums/en-US/w7itpronetworking/…,两个答案。)因为只有一个有人说了这一点,我找不到任何其他来源来证实,我撤回了我关于可能被弃用的声明。
猜你喜欢
  • 2012-11-24
  • 2016-02-16
  • 1970-01-01
  • 2011-03-22
  • 2012-03-25
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多