【发布时间】:2015-08-13 22:21:31
【问题描述】:
我正试图找出我们在使用频繁的 WCF 服务之一时遇到的问题。它偶尔会变得无响应,从而使我们依赖该服务的几个内部网站无法使用。
我们怀疑这是因为一个或多个消费网站未能正确关闭连接,因此我们达到了服务允许的并发连接数限制。然而,我们没有实际的方法来确定哪一个,因为跨多个 tfs 存储库有这么多。
简而言之,当客户端在 wcf 代理上调用 Close() 时,如何从服务中检测到?或者更确切地说,如何检测服务方法完成后http连接是否仍然打开?
我在本地工作站上创建了一个测试服务和客户端,并尝试了以下方法,但都没有奏效:
测试服务:
public class Service1 : IService1
{
public string GetData(int value)
{
return string.Format("You entered: {0}", value);
}
}
测试客户端:
class Program
{
static void Main(string[] args)
{
ServiceReference1.Service1Client client = new ServiceReference1.Service1Client();
Console.WriteLine(client.GetData(0));
Console.ReadKey();
client.Close();
Console.WriteLine("Closed.");
Console.ReadKey();
}
}
运行 netstat 表明,即使在 client.Close() 之后,连接仍然保持打开状态(也许我只是误解了 netstat 的输出)。
perfmon 性能计数器(在添加 ServiceModelService 4.0.0.0 之后)报告服务调用甚至在 client.Close() 执行之前就已完成。服务调用后,client.Close() 前后的计数器没有变化。
接下来,我尝试监听 OperationContext.Current.Channel.Closed 事件(以及 Closing 和 Faulted):
public class Service1 : IService1
{
public string GetData(int value)
{
OperationContext.Current.Channel.Faulted += Channel_Faulted;
OperationContext.Current.Channel.Closing += Channel_Closing;
OperationContext.Current.Channel.Closed += Channel_Closed;
return string.Format("You entered: {0}", value);
}
void Channel_Faulted(object sender, EventArgs e)
{
// Breakpoint
}
void Channel_Closing(object sender, EventArgs e)
{
// Breakpoint
}
void Channel_Closed(object sender, EventArgs e)
{
// Breakpoint
}
}
但是我在事件处理程序中放置的断点都没有被命中。
我还尝试在 Global.asax 的 Session_Start 和 Session_End 事件中设置断点。 Session_Start 确实会触发,但 Session_End 永远不会触发(尽管我不知道会话是否与 http 连接是否处于活动状态有关)。
我对 wcf 有点陌生(我之前写过几个非常基本的服务),所以我觉得我在这个问题上有点过头了,深入研究我不理解的部分(例如,我在今天之前不知道 OperationContext 存在)。
【问题讨论】:
-
你的服务是无状态的还是有状态的?
-
我们遇到问题的服务是无状态的。
-
该死的,stackoverflow 已经不是以前的样子了。如果我在 2008 年问过这个问题,到现在我已经有十几个答案了。