为什么我的WCF服务在调用10次后返回FaultException并超时?

9
我有一个WCF服务,有时需要返回故障。由于某些原因,我的服务调用开始超时,并显示以下错误信息:“等待回复时请求通道超时,已经过 00:00:59.8906201。增加传递给 Request 方法的超时值或增加 Binding 上的 SendTimeout 值。分配给此操作的时间可能是较长超时期间的一部分。”
在检查问题后,发现了一种模式:当服务返回10次故障时,超时就会开始。因此,我创建了一个测试服务实现:
public string GetData(int value)
{
    throw new FaultException("A testerror occured");
}

并且还有一个测试客户端:

   protected void RunTestGetData()
    {
        using (TestServiceReference.Service1Client client
            = new WSPerformanceTester.TestServiceReference.Service1Client())
        {
            try
            {
                client.GetData(1);
                client.Close();
                outputWriter.WriteLine(string.Format("Call run in thread {0}: GetData()", Thread.CurrentThread.ManagedThreadId));
                outputWriter.Flush();
            }
            catch (Exception e)
            {
                client.Abort();
                client.Close();
                outputWriter.WriteLine(string.Format("Error occured in thread {0}: GetData(): {1}", Thread.CurrentThread.ManagedThreadId, e.Message));
                outputWriter.Flush();
            }
        }
    }

只有当服务返回FaultException时才会发生这种情况。如果我抛出普通异常,服务能够在第10次调用后继续运行。显然,我希望将我的异常包装好,因此仅仅抛出普通异常并不是一个真正的选择。

为什么会出现超时异常?提前感谢任何帮助。

6个回答

3

我没有足够的积分来发表评论,所以只能新建回复...

自托管服务仅允许最多10个并发连接 - 无论是哪种传输方式。如果你在IIS/WAS中运行WCF服务,你不必担心这个问题(除非你使用XP/Vista,在这些系统中最大并发连接数也是10)。

在这种情况下,故障异常和普通异常之间的区别可能会导致你看到的结果有所不同。

请记住,未处理的普通异常会使信道故障。这样做我认为会打开一个可用的连接。当你返回一个故障时,它不会自动使信道故障,因为它允许你对连接进行一些操作,并在你的端口处理故障,因为它是一种可能的“预期”故障,而未处理的异常则不是。

即使你返回一个故障,你仍然需要Abort()连接。此外,在底层有未管理的资源,所以请确保在客户端/代理的调用者上实现IDisposable。


2

我曾经遇到过同样的问题。仔细观察后发现,在调用完webservice之后,我没有关闭webservice客户端。一旦我关闭了客户端,即使对webservice进行了10次方法调用,它也不会失败。请参见下面的示例。

WebServiceClient svcClient = new WebServiceClient();

string returnValue = svcClient.GetDocumentName(fileId);

svcClient.Close();

正确的模式:

using(WebServiceClient svcClient = new WebServiceClient())
{
   return svcClient.GetDocumentName(fileId);
}

ClientBase 实现了 IDisposable 接口,其中在 Dispose 方法中调用了 Close() 方法。


3
不应该用using语句包装WCF客户端。请参阅以下文章:http://msdn.microsoft.com/en-us/library/aa355056.aspx。 - mr goose
谢谢,我也遇到了这个问题,一开始很难追踪。不管怎样,感谢您的发布。 - zulucoda

2
我认为这可能是因为WCF服务的默认行为是10个并发会话。在FaultExceptions发生后,您是否保持连接打开?您可以尝试在BehaviorConfiguration(ServiceThrottling> MaxConcurrentSessions)中更改此值,看看是否有任何变化。我建议您使用Microsoft Service Configuration Editor查看默认设置了哪些其他值。(MSDN
希望这能帮到您...

但是客户端.Abort()或client.Close()不应该关闭会话吗?为什么只有在使用FaultException时才会发生这种情况? - Jesper Kihlberg
我和 Jesper 有同样的问题。有人知道吗? - Patrick Szalapski

1

显然,客户端代码应该如下:

protected void RunTestGetData()
{
    TestServiceReference.Service1Client client
        = new WSPerformanceTester.TestServiceReference.Service1Client()
    try
    {
        client.GetData(1);
    }
    catch (FaultException e)
    {
        //Handle fault
    }
    try
    {
        if (client.State != System.ServiceModel.CommunicationState.Faulted)
        {
            client.Close();
        }
    }
    catch(Exception e)
    {
        outputWriter.WriteLine("Error occured in Client.Close()");
        outputWriter.Flush();
        client.Abort();
    }
}

调用 client.Abort() 应该始终是最后的选择。


1

我可能说错了,但我认为这与WCF服务的托管有关。

因为它可能无法及时响应请求。

例如,在Windows XP上的IIS可以同时回复5个(我现在不太确定)请求。如果发出更多请求,它会进入队列。

我相信它可能会丢失请求,并且这样做,而不是处理它们,因为您的测试实际上什么也没做,只是抛出异常。


0

尝试使用我的WCF服务模型客户端API,看看是否出现相同的结果。我认为客户端代码有问题...

代码

PPT

此外,在客户端和服务器上启用详细的WCF日志记录...


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接