问题:
客户端应用程序是间歇性的(每周一次)在proxy.Open()
期间获得超时,并且仅在特定的方法调用上。获得超时的客户端可以在几秒钟之后调用WCF服务,没有任何问题。
设定:
所有运行Windows 7 64位,.NET 4.5.1,Microsoft Security Essentials的客户端
服务器正在运行Windows Server 2012R2,.NET 4.5.1,未安装防病毒版
WCF服务作为标准Windows服务运行:
[ServiceContract(SessionMode = SessionMode.Required)]
[ServiceBehavior(InstanceContextMode = InstanceContextMode.Single, ConcurrencyMode = ConcurrencyMode.Multiple)]
客户端总数= 30.最多3个客户端同时访问WCF服务。客户端通过许多不同的方法与服务进行通信(同步不同的表),但会话最多持续20秒。发送的每条消息的大小都保证不到2MB。
proxy
是System.ServiceModel.ClientBase
,是通过Visual Studio创建的 - 添加服务引用。
的app.config
服务器端:
<system.serviceModel>
<services>
<service behaviorConfiguration="secureBehavior" name="MyService.SynchronizationService">
<endpoint address="net.tcp://localhost:8999/MyService/SynchronizationService" binding="netTcpBinding" bindingConfiguration="secureNetTcp" contract="MyService.ISynchronizationService">
<identity>
<certificateReference storeName="Root" storeLocation="LocalMachine" x509FindType="FindByThumbprint" findValue="..." />
</identity>
</endpoint>
</service>
</services>
<bindings>
<netTcpBinding>
<binding name="secureNetTcp" openTimeout="00:00:25" closeTimeout="00:00:19" receiveTimeout="00:10:10" sendTimeout="00:01:00"
listenBacklog="100" maxConnections="100" maxBufferPoolSize="20971520" maxBufferSize="2097152" maxReceivedMessageSize="2097152">
<reliableSession ordered="true" inactivityTimeout="00:10:00" enabled="true"/>
<readerQuotas maxArrayLength="2147483647" maxBytesPerRead="2147483647" maxDepth="2147483647" maxNameTableCharCount="2147483647" maxStringContentLength="2147483647" />
<security mode="TransportWithMessageCredential">
<transport clientCredentialType="Windows" protectionLevel="EncryptAndSign" />
<message clientCredentialType="Windows" algorithmSuite="Basic256Sha256" />
</security>
</binding>
</netTcpBinding>
</bindings>
<behaviors>
<serviceBehaviors>
<behavior name="secureBehavior">
<serviceMetadata httpGetEnabled="false" httpsGetEnabled="false" />
<serviceCredentials>
<serviceCertificate findValue="..." storeLocation="LocalMachine" storeName="Root" x509FindType="FindByThumbprint" />
</serviceCredentials>
<serviceThrottling maxConcurrentCalls="100" maxConcurrentSessions="100" maxConcurrentInstances="100" />
</behavior>
</serviceBehaviors>
</behaviors>
</system.serviceModel>
客户方:
<system.serviceModel>
<bindings>
<netTcpBinding>
<binding name="NetTcpBinding_ISynchronizationService" openTimeout="00:00:25" closeTimeout="00:00:19" receiveTimeout="00:01:00" sendTimeout="00:04:00"
listenBacklog="100" maxConnections="100" maxBufferPoolSize="20971520" maxBufferSize="2097152" maxReceivedMessageSize="2097152">
<reliableSession ordered="true" inactivityTimeout="00:10:00" enabled="true"/>
<readerQuotas maxArrayLength="2147483647" maxBytesPerRead="2147483647" maxDepth="2147483647" maxNameTableCharCount="2147483647" maxStringContentLength="2147483647" />
<security mode="TransportWithMessageCredential">
<transport clientCredentialType="Windows" protectionLevel="EncryptAndSign"/>
<message clientCredentialType="Windows" algorithmSuite="Basic256Sha256"/>
</security>
</binding>
</netTcpBinding>
</bindings>
<client>
<endpoint address="net.tcp://bla.foo.com:8999/MyService/SynchronizationService" binding="netTcpBinding"
bindingConfiguration="NetTcpBinding_ISynchronizationService" contract="MyService.ISynchronizationService" name="NetTcpBinding_ISynchronizationService" />
</client>
</system.serviceModel>
客户端的错误消息:
抛出两种类型的错误消息:
1)
System.TimeoutException: Client is unable to finish the security negotiation within the configured timeout (00:00:00). The current negotiation leg is 1 (00:00:00).
---> System.TimeoutException: The open operation did not complete within the allotted timeout of 00:00:00. The time allotted to this operation may have been a portion of a longer timeout.
---> System.TimeoutException: Open timed out after 00:00:00 while establishing a transport session to net.tcp://bla.foo.com:8999/MyService/SynchronizationService. The time allotted to this operation may have been a portion of a longer timeout.
---> System.TimeoutException: Connecting to via net.tcp://bla.foo.com:8999/MyService/SynchronizationService timed out after 00:00:00. Connection attempts were made to 0 of 1 available addresses (). Check the RemoteAddress of your channel and verify that the DNS records for this endpoint correspond to valid IP Addresses. The time allotted to this operation may have been a portion of a longer timeout.
2)
System.TimeoutException: The open operation did not complete within the allotted timeout of 00:00:00. The time allotted to this operation may have been a portion of a longer timeout.
---> System.TimeoutException: Open timed out after 00:00:00 while establishing a transport session to net.tcp://bla.foo.com:8999/MyService/SynchronizationService. The time allotted to this operation may have been a portion of a longer timeout.
---> System.TimeoutException: Connecting to via net.tcp://bla.foo.com:8999/MyService/SynchronizationService timed out after 00:00:00. Connection attempts were made to 0 of 1 available addresses (). Check the RemoteAddress of your channel and verify that the DNS records for this endpoint correspond to valid IP Addresses. The time allotted to this operation may have been a portion of a longer timeout.
调试步骤:
起初我认为这是客户端的一个问题。也许在从睡眠中醒来之后没有出现互联网连接。所以我在客户端代码中添加了检查以检查网络连接,ping www.intel.com和www.amd.com,在调用WCF服务之前等待10秒钟等等。但这没有帮助。
然后我在客户端代码中添加了一个检查,以实际手动打开WCF服务的套接字。空白点验证是否存在连接。我还验证了我没有使用using
模式与proxy
,try { } finally { }
只使用Abort()
和Close()
次调用。然而,即使在验证连接之后,客户端有时仍会超时(我在调用WCF服务之前正确关闭了验证套接字)。
在超时发生时,客户端和服务器事件查看器都没有任何错误或警告。服务器和客户端负载不存在,整个时间都很空闲。
由于超时只发生在Open()
方法调用期间,甚至发生在与服务器位于同一本地网络的客户端上,我认为这一定是服务器端问题。
跟踪:
我的最后一步是在服务器端启用跟踪,看看发生了什么。不幸的是,这并未提供太多见解。在超时的那一刻,我可以看到我的套接字验证成功,但没有更多的消息或活动。
有人可能认为这是没有互联网连接或数据包丢失的明显迹象。但那么为什么问题只发生在Open()
方法调用期间,甚至在本地网络内?它也不是硬件问题,因为WCF服务曾经在运行Server 2008R2的不同服务器上,但问题完全相同。
帮助
是否有任何WCF专家可以帮助我找出这个问题?
这可能是某种WCF内部错误,而不是正确处理套接字吗?
例如,跟踪向我显示,即使客户端已正确完成与WCF服务的对话 - 称为具有[IsTerminating=true]
属性且称为proxy.Close()
的方法 - WCF仍会在内部抛出异常。根据您在跟踪日志中查看的位置,有不同的消息:
1)Activity =连接时接收字节;抛出错误= System.TimeoutException
- The socket was aborted because an asynchronous receive from the socket did not complete within the allotted timeout of 00:02:00. The time allotted to this operation may have been a portion of a longer timeout.
2)活动= 0000000000000;抛出错误= System.Net.Sockets.SocketException
- An existing connection was forcibly closed by the remote host.
3)活动= 0000000000000;抛出错误= System.Net.Sockets.SocketException
- The I/O operation has been aborted because of either a thread exit or an application request.
4)活动= 0000000000000;抛出错误= System.ServiceModel.CommunicationException
- The socket connection was aborted. This could be caused by an error processing your message or a receive timeout being exceeded by the remote host, or an underlying network resource issue. Local socket timeout was '00:02:00'.
任何可以帮助摆脱这些内部错误的人的奖励积分(这些都发生在客户端与服务器完成对话之后)。目前我认为必须使用反射进入WCF碗内,找到使用的套接字并手动关闭...
修改
奖金指向我:)我发现每次客户端关闭时,如何修复服务器端的内部SocketExceptions - How to properly close a client proxy (An existing connection was forcibly closed by the remote host)?
现在我需要测试这是否对Open()
超时有任何影响。我可能无法在新年之前推出新版本的客户端......同时,如果有人对Open()
超时有任何想法,请分享。