9

我有一个有时必须返回故障的 WCF 服务。由于某种原因,对我的服务的调用开始超时并出现以下错误:“请求通道在 00:00:59.8906201 之后等待回复时超时。增加传递给请求的调用的超时值或增加 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 次调用后继续运行。显然,我想很好地包装我的异常,所以仅仅抛出正常的异常并不是一个真正的选择。

为什么我会遇到这些超时异常?提前感谢您的帮助..

4

6 回答 6

3

我没有足够的积分来评论,所以新的回应......

自托管服务最多只允许 10 个并发连接 - 无论传输方式如何。如果您在 IIS/WAS 中运行 WCF 服务,则不必担心这一点(除非您在 XP/Vista 上,最大并发连接数也是 10)。

在这种情况下,故障异常和常规异常之间的差异可以解释您所看到的结果。

请记住,常规的未处理异常会使通道出错。在这样做时,我假设这会打开一个可用的连接。当您返回故障时,它不会自动使通道故障,因为它允许您对连接执行某些操作并最终处理故障,因为它是可能的“预期”故障,而未处理的异常则不会。

即使您返回错误,您仍然需要 Abort() 连接。此外,下面还有非托管资源,因此请务必在您的客户端/代理的调用者上实现 IDisposable。

于 2009-06-12T18:58:27.813 回答
2

我认为这可能是因为 WCF 服务的默认行为是 10 个并发会话。FaultExceptions 发生后您是否保持连接打开?您可以尝试在 BehaviorConfiguration (ServiceThrottling > MaxConcurrentSessions) 中更改此值,看看是否有任何改变。我建议您使用 Microsof 服务配置编辑器检查默认设置的其他值。( MSDN )

希望这可以帮助...

于 2009-06-12T12:43:35.390 回答
2

我面临着同样的问题。仔细观察后发现,在完成对 Web 服务的调用后,我并没有关闭 Web 服务客户端。一旦我这样做了,即使在对 web 服务进行 10 次方法调用后它也没有失败。请参见下面的示例。

WebServiceClient svcClient = new WebServiceClient();

string returnValue = svcClient.GetDocumentName(fileId);

svcClient.Close();

正确的模式:

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

ClientBaseimplements ,它在方法内IDisposable调用。Close()Dispose

于 2009-11-05T22:40:25.520 回答
1

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

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

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

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

于 2009-06-12T12:19:48.817 回答
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() 应该始终是最后的手段。

于 2009-06-18T09:15:14.213 回答
0

试试我的 WCF 服务模型客户端 API,看看是否会出现相同的结果。我认为客户端代码中的某些内容不正确...

编码

PPT

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

于 2009-06-12T18:18:21.170 回答