我正在使用 WCF 在 C# 中编写客户端/服务器应用程序。我所有的测试都很顺利,但是一旦我部署了服务,我就注意到与服务器通信的随机问题。我启用了调试并在服务器中看到了这样的消息:
The communication object, System.ServiceModel.Channels.ServerReliableDuplexSessionChannel, cannot be used for communication because it has been Aborted.
模式是这样的:
- 客户端正在发送查询
- 服务正在处理查询
- 服务正在发回一些东西
- 活动边界是“停止”级别 - 一切似乎都很好
- 将可靠会话的 inactivityTimeout 添加到上次联系的日期时间,您就有了服务抛出的异常的时间戳
应用程序是这样的:服务实例提供了一个与数据库交互的 API 方法,并且是“netTcpBinding”类型。连接了几个客户端(大约 40 个)并从服务中随机调用方法。即使没有发送或接收任何东西,客户也可以保持开放数天。
以下是相关位:
服务:
[ServiceContract(CallbackContract = typeof(ISVCCallback), SessionMode = SessionMode.Required)]
[ExceptionMarshallingBehavior]
...
和
[ServiceBehavior(InstanceContextMode = InstanceContextMode.Single, ConcurrencyMode = ConcurrencyMode.Multiple, UseSynchronizationContext=true)]
public class SVCService : ISVC
...
服务配置:
<behaviors>
<serviceBehaviors>
<behavior name="behaviorConfig">
<serviceMetadata httpGetEnabled="false" httpGetUrl="" />
<serviceDebug includeExceptionDetailInFaults="true" />
<serviceThrottling maxConcurrentCalls="50" maxConcurrentSessions="1000"
maxConcurrentInstances="50" />
</behavior>
</serviceBehaviors>
</behaviors>
<bindings>
<netTcpBinding>
<binding name="tcpBinding" closeTimeout="00:01:00" openTimeout="00:10:00"
receiveTimeout="23:59:59" sendTimeout="00:01:30" transferMode="Buffered"
listenBacklog="1000" maxBufferPoolSize="671088640" maxBufferSize="671088640"
maxConnections="1000" maxReceivedMessageSize="671088640" portSharingEnabled="true">
<readerQuotas maxStringContentLength="671088640" maxArrayLength="671088640"
maxBytesPerRead="671088640" />
<reliableSession inactivityTimeout="23:59:59" enabled="true" />
<security mode="None">
</security>
</binding>
</netTcpBinding>
</bindings>
客户端配置:
<bindings>
<netTcpBinding>
<binding name="NetTcpBinding_ISVC" closeTimeout="00:01:00" openTimeout="00:10:00"
receiveTimeout="23:59:59" sendTimeout="00:01:30" transactionFlow="false"
transferMode="Buffered" transactionProtocol="OleTransactions"
hostNameComparisonMode="StrongWildcard" listenBacklog="1000"
maxBufferPoolSize="671088640" maxBufferSize="671088640" maxConnections="1000"
maxReceivedMessageSize="671088640">
<readerQuotas maxStringContentLength="671088640" maxArrayLength="671088640"
maxBytesPerRead="671088640" />
<reliableSession ordered="true" inactivityTimeout="23:59:59"
enabled="true" />
<security mode="None">
<message clientCredentialType="Windows" />
</security>
</binding>
</netTcpBinding>
</bindings>
这里有什么问题吗?此类应用程序的最佳配置是什么?
更新:
我遇到一件事:
在一份服务合同中,我更改了一些内容并通知所有连接的客户。它通常工作正常,至少在我的测试中是这样。但是最后一次“崩溃”或“冻结”我浏览了日志,发现最新的函数是我使用回调合约通知客户端的地方。
我想在那里做什么:我将一些东西保存到数据库中,最后我通知所有连接的客户端更改。我认为连接的客户端列表不再是最新的,并且在这一步遇到超时。
现在的问题是如何避免这些超时。
- 我应该在服务中使用线程吗?我认为一旦服务调用结束,线程就会被杀死,我在这里吗?
- 我可以实现一个静态队列函数来执行所有回调通知(这是 Marc_S 建议的)
- 有没有办法可靠地检测服务器内部的连接断开?