本文在IT168已发表:http://tech.it168.com/msoft/2007-10-25/200710251312468.shtml

分步操作

WCF提供了一种被称之为分步操作(Demarcating Operation)的方法,以应对服务契约的操作需要指定执行顺序的情况。分步操作是使用OperationContract特性的IsInitiating和IsTerminating属性:
[AttributeUsage(AttributeTargets.Method)]
public sealed class OperationContractAttribute : Attribute
{
   public bool IsInitiating
   {get;set;}
   public bool IsTerminating
   {get;set;}
   //More members
}

一个分步操作的应用如下:
[ServiceContract(SessionMode = SessionMode.Required)]
interface IOrderManager
{
   [OperationContract]
   void SetCustomerId(int customerId);

[OperationContract(IsInitiating = false)]
   void AddItem(int itemId);

[OperationContract(IsInitiating = false)]
   decimal GetTotal(  );

[OperationContract(IsInitiating = false,IsTerminating = true)]
   bool ProcessOrders(  );
}
此时,操作AddItem()、GetTotal()以及ProcessOrder()都不能是启动会话的第一个操作。同时,ProcessOrder()操作则会成为终止会话的操作。这与业务的要求是一脉相承的。

IsInitiating属性的默认值为true,IsTerminating属性的默认值则为false。

如果IsInitiating值为true,并不必然代表该操作必然是启动会话的第一个操作。如果其它相同设置的操作首先被调用,就会启动一个会话,而原操作则在调用时被加入会话,成为会话的一部分。但如果IsTermination的值为true,则代表该操作必须是终止会话的操作。虽然在服务契约定义时,允许将多个操作的IsTerminating值设置为true,但一旦调用了IsTerminating值为true的方法,就不能再调用服务实例的其它方法,除非在客户端重新创建一个代理对象。此外,即使操作的IsTermination值为true,它也可以是启动会话的第一个操作,但在操作执行后它会终止会话。因此,如下的两个操作定义是等效的:
[OperationContract(IsTerminating = true)]
void StartAndEndSession();
[OperationContract(IsInitiating=true, IsTerminating = true)]
void StartAndEndSession();

然而,如下的两个操作则是不等效的,因为后者要求该操作不能为启动会话的第一个操作:
[OperationContract(IsTerminating = true)]
void StartAndEndSession();
[OperationContract(IsInitiating=false, IsTerminating = true)]
void StartAndEndSession();

实例停用(Instance Deactivation)

实例停用只针对会话服务而言。单例服务虽然也可以应用,但却无效。

“会话实际要做的不仅是关联客户端消息,同时还要关联托管了服务的上下文。启动会话时,宿主会创建一个新的上下文。会话终止时,上下文也随之而终止。默认情况下,上下文的生命周期与发布的服务实例的生命周期相同。然而,出于优化的目的,WCF为服务设计者提供了一个分离两种生命周期的选项,该选项允许WCF独立地停用实例,而不必依赖于它的上下文。实际上,WCF还允许不包含实例的上下文存在,如下图所示。”

这种实例管理技术称为上下文停用(Context Deactivation)。控制上下文停用的最常见办法是通过OperationBehavior特性的ReleaseInstanceMode属性:
public enum ReleaseInstanceMode
{
   None,
   BeforeCall,
   AfterCall,
   BeforeAndAfterCall,
}
[AttributeUsage(AttributeTargets.Method)]
public sealed class OperationBehaviorAttribute : Attribute,...
{
   public ReleaseInstanceMode ReleaseInstanceMode
   {get;set;}
   //More members
}

“通常,我们只需要将实例停用应用到部分服务方法上,而不是全部方法;或者为不同的方法设置不同的值。”例如:
class MyService : IMyContract,IDisposable
{
   [OperationBehavior(ReleaseInstanceMode = ReleaseInstanceMode.AfterCall)]
   public void MyMethod(  )
   {...}
   public void MyOtherMethod(  )
   {...}
   public void Dispose(  )
   {...}
}

ReleaseInstanceMode属性的默认值为ReleaseInstanceMode.None。关于ReleaseInstanceMode属性值,以下四张图片足以说明它们的工作方式:
 
ReleaseInstanceMode.None


ReleaseInstanceMode.BeforeCall

 
ReleaseInstanceMode.AfterCall

 
ReleaseInstanceMode.BeforeAndAfterCall

准确地选择ReleaseInstanceMode,可以有效地提高系统的性能,优化内存以及资源的利用。

除了可以通过应用OperationBehaviorAttribute应用ReleaseInstanceMode,也可以通过编程方式在服务的操作中显式地完成对实例的停止。方法是利用InstanceContext的ReleaseServiceInstance()方法:
class MyService : IMyContract,IDisposable
{
   public void MyMethod(  )
   {
      //Do some work then
      OperationContext.Current.InstanceContext.ReleaseServiceInstance(  );
   }
   public void Dispose(  )
   {...}
}

