gpt4 book ai didi

wcf - 为长时间运行的 WCF 应用程序选择正确的连接属性

转载 作者:行者123 更新时间:2023-12-02 08:59:29 26 4
gpt4 key购买 nike

我正在使用 WCF 用 C# 编写客户端/服务器应用程序。我的所有测试都很顺利,但是当我部署服务后,我注意到与服务器通信时出现随机问题。我启用了调试并在服务器中看到了这样的消息:

The communication object, System.ServiceModel.Channels.ServerReliableDuplexSessionChannel, cannot be used for communication because it has been Aborted.

模式是这样的:

  • 客户端正在发送查询
  • 服务正在处理查询
  • 服务正在发回一些内容
  • 事件边界处于“停止”级别 - 一切看起来都很好
  • 将可靠 session 的 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>

这里有什么问题吗?此类应用程序的最佳配置是什么?

更新:

我遇到了一件事:

在一份服务契约(Contract)中,我更改了一些内容并通知所有连接的客户端。它通常工作得很好,至少在我的测试中是这样。但上次“崩溃”或“卡住”时,我单步查看日志,发现最新的函数是我使用回调合约来通知客户端的地方。

我想在那里做什么:我将一些内容保存到数据库中,最后我通知所有连接的客户端更改。我认为连接的客户端列表不再是最新的,并且在这一步遇到超时。

现在的问题是如何避免这些超时。

  • 我应该在服务中使用线程吗?我认为一旦服务调用结束,线程就会被杀死,我在这里吗?
  • 我可以实现一个静态队列函数来执行所有回调通知(这是 Marc_S 建议的)
  • 有没有办法可靠地检测服务器内部的连接丢失?

最佳答案

只是一个疯狂的想法:由于您的客户似乎在很长一段时间内(甚至几天)发送消息,但似乎发送频率并不高 - 您是否可以重新构建您的应用程序以使用消息之类的东西队列而不是回调合约?

队列是解耦两个系统并减少超时等可能性的好方法。

在基于队列的场景中,您的客户端会将消息放入队列(例如,Windows Server 的每个副本附带的 MSMQ),并且您的服务将监听传入队列中的消息。该服务将抓取消息,处理它们,并且通常将某种响应消息放回第二个队列(然后客户端监听)。

这里的主要好处是:

  • 您不需要相当脆弱且复杂的回调合约设置
  • 您的系统是解耦的,即使它们之间的连接中断几秒钟、几分钟、几小时,它们也会继续工作
  • 您的服务可以响应传入消息并发回更多“有针对性”的响应,例如某些客户端可以监听“正常”响应队列,其他客户端可以监听“优先”响应队列等 - 在我看来,系统只是为您提供了更大的灵活性

查看更多资源:

并查看诸如

之类的内容

以及其他系统(MassTransit 等),它们支持排队通信,以在系统之间提供高度可扩展、可靠的消息传递。

关于wcf - 为长时间运行的 WCF 应用程序选择正确的连接属性,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/2392462/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com