wcf(3) 基于会话的客户端及异常处理

(一)ChannelFactory<T>的缓存机制


ChannelFactory<T>是一个复杂费时的工作,wcf内部使用缓存机制提高服务调用性能


 CalculatorClient proxy1 = new CalculatorClient("calculatorservice");

 proxy1.Open();

 CalculatorClient proxy2 = new CalculatorClient("calculatorservice");

 proxy2.Open();

 Console.WriteLine(object.ReferenceEquals(proxy1.ChannelFactory, proxy2.ChannelFactory));

 结果是true,证明两个ChannelFactory是同一个对象


破坏缓存机制的两种方式:

1。在构造函数中传入绑定的对象构建ClientBase<T>

2。在ClientBase<T>.Open之前,访问三个只读属性:ChannelFactory,Endpoint,ClientCredential



(二)基于会话信道的客户端

wcf的信道分为两种:

1。会话信道

    它确保客户端与服务端之间消息能够相互关联,但是信道的错误(Fault)会影响后续的消息交换

2。数据报信道

    即使同一数据报信道中,每次消息交互都是相互独立的,信道的错误也不会影响后续的消息交换


绝大部分绑定类型(BasicHttpBinding除外),默认情况下创建的都是会话信道。


(三)服务契约的关闭与并发会话的限制 


maxConcurrentCalls

maxConcurrentInstances

maxConcurrentSessions      =5


以上最大会话数量为5的情况下:

下面代码会报超时错误,但是要配合  

<binding name="myWsHttpBind" sendTimeout="00:00:10" 

receiveTimeout="00:00:10" openTimeout="00:00:10"/>


 static void timeoutTest()

        {

            Binding binding = new WSHttpBinding();

            EndpointAddress address = new EndpointAddress("http://127.0.0.1:9999/calculatorservice");

            ChannelFactory<ICalculator> channelFactory =

                  new ChannelFactory<ICalculator>(binding, address);


            for (int i = 1; i <= 20; i++)

            {

                try

                {

                    ICalculator calculator = channelFactory.CreateChannel();

                    Console.WriteLine($"{i}:x+y={calculator.Add(1, 2)} when x={1} and y={2}");


                }

                catch (Exception ex)

                {

                    Console.WriteLine($"{i}t:{ex.Message}");

                }

            }


            Console.ReadKey();

        }

 

解决这个问题,除了设置maxConcurrentSessions的大小,最根本的在于:

服务代理不用的情况下,应该及时关闭。这样基于服务代理对象的会话也会关闭。



上面谈的是最大会话限,对于非会话信道是否也有限制呢?


但是这个例子出错了:

12t:无法处理消息。这很可能是因为操作“http://www.artech.com/CalculatorService/Add”

不正确,或因为消息包含无效或过期的安 全上下文令牌,

或因为绑定之间出现不匹配。如果由于未处于活动状态导致服务中止了该通道,

则安全上下文令牌无效。若要防止服务永久中止闲置会话,请增加服务终结点绑定上的接收超时。


只要设置客户端的安全模式后,就会报错:

Binding binding = new WSHttpBinding(SecurityMode.None);



(四)会话信道与异常处理


调用除法方法时,如果除数为0,则服务端抛出DivideByZeroException异常,

当前信道的状态变成Faulted,表示信道错误。

错误的信道不能继续用于后续的通信,即使调用Close方法试图将期关闭也不行。

这种情况下会调用另一个方法:Abort,强行中断当前信道。


对于客户端来说,信道在下面两种情况下状态会变成Faulted

。调用超时,抛出TimeoutException

。调用失败,抛出CommunicationException


正确的处理服务调用代码应该是:

try

{

   int result=calculator.Divide(1,0);

   (calculator as ICommunicationObject).Close();

}

catch(CommunicationException ex)

{

  (calculator as ICommunicationObject).Abort();

}

catch(TimeoutException ex)

{

  (calculator as ICommunicationObject).Abort();

}

catch(Exception ex)

{

}



(五)通过AOP的方式解决会话信道的关闭与中断


性能与并发的权衡


由于信道的创建与释放都是一件相对耗时的操作,所以从性能上来讲,

我们鼓励服务代理对象(或者说是信道)的重用。

但是,服务代理重用就意味着信道一直保持开启的状态,

这样信道可能会达到服务端所允许的最大并发会话量,后续的请求就阻塞了,

所以从并发的角度,我们又不主张服务代理的重用。

这就是性能和可扩展性不可能同时兼得的问题。软件设计就是要在这两方面找一个平衡点。




本文出自勇哥的网站《少有人走的路》wwww.skcircle.com,转载请注明出处!讨论可扫码加群:
本帖最后由 勇哥,很想停止 于 2024-06-14 16:13:29 编辑

发表评论:

◎欢迎参与讨论,请在这里发表您的看法、交流您的观点。

会员中心
搜索
«    2025年4月    »
123456
78910111213
14151617181920
21222324252627
282930
网站分类
标签列表
最新留言
    热门文章 | 热评文章 | 随机文章
文章归档
友情链接
  • 订阅本站的 RSS 2.0 新闻聚合
  • 扫描加本站机器视觉QQ群,验证答案为:halcon勇哥的机器视觉
  • 点击查阅微信群二维码
  • 扫描加勇哥的非标自动化群,验证答案:C#/C++/VB勇哥的非标自动化群
  • 扫描加站长微信:站长微信:abc496103864
  • 扫描加站长QQ:
  • 扫描赞赏本站:
  • 留言板:

Powered By Z-BlogPHP 1.7.2

Copyright Your skcircle.com Rights Reserved.

鄂ICP备18008319号


站长QQ:496103864 微信:abc496103864