这两种实现实例停止的方式还可以结合使用,例如在应用了OperationBehavior特性,并将ReleaseInstanceMode设置为BeforeCall的方法中,如果显式调用ReleaseServiceInstance()方法,其效果就相当于将ReleaseInstanceMode设置为BeforeAndAfterCall。

限流(Throttling)

限流“允许开发者限制客户端连接数以及服务的负荷。限流可以避免服务的最大化,以及分配与使用重要资源的最大化。引入限流技术后,一旦超出配置的设置值,WCF就会自动地将等待处理的调用者放入到队列中,然后依次从队列中取出。在队列中等待处理调用时,如果客户端的调用超时,客户端就会获得一个TimeoutException异常。每个服务类型都可以应用限流技术,也就是说,它会影响到服务的所有实例以及服务类型的所有终结点。实现方式是为限流与服务使用的每个通道分发器建立关联。”

限流由ServiceThrottlingBehavior类定义,包括三个重要的属性:MaxConcurrentCalls、MaxConcurrentSessions、MaxConcurrentInstances,它们分别的默认值为16,10和Int.MaxValue。

在翻译过程中,我在查阅MSDN时,发现MaxConcurrentSessions的默认值为64,这让我感觉很奇怪,莫非作者在这里出现了错误。然而经过我仔细地查阅相关资料,发现在WCF的早期版本中,MaxConcurrentSessions的默认值确实为64,但在2006年6月的CTP版本中已经被修改为16。

设置限流值可以通过配置文件,也可以通过编码方式。前者例如:
<system.serviceModel>
   <services>
      <service name = "MyService" behaviorConfiguration = "ThrottledBehavior">
         ...
      </service>
   </services>
   <behaviors>
      <serviceBehaviors>
         <behavior name = "ThrottledBehavior">
            <serviceThrottling
               maxConcurrentCalls     = "12"
               maxConcurrentSessions  = "34"
               maxConcurrentInstances = "56"
            />
         </behavior>
      </serviceBehaviors>
   </behaviors>
</system.serviceModel>

WCF并没有提供关于限流的特性。但实现该特性的方法非常简单,如下内容是我定义的关于限流的特性,本书并没有提供:
    public class ServiceThrottlingAttribute : Attribute, IServiceBehavior
    {
        private ServiceThrottlingBehavior throttle;

public ServiceThrottlingAttribute(
          int maxConcurrentCalls,
          int maxConcurrentInstances,
          int maxConcurrentSessions)
        {
            this.throttle = new ServiceThrottlingBehavior();
            throttle.MaxConcurrentCalls = maxConcurrentCalls;
            throttle.MaxConcurrentInstances = maxConcurrentInstances;
            throttle.MaxConcurrentSessions = maxConcurrentSessions;
        }

#region IServiceBehavior Members

void IServiceBehavior.AddBindingParameters(ServiceDescription serviceDescription,
ServiceHostBase serviceHostBase,
System.Collections.ObjectModel.Collection<ServiceEndpoint> endpoints,
System.ServiceModel.Channels.BindingParameterCollection bindingParameters)
        { }

void IServiceBehavior.ApplyDispatchBehavior(ServiceDescription serviceDescription,
ServiceHostBase serviceHostBase)
        {
            ServiceThrottlingBehavior currentThrottle = serviceDescription.Behaviors.Find<ServiceThrottlingBehavior>();
            if (currentThrottle == null)
            {
                serviceDescription.Behaviors.Add(this.throttle);
            }
        }

void IServiceBehavior.Validate(ServiceDescription serviceDescription,
 ServiceHostBase serviceHostBase)
        {  }

#endregion
    }

定义的ServiceThrottlingAttribute特性继承了Attribute,并实现了IServiceBehavior接口。在特性内,则使用了ServiceThrottlingBehavior类,以设置限流的相关值。如果要配置服务的限流值,就可以应用该特性,例如:
[ServiceThrottling(12, 34, 56)]
class MyService : IMyContract,IDisposable
{
     public void MyMethod(  )
     {
        ChannelDispatcher dispatcher = OperationContext.Current.Host.ChannelDispatchers[0] as ChannelDispatcher;
        ServiceThrottle serviceThrottle = dispatcher.ServiceThrottle;
        
        Trace.WriteLine("MaxConcurrentCalls = " + serviceThrottle.MaxConcurrentCalls);
        Trace.WriteLine("MaxSessions = " + serviceThrottle.MaxConcurrentSessions);
        Trace.WriteLine("MaxInstances = " + serviceThrottle.MaxConcurrentInstances);
     }
}

则输出结果为:
MaxConcurrentCalls = 12
MaxSessions = 56
MaxInstances = 34

