一、事务协议
总体来说,WCF开发人员不需要涉及事务协议与管理器。我们应该依赖WCF来选择相应的事务协议和管理器,重点关注业务逻辑的实现。
WCF是根据事务范围里的参与个体来选择事务管理协议的。事务管理协议之间的差别与远程调用、通行协议,以及跨越的系统边界有关。
可选择的管理协议如下:
轻量级事务协议
这个协议只在本地同一个应用程序域内的上下文环境里管理事务,他不能跨越应用程序边界来传播事务(更不能跨越进程或机器边界了),也不能跨越服务边界(从客户端到服务段)。轻量级协议只能在单个服务内部或同一个应用程序域里的两个个体间使用。与其它协议相比,轻量级协议拥有最佳的性能。
OleTx事务协议
这个协议可以跨域应用程序域、进程和机器边界来传播事务,并且可以管理两阶段提交协议。协议使用RPC调用,并且消息格式是Windows指定的二进制格式。因为这个原因,他不能跨越防火墙,也不能与非Windows平台的系统交互。这通常不能问题所在,应为OleTx进程用于Intranet里,而且是相同的Windows环境下。
WSAT事务协议
这个协议和OleTx事务协议一样,可以跨域应用程序域、进程和机器边界来传播事务,并且可以管理两阶段提交协议。但是,WSAT事务协议基于行业标准,并能够穿越防火墙。推荐在Internet上有多个事务管理器参与事务时使用这种协议。
二、协议与绑定
没有绑定支持轻量级事务协议,因为该协议无法跨域服务边界传播。TCP和IPC绑定可以配置为同时使用OleTx和WSAT事务协议,或者使用两者之一。两个绑定默认使用OlxTx事务协议,在需要的时候会切换为WSAT事务协议。
此外,这些Intranet绑定允许使用配置文件或代码来配置事务协议,这一点和其它的绑定属性一致。
WCF提供了抽象类TransactionProtocol,定义如下:
// 指定在流动事务中使用的事务处理协议。 public abstract class TransactionProtocol { // 初始化 System.ServiceModel.TransactionProtocol 类的新实例。 protected TransactionProtocol(); // 获取事务处理协议的默认值。 public static TransactionProtocol Default { get; } // 获取 OleTransactions 事务处理协议值。 public static TransactionProtocol OleTransactions { get; } // 获取 WSAtomicTransaction11 事务处理协议值。 public static TransactionProtocol WSAtomicTransaction11 { get; } // 获取 WSAtomicTransactionOctober2004 事务处理协议值。 public static TransactionProtocol WSAtomicTransactionOctober2004 { get; } }TCP和IPC都提供了TransactionProtocol属性。例如:
public class NetTcpBinding : Binding,... { TransactionProtocal TransactionProtocal { get; set } ...... }
采用编程方式设置协议,首先需要构建需要的绑定类型,然后使用某个静态方法来设置属性:
NetTcpBinding bingding = new NetTcpBinding(); //支持传播事务的协议 bingding.TransactionFlow = true; bingding.TransactionProtocol = TransactionProtocol.WSAtomicTransactionOctober2004;注意,事务协议配置只有在启用事务传播的时候才有意义。配置文件里配置事务协议如下:
当为TCP和IPC绑定配置事务协议时,服务和客户端必须使用相同的协议。由于TCP和IPC绑定只能在Intranet内部使用,因此配置为WSAT事务协议并没什么实际意义。
WS绑定(WsSHttpBinding、WS2007HttpBinding、WSDualHttpBinding等等)都是为了Internet设计的,当需要多个事务管理器协调工作时,就应该使用WSAT事务协议。但是,当Internet只有一个事务管理器时,这些绑定默认都使用OleTx事务协议。这里没必要配置特别的事务协议。
三、事务管理器
如果管理事务呢?最佳的解决方案就是使用一个名叫事务管理器的第三方来完成这个工作,由它来负责为客户端和服务端两个两阶段提交协议。
事务管理器是整个事务控制模型的核心和枢纽,是它控制着事务的所有参与者,协调整个事务从开始到完成的所有相关处理流程。事务管理器为应用和资源管理器提供一系列核心的事务性的服务,实现事务的开始、提交和回滚。Windows提供了三种不同的事务管理器,如下图所示:
上图所示的三个事务管理器就是轻量级事务管理器(LTM),核心事务管理器(KTM)和分布式事务、协调器(DTC)。作为平台使用的功能、应用程序要做的工作、调用的服务、使用的资源,.NET都会自动分配合适的事务管理器。因为分配工作是自动完成的,所以代码就看可以从事务管理和事务协议之间解耦了。再次重申,开发人员从来不需要为事务管理器烦恼。
轻量级事务管理器(LTM: Lightweight Transaction Manager)
正如其名称隐含的意思,轻量级事务管理器(以下简称LTM)具有最小的负载,是性能最高的事务管理器。
LTM的作用范围仅限于开启事务的应用程序域(AppDomain)中,并且登记到事务中的持久化资源(Durable Resource)数量不能超过一个。
一般地,被开启的事务就由LTM管理,如果事务涉及到跨应用程序域的操作,当前的事务回被奉送、传播到另一个执行上下文中,此时事务将脱离LTM的管辖。
此外,基于LTM的事务中可以同时登记(Enlist)多个易失型资源(Volatile),但是仅仅允许登记唯一一个持久化资源。当第二个持久化资源被登记到当前事务中,该事务也将脱离LTM的管辖。
如果只有单个资源管理器,并且资源支持单阶段提交协议,LTM会使用优化协议。更为重要的是,LTM只能管理单个服务内的事务,不支持事务流传播。
LTM是最小的事务管理器,它可以直接在资源上执行事务操作。
内核事务管理器(KTM:Kernel transaction Manager)
内核事务管理器(以下简称KTM)在Windows Vista中被引入,并被用于后续的Windows Server 2008和Windows 7。引入KTM的主要的目的在于实现将文件管理和注册表管理纳入事务的范畴。借助于KTM,我们可以以事务的方式操作NTFS文件系统下的文件资源,以及注册表资源。我们将支持事务的文件系统和注册表成为事务型的文件系统(TxF)和事务型注册表(TxR)。
之所以被称为内核事务管理器,使因为基于KTM的事务控制引擎运行在内核模式(Kernel Mode),而不是用户模式(User Mode)下。
KTM在内存中调用时使用轻量级事务协议。KTM之多可以管理一个持久化的内核资源管理器(KTM)事务,但是可以管理多个易失型事务资源管理器。
使用KTM时至多可以使用一个服务,但不是传播事务。
分布式事务协调器(DTC:Distributed Transaction Coordinator)
DTC用于管理跨边界(跨应用程序域、进程、机器以至跨网络)执行的分布式事务,它采用相应的事务管理协议,比如OleTx和WSAT,协调一个分布式事务中的所有参与者。
在事务流跨越服务边界时,会使用DTC作为事务管理器,它可以管理包含多个服务和资源管理器的事务。
在每台允许WCF的机器上,DTC默认都是可用的,WCF紧密的与DTC继承在一起。他负责创建事务,收集资源管理器投票,以及告诉资源管理器提交或终止事务。
如下图所示,该应用程序为一个非事务性客户端调用机器A上的服务。机器A上的服务被配置来使用一个事务。这个服务会成为事务的根(root),它不仅可以启动事务,也可以决定什么时候结束事务。
WCF中每个事务只多有一个根服务,这是因为非事务性客户端也可以作为服务的根。
当机器A事务中的某个服务尝试访问机器B中的资源或服务时,他应该有一个远程服务的代理,这个代理可以传播事务ID到机器B。机器B的拦截器可以获取事务ID,然后通知机器B上的DTC来启动并管理本地事务。因为事务ID已经传播给机器B,所以机器B上的资源管理器可以自动加载这个事务ID。与之类似,事务ID也会传播到机器C。
当事务完成时,如果所有的参与者投票提交事务,此时就会启动两阶段提交协议。根机器上的DTC会收集所有的投票,并通知参与事务的所有机器上的DTC,告诉它们启动第一阶段协议。远程机器上的DTC收集自己机器上所有资源管理器的投票结果并告诉DTC。在所有远程机器都返回结果以后,根机器上的DTC综合所有资源管理器的投票结果。如果所有的资源管理器都投票提交,根机器上的DTC会通知远程上的所有的DTC来启动第二阶段协议,然后通知各个资源管理器提交事务。如果一个资源管理器投票终止事务,那么根机器上的DTC就会通知所有的DTC终止事务。注意,只有根事务上的DTC才有权利收集投票结果并做出决策。
四、事务管理器提升
.NET可以动态地给事务管理器分配事务。如果事务管理器无法胜任工作,.NET将会提升事务,也就是让更高级别的事务管理器来管理事务。一个事务可以被提升多个一旦提升就无法降级。因为可以动态提升,所以开发人员避免了直接与事务管理器打交道。
LTM提升
.NET里的每个事务都是有LTM着手管理的。只有事务只与单个持久化资源交互,而且事务不尝试传播事务到WCF服务,LTM就能代码最佳的性能。LTM还可以管理易失型资源管理器,但是,如果事务尝试加入第二个持久化资源或者传播事务给其它服务,.NET将会从LTM提升到DTC。如果第一个持久化事务被KTM访问,.NET将会把事务从LTM提升到KTM。
KTM提升
只要与单个内核资源管理器(LRM)交互且事务是本地的,KTM就可以管理事务。KTM可以在需要时管理尽可能多的易失型资源管理器。如果事务尝试加入第二个持久化资源或者传播事务给其它服务,.NET将会从KTM提升到DTC。