服务代理的关闭与并发会话的限制

这几天将WCF的绑定由BasicHttpBinding换成了wsHttpBinding,随后问题也伴随着wsHttpBinding的绑定而来。

时而客户端得到异常:请求通道在等待 00:00:59.9840000以后答复超时。增加传递给请求调用的超时值,或者增加绑定上的 SendTimeout 值。分配给此操作的时间可能是更长超时的一部分。服务重启之后恢复正常。

在Artech博客中看到一篇相关文章:http://www.cnblogs.com/artech/archive/2009/07/04/1516908.html

整理如下:

1.信道分两种

  • 会话信道(Sessionful Channel):会话信道确保客户端和服务端之间传输的消息能够相互关联,但是信道的错误(Fault)会影响后续的消息交换;
  • 数据报信道(Datagram Channel):即使在同一个数据报信道中,每次消息的交换都是相互独立,信道的错误也不会影响后续的消息交换

2.信道创建

  对于绝大部分绑定类型(BasicHttpBinding除外),在默认的情况下创建的都是会话信道。对于WCF客户端来说,如果进行基于会话信道的服务调用,有一些问题需要引起足够的重视(基于会话信道服务调用须要注意的第一个问题和WCF流量限制有关),如果使用不当,不但影响客户端本身的服务调用,还会对服务处理请求的吞吐量造成很大的影响。

以下为客户端调用服务的代码:

 1 class Program
 2     {
 3         static void Main(string[] args)
 4         {
 5             try
 6             {
 7                 for (int i = 0; i < 10000; i++)//循环10000次调用服务
 8                 {
 9                     SR.TestClient c = new SR.TestClient();
10                         string res = c.Login("张三", "123", "", "");
11                         Console.WriteLine("" + i + "");
12                 }
13             }
14             catch (Exception ex)
15             {
16                 Console.WriteLine(ex.Message);
17             }
18             Console.ReadLine();
19         }
20     }

执行结果:

出现这种情况的原因是因为在客户端调用服务后没有关闭服务代理。连接数量超出WCF对并发会话数量的控制。

WsHttpBinding在默认的情况下安全模式(SecurityMode)为基于消息的安全,所以创建出来的信道自动被赋予了会话的特性。

之前BasicHttpBinding绑定模式没有出现此问题是因为BasicHttpBinding不是会话模式

客户端调用改用如下模式即可

 1 class Program
 2     {
 3         static void Main(string[] args)
 4         {
 5             try
 6             {
 7                 for (int i = 0; i < 10000; i++)
 8                 {
 9                     SR.TestClient c = new SR.TestClient();
10                     string res = c.Login("张三", "123", "", "");
11                     Console.WriteLine("" + i + "");
12                     c.Close();
19                 }
20             }
21             catch (Exception ex)
22             {
23                 Console.WriteLine(ex.Message);
24             }
25             Console.ReadLine();
26         }
27     }

 以上写法虽然可以解决此问题,但是还不够完善,如果服务调用异常,将直接跳过c.Close().可更改如下

 1 class Program
 2     {
 3  4         static void Main(string[] args)
 5         {
 6             WB.InSideContract_WebSiteClient wc = new WB.InSideContract_WebSiteClient();
 7             try
 8             {
 9                 10 11                     SR.TestClient c = new SR.TestClient();
12                     string res = c.Login("张三", "123", "", "");
13                     14                     c.Close();
15 16             }
17             catch (Exception ex)
18             {
19                 Console.WriteLine(ex.Message);
20                 Console.WriteLine(ex.InnerException.Message);
21                 wc.Abort();
22             }
23             Console.ReadLine();
24         }
25     }
原文地址:https://www.cnblogs.com/yf2011/p/4466403.html