(五)、WCF中的行为

 

    行为(Behaviors)指的是那些影响WCF系统运行的设置。WCF系统中的行为分为服务行为(Service behavior)和操作行为(Operation behavior).常见的服务行为包括实例控制、并发控制、元数据发布。常见的操作行为包括事物流设置。

  1. 实例管理 通过ServiceBehavior特性的InstanceContextMode属性进行设置,
  2. Public enum InstanceContextMode { PerSession = 0, PerCall = 1, Single =2 }

    1.1,  PerCall 实例策略:当服务端采用了PerCall 实例策略后,每个客户端请求的消息会被分布到一个新的服务实例上。而一旦这个调用返回之后,服务实例则被销毁。

    PerCall调用流程

    /// <summary> /// 设置实例管理 /// </summary> [ServiceBehavior(InstanceContextMode=InstanceContextMode.PerCall)] public class Service : IService,IDisposable { private int _count = 0; public void Operate() { //由于是PerCall,_count的值不会被保存 _count++; Console.WriteLine("Count的值为{0}",_count); } public void Dispose() { Console.WriteLine("Dispose方法被调用"); } }

            1.2, PerSession 实例策略和会话,Persession是默认的实例策略,Persession代表了会话的实例管理模式。需要满足三方面的要求才能在客户端和服务端之间建立会话。

  3. 服务契约的会话设置
  4. 服务行为的实例模式设置
  5. 绑定的设置
  6.  (五)、WCF中的行为_第1张图片

    (会话调用流程)

    1.2.1 服务契约的会话设置通过ServiceContractSessionMode属性设置

    Public enum SessionMode { Allowed = 0, // 默认设置,允许客户端进行会话通信 Required = 1, // 指服务端要求用会话模式,必须采用传输会话的绑定来进行消息交互,例如//netTcpBinding,NetNamedPipeBinding,服务行为仍然可以采用PerCall模式。 NotAllowed = 2 // 与Required相反 }

    [ServiceContract(SessionMode= SessionMode.Allowed] Pulic interface Iservice { [OperationContract] Void Operate(); }

    1.2.2 服务行为的实例模式设置

    1.2.3 绑定的选择,NetTcpBinding,netNamedPipeBinding使用的协议本身具有传输层会话的能力,而wsHttpBinding,虽然无会话的HTTP协议,可以在头插入会话ID来模仿传输层会话。

    using System; using System.ServiceModel; namespace WCF.Fourth { /// <summary> /// 服务契约,定义SessionMode为Allowed /// </summary> [ServiceContract(SessionMode=SessionMode.Allowed)] public interface IService { [OperationContract] void Operate(); } /// <summary> /// 设置实例管理 /// </summary> [ServiceBehavior(InstanceContextMode=InstanceContextMode.PerSession)] public class Service : IService,IDisposable { private int _count = 0; public void Operate() { //由于是PerSession,_count的值会累加 _count++; Console.WriteLine("Count的值为{0}",_count); } public void Dispose() { Console.WriteLine("Dispose方法被调用"); } } }

    1.3 Single实例策略:类似于设计模式的单件模式,所以的客户端代理消息都会发送到同一个服务器的实例上。

    (五)、WCF中的行为_第2张图片

    using System; using System.ServiceModel; namespace WCF.Fourth { /// <summary> /// 服务契约 /// </summary> [ServiceContract] public interface IService { [OperationContract] void Operate(); } /// <summary> /// 设置实例管理 /// </summary> [ServiceBehavior(InstanceContextMode=InstanceContextMode.Single)] public class Service : IService,IDisposable { public int _count = 0; public void Operate() { //由于是Single,_count的值会持续累加 _count++; Console.WriteLine("Count的值为{0}",_count); } public void Dispose() { Console.WriteLine("Dispose方法被调用"); } } }

  7. 并发管理 包含了如果管理被关联到同一服务实例上的不同消息,可以理解为多线程:
  8. 2.1 并发管理的设置(ConcurrencyMode)是枚举类型

    Public enum ConcurrencyMode { Single = 0, //默认 Reetrant = 1, Multiple =2 }

    对于PerCall模式,任何一个服务实例都是被单线程调用,不存在并发。而对于PerSessionSingle模式,一个服务实例可能被多个线程访问。

    2.1.1 Single模式:提供同步锁

    using System; using System.ServiceModel; using System.Threading; namespace WCF.Fourth { /// <summary> /// 服务契约 /// </summary> [ServiceContract] public interface IService { [OperationContract] void Operate(); } /// <summary> /// 设置并行管理, /// 为了验证并行管理,这里使用Single实例管理模式 /// </summary> [ServiceBehavior(InstanceContextMode=InstanceContextMode.Single, ConcurrencyMode=ConcurrencyMode.Single)] public class Service : IService,IDisposable { public void Operate() { Console.WriteLine("进入操作"); //延长操作执行时间 Thread.Sleep(1000 * 3); Console.WriteLine("退出操作"); } public void Dispose() { Console.WriteLine("Dispose方法被调用"); } } }

    2.1.2 Multiple并发模式。每个操作都允许客户端多个请求同时访问。提高运行效率,防止信息阻塞。

    using System; using System.ServiceModel; using System.Threading; namespace WCF.Fourth { /// <summary> /// 服务契约 /// </summary> [ServiceContract] public interface IService { [OperationContract] void Operate(); } /// <summary> /// 设置并行管理, /// 为了验证并行管理,这里使用Single实例管理模式 /// </summary> [ServiceBehavior(InstanceContextMode=InstanceContextMode.Single, ConcurrencyMode=ConcurrencyMode.Multiple)] public class Service : IService,IDisposable { public void Operate() { Console.WriteLine("进入操作"); //延长操作执行时间 Thread.Sleep(1000 * 3); Console.WriteLine("退出操作"); } public void Dispose() { Console.WriteLine("Dispose方法被调用"); } } }

    2.1.3 Reetrant 并发模式和Single模式一样,只允许一个线程访问服务操作,在访问进入操作之前必须获得同步锁。不同的是,Reetrant模式解决了Single模式的死锁问题:当服务回调客户端操作时,返回消息将导致死锁。死锁原因:

  9. signle模式下回调客户端操作,如有返回消息将发生死锁
  10. 单例的服务端操作内调用其他服务,并且通过调用链返回服务本身。(?)
  11. 客户端代理被同一个应用程序域的其他服务引用,导致调用链返回到服务本身。(?)
  12. Reentrant模式解决死锁问题,当服务操作调用其他服务或者回调时,将会释放服务端的同步锁。这样就保证服务的回调消息或者调用链不会发生死锁。

    using System; using System.ServiceModel; using System.Threading; namespace WCF.Fourth { /// <summary> /// 服务契约 /// </summary> [ServiceContract(CallbackContract = typeof(ICallback))] public interface IService { [OperationContract] void Operate(); } /// <summary> /// 回调契约 /// </summary> public interface ICallback { [OperationContract] void Callback(); } /// <summary> /// 设置并行管理为Reentrant /// </summary> [ServiceBehavior(InstanceContextMode=InstanceContextMode.Single, ConcurrencyMode=ConcurrencyMode.Reentrant)] public class Service : IService,IDisposable { public void Operate() { Console.WriteLine("{0}进入操作", DateTime.Now.ToString()); //这里进行回调,WCF会释放同步锁 ICallback callback = OperationContext.Current.GetCallbackChannel<ICallback>(); callback.Callback(); Console.WriteLine("{0}退出操作", DateTime.Now.ToString()); } public void Dispose() { Console.WriteLine("Dispose方法被调用"); } } }

    3. 元数据的发布:元数据可以视为一个服务的对外接口的描述,服务包含终结点的3要素:地址,绑定,契约

    3.1  HTTPGET方式发布元数据

    <behaviors> <serviceBehaviors> <behavior name="MyBehavior"> <serviceMetadata httpGetEnabled = "true"/> </behavior> </behaviors>

      using (ServiceHost host = new ServiceHost(typeof(Service))) { //这里添加元数据行为 ServiceMetadataBehavior metadataBehavior = host.Description.Behaviors.Find<ServiceMetadataBehavior>(); if (metadataBehavior == null) { metadataBehavior = new ServiceMetadataBehavior(); metadataBehavior.HttpGetEnabled = true; host.Description.Behaviors.Add(metadataBehavior); } host.Open(); Console.WriteLine("服务已经启动!"); Console.ReadLine(); }

    3.2 MEX终结点发布元数据

    WCFMEX终结点提供了基于不同通信协议的专门绑定,如mexTcpBindingmexNamedPipeBindingmexHttpBinding

  13. 事物管理
  14. 4.1 事物的基本概念和特性

    A(原子性-Atomicity)

    C (一致性- Consistency)事物必须从一个一致性状态到另一个一致性状态

    I (隔离性-Isolation)

    D(持续性-Durability

    4.2 单服务事物:整个事物的操作在一个服务中完成

    分布式服务:事物的操作涉及多个服务

    4.2.1 显示的使用事物类型:比如数据操作时。

    4.2.2 使用操作行为(OperationBehavior)声明事物

    using System; using System.ServiceModel; using System.Runtime.Serialization; using System.Transactions; namespace WCF.Fourth { /// <summary> /// 服务契约 /// </summary> [ServiceContract] public interface IService { [OperationContract] void SuccessOperation(); [OperationContract] void FailOperation(); [OperationContract] void Assert(); } /// <summary> /// 设置实例管理 /// </summary> [ServiceBehavior(InstanceContextMode=InstanceContextMode.Single)] public class Service : IService { private BackAccount A; private BackAccount B; public Service() { Console.WriteLine("服务实例被构造"); A = new BackAccount("A", 100); B = new BackAccount("B", 200); } /// <summary> /// 这里检验两个帐号的金额是否保持一致性 /// </summary> public void Assert() { Console.WriteLine(A); Console.WriteLine(B); Console.WriteLine("A和B帐户的和为{0}", A.Amount + B.Amount); } /// <summary> /// 使用事务 /// </summary> [OperationBehavior(TransactionScopeRequired = true, TransactionAutoComplete = true)] public void SuccessOperation() { //注册A和B为易失型事务操作 Transaction.Current.EnlistVolatile(A, EnlistmentOptions.None); Transaction.Current.EnlistVolatile(B, EnlistmentOptions.None); A.Add(-50); B.Add(50); } /// <summary> /// 使用事务 /// </summary> [OperationBehavior(TransactionScopeRequired = true, TransactionAutoComplete = true)] public void FailOperation() { //注册A和B为易失型事务操作 Transaction.Current.EnlistVolatile(A, EnlistmentOptions.None); Transaction.Current.EnlistVolatile(B, EnlistmentOptions.None); A.Add(-50); //这里模拟产生异常 throw new FaultException(); B.Add(50); } } /// <summary> /// 帐号类型,这是一个易失型事务资源 /// </summary> [DataContract] public class BackAccount : IEnlistmentNotification { [DataMember] public String Name; [DataMember] public double Amount; private double _newAmount; public BackAccount(String name, double amount) { Name = name; Amount = amount; } public override string ToString() { return Name + "的账户:" + Amount.ToString(); } public void Adjust(double newAmount) { _newAmount = newAmount; } public void Add(double amount) { double newAmount = Amount + amount; Adjust(newAmount); } /// <summary> /// 提交操作 /// </summary> public void Commit(Enlistment enlistment) { Amount = _newAmount; enlistment.Done(); Console.WriteLine("{0}已提交", Name); } public void InDoubt(Enlistment enlistment) { throw new Exception(); } public void Prepare(PreparingEnlistment enlistment) { enlistment.Prepared(); } /// <summary> /// 回滚操作 /// </summary> public void Rollback(Enlistment enlistment) { enlistment.Done(); Console.WriteLine("{0}已回滚", Name) } } } 4.3 分布式事务:一个事物有多个服务完成

    4.3.1 两段提交协议:事务协调器和多个事务组成

    4.3.2 事物的流动:事务有途径的从一个服务传到另外一个服务之中。

    满足条件:

  15. 设置绑定启动事务流动
  16. 设置操作契约启用事务流动
  17. <binding name="myBinding" transctionFlow="true"></binding> // 绑定事务流动

    操作事务流动通过声明TransactionFlow特性来实现。

    Public enum TransctionFlowOption { NotAllowed = 0, // 不允许事务流动 Allowed =1, //允许事务流动 Mandatory = 2 // 该操作强制需要事务流动 }

    代码见后附件

    4.4 事务协议和事务管理器

  18. 轻量级协议(LightWeight Protocol)不能跨域服务边界,适用于统一应用程序域的单服务事务,性能是最好的
  19. OleTx协议:基于windows操作的事务协议,不能说、穿越防火墙
  20. WSAT协议,是web服务的标准协议,跨平台,穿越防火墙。
  21. 事务管理器:

  22. 轻量级事务管理器LTM
  23. 核心事务管理器KTM
  24. 分布式事务协调器DTC
  25.  

    代码下载

     

     

你可能感兴趣的:(service,Class,callback,interface,WCF,behavior)