为什么我的 WCF 服务在 10 次调用后返回故障异常并超时?
我有一个 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 次调用后继续运行。 显然,我想很好地包装我的异常,所以仅仅抛出正常的异常并不是一个真正的选择。
为什么我会遇到这些超时异常? 预先感谢您的任何帮助..
I have a WCF service that sometimes has to return a Fault. For some reason, the calls to my service begins to time out with the following error:
"The request channel timed out while waiting for a reply after 00:00:59.8906201. Increase the timeout value passed to the call to Request or increase the SendTimeout value on the Binding. The time allotted to this operation may have been a portion of a longer timeout."
After examining the problem, a pattern emerged: When the service had returned a fault 10 times, the timeout starts. So I created a testservice implemented by:
public string GetData(int value)
{
throw new FaultException("A testerror occured");
}
And a testclient:
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();
}
}
}
This only happens, when the service is returning a FaultException. If I throw a normal exception, the service is able to continue running after the 10th call. Obviously, i would like to wrap my exceptions nicely, so just throwing normal exceptions is not a real option.
Why do I experience these timeout exceptions? Thanks in advance for any help..
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(6)
我没有足够的观点来评论,所以新的回应...
自托管服务最多只允许 10 个并发连接 - 无论传输方式如何。 如果您在 IIS/WAS 内运行 WCF 服务,则不必担心这一点(除非您使用的是 XP/Vista,其中最大并发连接数也是 10)。
在这种情况下,故障异常和常规异常之间的差异可以解释您所看到的结果。
请记住,常规的未处理异常会使通道出现故障。 这样做时,我假设这会打开一个可用的连接。 当您返回故障时,它会自动对通道进行故障处理,因为它允许您对连接执行某些操作并在您的一端处理故障,因为它可能是“预期”故障,而未处理的异常则不会。
即使返回错误,您仍然需要 Abort() 连接。 此外,下面还有非托管资源,因此请务必在客户端/代理的调用者上实现 IDisposable。
I don't have enough points to comment, so new response...
Self hosted services only allow a max of 10 concurrent connections - no matter the transport. If you're running WCF services inside of IIS/WAS you shouldn't have to worry about this (unless you're on XP/Vista where the max concurrent connections is also 10).
Differences between a fault exception and a regular exception in this scenario can account for the result you're seeing.
Remember, a regular unhandled exception will fault the channel. In doing so I assume this opens up an available connection. When you return a fault, it won' automatically fault the channel because it allows you to do something with the connection and handle the fault on your end because it is a possible "expected" fault whereas an unhandled exception would not be.
Even when you return a fault, you still need to Abort() the connection. Also, underneath there are unmanaged resources so be sure to implement IDisposable on your clients/proxy's callers.
我认为这可能是因为 WCF 服务的默认行为是 10 个并发会话。
发生故障异常后是否保持连接打开? 您可以尝试在BehaviorConfiguration(ServiceThrotdling > MaxConcurrentSessions)中更改此值,看看是否会发生任何变化。
我建议您使用 Microsoft 服务配置编辑器来检查默认设置的其他值。 (MSDN)
希望这有帮助...
I think this might be because the default behavior of a WCF service is 10 concurrent sessions.
Are you keeping the connections open after the FaultExceptions occur? You can try to alter this value in the BehaviorConfiguration (ServiceThrottling > MaxConcurrentSessions) and see if that changes anything.
I suggest you use the Microsof Service Configuration Editor to check out what other values are set by default. (MSDN)
hope this helps...
我面临着同样的问题。 仔细观察发现,在完成对 Web 服务的调用后,我没有关闭 Web 服务客户端。 一旦我这样做了,即使在对 Web 服务进行 10 次方法调用之后,它也没有失败。 请参阅下面的示例。
正确模式:
ClientBase
实现IDisposable
,它在Dispose
方法中调用Close()
。I was facing the same issue. A closer look revealed that I was not closing the webservice client after I was done making the calls to the webservice. Once I did that, it did not fail even after 10 method calls to the webservice. See the example below.
proper pattern:
ClientBase
implementsIDisposable
, which callsClose()
within theDispose
method.我在这里可能是错的,但我认为这与 WCF 服务的托管有关。
因为它可能无法及时响应请求。
例如,Windows XP 上的 IIS 可以同时回复 5 个(我现在不太确定)请求。 如果发出更多请求,则会进入队列。
我相信它可能会丢失请求,并且这样做而不是处理它们,因为您的测试实际上除了抛出异常之外什么也不做。
I might be wrong here, but I think it has something to do with the hosting of the WCF service.
Because it might not be able to respond to the request in a timely fashion.
IIS on Windows XP, for instance, can reply to 5 (and I'm not so sure about it right now) simultaneous requests. If more requests are made, it go to a queue.
And I believe it might be loosing the requests, and doing so, not processing them, as your test actually do nothing but throw an exception.
显然,客户端代码应如下所示:
调用 client.Abort() 应该始终是最后的手段。
Apparently, the client code should be as follows:
Calling client.Abort() should always be a last resort.
尝试我的 WCF 服务模型客户端 API,看看是否会出现相同的结果。 我认为客户端代码中有问题...
代码
PPT
另外,在客户端和服务器上启用详细 WCF 日志记录...
Try my WCF Service Model Client API and see if the same results occur. I am think something is not right in the client code...
The Code
The PPT
Also, enable verbose WCF logging on both the client and server...