您的位置:首页 > 其它

(五)、WCF中的行为

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

实例管理 通过ServiceBehavior特性的InstanceContextMode属性进行设置,

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代表了会话的实例管理模式。需要满足三方面的要求才能在客户端和服务端之间建立会话。

服务契约的会话设置

服务行为的实例模式设置

绑定的设置



(会话调用流程)

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

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实例策略:类似于设计模式的单件模式,所以的客户端代理消息都会发送到同一个服务器的实例上。



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方法被调用");
}
}
}


并发管理 包含了如果管理被关联到同一服务实例上的不同消息,可以理解为多线程:

2.1 并发管理的设置(ConcurrencyMode)是枚举类型

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


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

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模式的死锁问题:当服务回调客户端操作时,返回消息将导致死锁。死锁原因:

在signle模式下回调客户端操作,如有返回消息将发生死锁

单例的服务端操作内调用其他服务,并且通过调用链返回服务本身。(?)

客户端代理被同一个应用程序域的其他服务引用,导致调用链返回到服务本身。(?)

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 HTTP—GET方式发布元数据

<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终结点发布元数据

WCF为MEX终结点提供了基于不同通信协议的专门绑定,如mexTcpBinding、mexNamedPipeBinding、mexHttpBinding

事物管理

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 事物的流动:事务有途径的从一个服务传到另外一个服务之中。

满足条件:

设置绑定启动事务流动

设置操作契约启用事务流动

<binding name="myBinding" transctionFlow="true"></binding> // 绑定事务流动

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

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


代码见后附件

4.4 事务协议和事务管理器

轻量级协议(LightWeight Protocol)不能跨域服务边界,适用于统一应用程序域的单服务事务,性能是最好的

OleTx协议:基于windows操作的事务协议,不能说、穿越防火墙

WSAT协议,是web服务的标准协议,跨平台,穿越防火墙。

事务管理器:

轻量级事务管理器LTM:

核心事务管理器KTM

分布式事务协调器DTC

代码下载
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: