WCF开发时如何选择正确的实例模式(InstanceMode

系统 1796 0
在使用WCF实例模型时,你是否思考过这几个的问题:
  • ”WCF中的实例模式如何正确应用”?
  • ”使用WCF中的实例模式有何原则可以遵循吗”? 


众所周知:客户端调用服务时,最终会将调用服务端的某个实例来完成。在WCF服务中,可以通过ServiceBehavior的InstanceContextMode设置服务实例。

InstanceContextMode定义如下:

  //  摘要:
    
//      指定可用来处理包含在传入消息中的调用的服务实例数。
     public   enum  InstanceContextMode
    {
         //  摘要:
        
//      为每个会话创建一个新的 System.ServiceModel.InstanceContext 对象。
        PerSession =  0 ,
         //
        
//  摘要:
        
//      新的 System.ServiceModel.InstanceContext 对象在每次调用前创建,在调用后回收。如果信道未创建会话,则该值的行为就如同
        
//      System.ServiceModel.InstanceContextMode.PerCall 一样。
        PerCall =  1 ,
         //
        
//  摘要:
        
//      只有一个 System.ServiceModel.InstanceContext 对象用于所有传入呼叫,并且在调用后不回收。如果服务对象不存在,则创建一个。
        Single =  2 , } 

既然InstanceContextMode有三个枚举值,那就说明WCF服务端的实例有三种表现形式。那在平时的开发过程中,我们应遵循什么样的原则来采用哪种实例模式。? 

首先看看在三种实例模式下,服务端实例具有怎样的表现。 

服务实现:在服务的构造函数中,初始化计数器,进行服务调用时,将计数器进行累加输出。如下:

private   int  _counter;
public  AddService()
{
    _counter =  0 ;
    Console.WriteLine( " Single Mode " );
}

public   int  Add( int  x,  int  y)
{
     Console.WriteLine( " Start invoke... " );
     Console.WriteLine( " Invoke Thread Id is {0} " , System.Threading.Thread.CurrentThread.ManagedThreadId);           
     _counter++;
     Console.WriteLine( " counter is :{0} " , _counter);
      return  x + y;
}


 

1、各种实例模式的表现  

PerCall模式

客户端调用时,服务端输出如下:

WCF开发时如何选择正确的实例模式(InstanceMode)?  

可以看出: PerCall 模式下,每次进行服务调用,实例都会进行初始化,并且实例销毁与服务调用是同一个线程完成的。 

PerSession模式  

客户端调用时,服务端输出如下:

WCF开发时如何选择正确的实例模式(InstanceMode)?  

 可以看出: PerSession模式下,每次进行服务调用,实例都会进行初始化,但是对与每个代理,服务会使用同一个实例对象来为客户端服务。注意:同一客户端值的是同一个代理对象(透明代理),而不是计算机

使用会话模式有三个要求:1、使用支持会话的绑定 ;2、契约为会话契约;3、实例模式为:PerSession

Single模式   

客户端调用时,服务端输出如下:

         WCF开发时如何选择正确的实例模式(InstanceMode)?

 可以看出: Single模式下,所有客户端共享同一个服务实例对象。
 

  2、如何选择服务实例模型

 要选择服务实例模型,首先看看这三种模型各有什么优缺点:

PerCall:  

优点:对于客户端调用来说,服务不用每次为服务的调用进行状态的同步,因为每次进行服务调用都会要求服务重新进行资源分配;能够对客户端的并发调用即使响应。只有在并发调用的时候,服务端才会在内存中创建和维护多个服务实例。在进行服务调用时,客户端仅仅持有服务的代理,而不会占用实际的资源,只有在发生服务调用时,才会获取资源。

缺点:对并行的调用需要自己进行线程同步;由于每次调用都需要重建资源的状态,对性能有一定的影响。 

PerCall模式下,即使不停的创建于销毁服务实例,也不会释放与客户端的连接。因为建立连接远比服务实例的创建于销毁所需资源要多的多。

 

PerSession:

 

优点:服务端能识别不同的客户端代理,能为相同的客户端分配同一个实例,这个实例对象会一直保持,直到会话的结束。

缺点:整个会话期间,占用服务器资源,因此无法支持过多的客户端,因为创建服务实例代价比较大;与客户端、服务器模式一样存在可伸缩性的问题。

维持服务端与客户端的会话,WCF依靠传输层会话或者通过ws*绑定来模拟传输层会话。

 

 

    Single:

优点:无需考虑线程的同步问题,客户端对服务的调用是排队进行的,服务一次只能为一个客户端进行处理,处理完成后才能进行为下一个客户端服务。

缺点:由于是串行的方式为客户端服务,所以效率比较低。服务的可伸缩性限制比较大

 

3、设计服务  

3.1、 PerCall模式

设计单调服务(PerCall模式时):虽然可以应用在任一服务上,但是在设计此类服务时还是应该注意到一些问题:由于客户端不用关心服务端实例模型,PerCall模式下,服务也是每次都为客户端端的调用分配新的实例对象,调用完成后就销毁实例,因此客户端需要进行一些状态管理。 为此,客户端在进行服务调用时,服务端实例对象实例化时需要从存储介质中获取状态,那么每个操作对都应该有只是一个参数,在进行服务调用时,通过参数来初始化状态。

示例:

 

      [ServiceBehavior(InstanceContextMode = InstanceContextMode.PerCall)]

    public class  OrderService : IOrder,IDisposable

    {
         private   int  _counter;

         public  OrderService()
        {
            _counter =  0 ;
            Console.WriteLine( " perCall Mode " );
            Console.WriteLine( " counter is {0} " , _counter);
        }

         #region  IOrder Members

         public   void  Order( string  orderId)
        {                       
             int  amount = GetStore(orderId);
            UpdateStore(amount - order.Number);
        }

         #endregion

         private   int  GetStore( string  orderId)
        {
             string  connectionString = ConfigurationManager.AppSettings[ " connectionString " ];
             using  ( var  connection =  new  SqlConnection(connectionString))
            {
                connection.Open();
                  // 获取库存数量信息
                 return   int ;
            }
        }

         private   void  UpdateStore( int  p)
        {
             string  connectionString = ConfigurationManager.AppSettings[ " connectionString " ];
             using  ( var  connection =  new  SqlConnection(connectionString))
            {
                connection.Open();
                 //  将库存信息更新到数据库                
            }
        }


         public   void  Dispose()
        {
             // 释放资源
        }
    }

 

  3.2、PerSession模式

使用PreSession模式时,即使WCF在一个服务实现中,将服务实现的多个契约定义为会话或者非会话模式,但最好使用一致性配置,即所有契约都支持会话,避免将不同模式的服务定义在一个服务实现中。 

3.3、Single模式  

Single模式的服务于可伸缩性有着剧烈的冲突。Single模式的服务所有的客户端代理均使用同一个服务实例,WCF服务保证了服务状态的同步性。存在并发性访问比较高的情况下,它带来的是性能的严重下降。 只有在应用场景中适用单例的时候使用它。通常,应尽可能的使用其他方案来使状态同步,尽量避免使用Single模式.

后记:读《WCF 服务编程》后的对实例模式的重新认识。 

WCF开发时如何选择正确的实例模式(InstanceMode)?


更多文章、技术交流、商务合作、联系博主

微信扫码或搜索:z360901061

微信扫一扫加我为好友

QQ号联系: 360901061

您的支持是博主写作最大的动力,如果您喜欢我的文章,感觉我的文章对您有帮助,请用微信扫描下面二维码支持博主2元、5元、10元、20元等您想捐的金额吧,狠狠点击下面给点支持吧,站长非常感激您!手机微信长按不能支付解决办法:请将微信支付二维码保存到相册,切换到微信,然后点击微信右上角扫一扫功能,选择支付二维码完成支付。

【本文对您有帮助就好】

您的支持是博主写作最大的动力,如果您喜欢我的文章,感觉我的文章对您有帮助,请用微信扫描上面二维码支持博主2元、5元、10元、自定义金额等您想捐的金额吧,站长会非常 感谢您的哦!!!

发表我的评论
最新评论 总共0条评论