[转]WCF分布式事务

WCF 支持分布式事务,也就是说事务可以跨越服务、进程、机器边界,在多个服务和客户端间存在。

Single service/single resource transaction
uploads/200705/02_105023_wcftrans1.gif


Distributed transactional service-oriented application
uploads/200705/02_105028_wcftrans2.gif


Transaction Binding

只有 TCP-、 IPC- 以及 WS-related 等 Binding 支持事务。缺省情况下,这些 Binding 并不会参与事务,需要我们显示将 TransactionFlow 属性设置为 true 才行。
 
NetTcpBinding tcpBinding = new NetTcpBinding( );
tcpBinding.TransactionFlow 
= true;

 

<bindings>
  
<netTcpBinding>
    
<binding name = "TransactionalTCP" transactionFlow = "true" />
  
</netTcpBinding>
</bindings>

 

 

TransactionFlow 并不会在 Metadata 中发布,也就是说我们同样需要手动设置客户端 Binding 的 TransactionFlow 属性。
代码
WSHttpBinding binding = new WSHttpBinding();
binding.TransactionFlow 
= true;

ChannelFactory
<IContract> factory = new ChannelFactory<IContract>(binding,  "http://localhost:8080/myservice");
IContract client 
= factory.CreateChannel();
using (client as IDisposable)
{
  
using (TransactionScope scope = new TransactionScope())
  {
    client.Test();
    scope.Complete();
  }

 

启用可靠性(Reliability)通讯有助于减少事务失败的可能性,如果使用 NetTcpBinding、WSHttpBinding,建议做如下设置,以便启用可靠性传输。而 NetNamedPipeBinding 和 WSDualHttpBinding 默认就是可靠性,则无需再做调整。
NetTcpBinding binding = new NetTcpBinding();
binding.ReliableSession.Enabled 
= true;

 

Transaction Protocols


WCF 使用不同的事务管理协议来控制事务执行范围(execution scope)。
  • Lightweight: 仅能在同一程序域的上下文中传递事务,无法跨越程序域和服务边界。只能在服务内部或外部适用,同时它也是性能最好的一种协议。不过这种协议似乎没什么用处,因为 WCF Framework 中没有任何一种 Binding 支持此协议。
  • OleTx: 允许事务跨越程序域、进程或机器边界。使用 RPC 调用,采取 Windows 专用二进制格式。无法跨越防火墙,也不能和其他异种平台进行整合。多用于 Windows 体系的 Intranet 环境。
  • WS-Atomic(WSAT): 和 OleTx 相似,同样允许事务跨越程序域、进程或机器边界。和 OleTx 不同,WSAT 是一种工业标准,采取 HTTP 协议,TEXT 编码,可以跨越防火墙。虽然 WSAT 也能用于 Intranet,但多数时候它用于 Internet 环境。
NetTcpBinding tcpBinding = new NetTcpBinding( );
tcpBinding.TransactionFlow 
= true;
tcpBinding.TransactionProtocol 
= TransactionProtocol.WSAtomicTransactionOctober2004;



代码
<bindings>
  
<netTcpBinding>
    
<binding name = "TransactionalTCP"
      transactionFlow 
= "true"
      transactionProtocol 
= "WSAtomicTransactionOctober2004"
      
/>
  
</netTcpBinding>
</bindings>

 

Transactional Service

除了开启 Binding 的事务支持外,我们还必须通过 TransactionFlow 和 TransactionScopeRequired 来控制服务是否参与和使用事务。

TransactionFlowAttribute 只能用于服务方法(Operation/Method)上,它允许我们进行不同的事务参与设置。有一点要注意,我们不能为 IsOneWay=true 的服务设置事务支持。

  • TransactionFlowOption.NotAllowed: 不参与任何事务。(默认值)
  • TransactionFlowOption.Allowed: 允许参与事务。也就是说,如果调用方(客户端)和服务Binding启用了事务,则参与。
  • TransactionFlowOption.Mandatory: 强制启用事务。调用方(客户端)和服务 Binding 必须启用事务才能调用本服务。
"TransactionScopeRequired=true" 指示服务方法使用环境事务(ambient transaction)。
代码
[ServiceContract]
public interface IService
{
  [OperationContract]
  [TransactionFlow(TransactionFlowOption.Allowed)]
  
void Test();
}

public class Service : IService 
{
  [OperationBehavior(TransactionScopeRequired
=true)]
  
public void Test()
  {
    Transaction transaction 
= Transaction.Current;
    Debug.Assert(transaction 
== null);
  }
}

 


Transaction modes

我们可以将事务分为三种类型,分别是 Client/Service transaction、Client transaction、Service transaction。

1. Client/Service transaction,最常见的一种事务模型,通常由客户端或服务本身启用一个事务。

设置步骤:
(1) 选择一个支持事务的Binding,设置 TransactionFlow = true。
(2) 设置 TransactionFlow(TransactionFlowOption.Allowed)。
(3) 设置 OperationBehavior(TransactionScopeRequired=true)。

2. Client transaction,强制服务必须参与事务,而且必须是客户端启用事务。

设置步骤:
(1) 选择一个支持事务的Binding,设置 TransactionFlow = true。
(2) 设置 TransactionFlow(TransactionFlowOption.Mandatory)。
(3) 设置 OperationBehavior(TransactionScopeRequired=true)。

3. Service transaction,服务必须启用一个根事务,且不参与任何外部事务。

设置步骤:
(1) 选择任何一种Binding,设置 TransactionFlow = false(默认)。
(2) 设置 TransactionFlow(TransactionFlowOption.NotAllowed)。
(3) 设置 OperationBehavior(TransactionScopeRequired=true)。
posted @ 2010-05-23 10:10  黑羽飘舞  阅读(383)  评论(0编辑  收藏  举报