3

我有一个双工 WCF 服务,它在神奇的 10 个代理实例之后挂起。客户端上的具体错误是:

“System.TimeoutException:发送到 net.tcp://localhost:8080/RoomService/netTcp 的请求操作未在配置的超时 (00:00:59.9960000) 内收到回复”。

服务器上没有任何明显的错误消息。

请注意,这不是标准的、明显的问题,即未能关闭我的代理连接,因为我在打开下一个代理连接之前适当地关闭了代理连接的每个实例:

try
{
    client.Close();
}
catch (CommunicationException)
{
    client.Abort();
}
catch (TimeoutException)
{
    client.Abort();
}
catch (Exception)
{
    client.Abort();
    throw;
}

我已经将我的节流行为设置为 500 同步所有内容:

ServiceThrottlingBehavior throttlingBehavior = new ServiceThrottlingBehavior()
{
    MaxConcurrentCalls = 500,
    MaxConcurrentSessions = 500,
    MaxConcurrentInstances = 500
};

我已将服务的 ConcurrencyMode 设置为 Multiple,并尝试了 InstanceContextMode 的所有三个可能值。

[ServiceBehavior(InstanceContextMode=InstanceContextMode.PerSession, ConcurrencyMode = ConcurrencyMode.Multiple)]

我尝试过自托管服务,并将其托管在 IIS 中,并且在每个服务上都得到了相同的结果。

我已经尝试过 NetTcpBinding、WSDualHttpBinding 和 PollingDuplexBinding(在 Silverlight 上),每个结果都相同。我不能尝试 BasicHttpBinding 或 WSHttpBinding,因为这是一个双工服务。

在我的代码中有一个地方我启动了多个线程(同时执行多个回调),但出于故障排除的目的,我已经注释掉了这一点,它并没有产生任何影响。

在客户端上,我尝试为每个测试使用新代理,并在所有测试中重用相同的代理,但没有任何运气。我尝试为每个代理创建一个新的 InstanceContext,并在所有代理中重用相同的 InstanceContext,但同样没有运气。

无论我做什么,在我的测试工具中执行第 10 次测试之后,下一次对服务的调用都会挂起。

关于我可能做错了什么的任何想法?

4

5 回答 5

5

好的,所以我至少犯了一个愚蠢的错误:我正在创建节流行为,但忽略了将其添加到适当的服务中。现在已正确添加:

ServiceThrottlingBehavior throttlingBehavior = new ServiceThrottlingBehavior()
{
    MaxConcurrentCalls = 500,
    MaxConcurrentSessions = 500,
    MaxConcurrentInstances = 500
};
base.Description.Behaviors.Add(throttlingBehavior);

现在我可以运行 10 多个测试,因此我的直接问题得到了解决。

但是我仍然对为什么会遇到这个问题感到困惑,因为我在继续下一个代理之前专门关闭了一个代理。MaxConcurrentXXX 为 2 应该在这种情况下工作;我不应该需要 500 的 MaxConcurrentXXX。如果每个连接到服务器的客户端在实际连接之后继续破坏连接,我有点担心可伸缩性。

也许我在其他地方犯了一个愚蠢的错误——这不会是第一次——但我已经专门逐步完成了关闭代理的代码,并且肯定会被调用。

于 2009-07-17T05:14:54.443 回答
0

当我在服务器端有一个信号量在客户端完成服务后没有被释放时,我就发生了这种情况。

是否有任何服务器端资源或锁未正确释放?由于您的服务实例是每个会话的,我怀疑服务器对象正在徘徊并持有锁。如果您将行为更改为每次调用会怎样?

于 2009-07-17T02:03:37.180 回答
0

我没有答案,但我有一些调试建议。

1)将visual studio调试器附加到服务进程,看看它是否能捕捉到正在发生的事情。

2) 配置服务行为,将异常信息传回客户端,查看服务是否抛出未报告的异常:

<behaviors>
    <serviceBehaviors>
        <behavior name="ServiceBehavior">
            <serviceDebug includeExceptionDetailInFaults="True"/>
        </behavior>
    </serviceBehaviors>
</behaviors>

3) 在启用 ActivityTracing 的情况下打开服务日志记录,并使用服务跟踪查看器(来自Windows SDK)分析日志并查看是否弹出任何内容

<system.diagnostics>
    <trace autoflush="true" />
    <sources>
        <source name="System.ServiceModel" switchValue="Information, ActivityTracing" propagateActivity="true">
            <listeners>
                <add name="sdt" type="System.Diagnostics.XmlWriterTraceListener" initializeData="Service.svclog"  />
            </listeners>
        </source>
    </sources>
</system.diagnostics>

4) 将服务包装器与功能代码隔离开,查看服务是否仍然挂起。如果没有,则逐步添加功能,直到您弄清楚是什么导致它挂起

5) 如果您使用的是 HTTP 绑定,请使用 fiddler 代理服务并记录 http 流量。

6) 尝试在托管 Windows 服务中托管 WCF 服务,并在启动后将调试器附加到服务进程。

于 2009-07-17T03:25:28.343 回答
0

看看 ServiceBehavior.AutomaticSessionShutdown。

于 2009-07-17T21:13:22.433 回答
0

在客户端回调函数的开头使用 OperationContext.Current.Channel.Close();

这将解决问题。

于 2009-09-25T11:09:28.860 回答