转载于:https://www.cnblogs.com/wayfarer/archive/2007/11/12/956561.html

Programming WCF Services翻译笔记(八)相关推荐

  1. Programming WCF Services翻译笔记(四)

    本书的第2章主要讲解了服务契约.内容:"本章首先会讨论如何通过操作重载与契约层级,为两种迥然不同的编程模型建立关联.然后,本章会介绍一些简单而又强大的设计和分离服务契约的技术与指导原则.在本 ...

  2. Programming WCF Services翻译笔记(五)

    本书的第3章主要讲解了有关数据契约的知识."从抽象层面看,WCF能够托管CLR类型(接口和类)并将它们公开为服务,也能够以本地CLR接口和类的方式使用服务.WCF服务的操作接收和返回诸如in ...

  3. Programming WCF Services 学习笔记四、Instance Management

        1.         Behaviors i.              Service的实例模型是客户端无关的,即Client端不会知道Service的实例模型,Service的实例模型也不 ...

  4. [Programming WCF Services]Chapter 1. WCF Essentials - Metadata Exchange

    1.HTTP-GET WCF 方式 通过Http的方式提供metadata 1.1.配置文件方式 <system.serviceModel><services><serv ...

  5. 《Programming WPF》翻译 目录

    原文:<Programming WPF>翻译 目录 注:第1.2章我只做了笔记,没有翻译,请大家阅读时注意. 还有就是,这本书的英文版本下载:[O'Reilly] Programming ...

  6. 《The C Programming Language》读书笔记 说明

    <The C Programming Language>读书笔记 说明 作为笔记而言,完全是一种自写自看的行为,本来是没有必要写这篇东西的.但是作为一个生活在网络时代的学 生来说,想学好一 ...

  7. 黑马程序员_java自学学习笔记(八)----网络编程

    黑马程序员_java自学学习笔记(八)----网络编程 android培训. java培训.期待与您交流! 网络编程对于很多的初学者来说,都是很向往的一种编程技能,但是很多的初学者却因为很长一段时间无 ...

  8. 《iOS5 programming cookbook》学习笔记1

    <iOS5 programming cookbook>学习笔记 看到这个同学的这篇文章,把它下了下来,粗粗一看觉得不错,正好进阶一下.我也写个笔记,每章一篇. 这位同学真好学啊,有新东西学 ...

  9. 《Programming WPF》翻译 第7章 3.笔刷和钢笔

    原文:<Programming WPF>翻译 第7章 3.笔刷和钢笔 为了在屏幕上绘制一个图形,WPF需要知道你想要为图形填充什么颜色以及如何绘制它的边框.WPF提供了一些Brush类型支 ...

  10. Programming Entity Framework-dbContext 学习笔记第五章

    ### Programming Entity Framework-dbContext 学习笔记 第五章 将图表添加到Context中的方式及容易出现的错误 方法 结果 警告 Add Root 图标中的 ...

最新文章

  1. java spring框架怎么学_JAVA学习之路~spring框架(一)
  2. powerdesigner奇淫技
  3. 《Drupal实战》——3.3 使用Views创建列表
  4. CentOS安装SonarQube7.9.1
  5. 嵌入式工程师有发展前途吗?这是我看过最靠谱的回答
  6. Android开发之AudioManager(音频管理器)详解
  7. Spark:聚类算法之LDA主题模型算法
  8. 【语音编码】基于matlab LPC编解码【含Matlab源码 554期】
  9. 基于Java Web的随意购商城系统(开源项目)
  10. 智能药盒的设计与实现
  11. 自动驾驶技术基础——惯导
  12. java五个数以升序排列,java4个数的数组排列
  13. 【工作笔记】004 tapestry框架
  14. Atitit 手机号码选号 规范 流程 attilax总结 v2 r99.docx
  15. 步进电机c语言驱动原理,《步进电机【驱动电路+C语言驱动程序】》.doc
  16. 字节跳动 录屏功能_免费屏幕录制软件有哪些?原来这么多
  17. ORA-01119、ORA-27040的两种可能存在的错误
  18. [SSL: CERTIFICATE_VERIFY_FAILED]
  19. windows常用脚本bat合集
  20. 十款强大的图像后期处理软件和工具

热门文章

  1. java代码用户界面网格布局GridLayout.划分为格子区域
  2. 用Windows Live Writer写51cto博客
  3. wince下的地址映射知识点滴
  4. 计算机网络考前,《计算机网络原理》--考前复习资料.doc
  5. 接入TapTap防沉迷系统的逻辑图
  6. C# Linq以及反射总结
  7. datetime 比较_MySQL时间类型datetime,timestamp,int如何选择,很多程序员收藏了
  8. 程序员让开,硅谷将是物理学家的天下,薪水高得离谱
  9. 一个简单的倒计时js插件
  10. 【转】vim ctag使用方法