mysql分布式事务wcf_基于WS-AtomicTransaction标准的WCF远程分布式事务

在.net remoting的事务传播以及wcf分布式事务 中,我们用TIP协在.net remoting协议上实现了远程事务,其本质是通过将TIP事务的TIP URL传递到远程机器上,然后由远程机器通过TIP协议连接到事务协调器上,但是总体看下来还是有一些缺点:

(1)实现起来还是有点麻烦。

(2)特别是如果涉及多台服务器,多个服务都参与到事务中的时候,那样需要将TIP URL传来传去,换言之,需要自己实现事务传播,那更是麻烦。

(3)不支持异构系统,比如除了调用.net remoting外,还需要调用j2ee的web service的话,那根本就不可能做到AtomicTransaction了。

相对而言,WCF在远程分布式事务传播上就简单得多了,而且远程分布式事务传播是WCF内部实现的,使用起来只需要在配置文件上和Contract上面加上一些特性即可。与TIP事务不同,WCF是通过实现WS-Transaction,WS-Coordination, WS-AtomicTransaction,而这几个都不是微软自己的协议,是一套工业标准。只要服务方的基础架构也实现了这套工业标准,WCF实现的WS就可以和WebSphere实现的WS在实现分布式事务。

废话少说,我们就来看看怎么用WCF实现基于WS-AT的远程分布式事务吧(假设有两台服务器MachineA和MachineB参与了分布式事务)。

第一件要做的事情就是配置MSDTC,让它只是WS-AT协议

1、安装Windows Communication Foundation 更新程序 (KB912817)

2、使用Windows SDKs的工具MakeCert.exe,为MachineA和MachineB生成X.509证书(分别称为CertA和CertB)

MakeCert.exe -r -pe -sky exchange -n "CN=MachineA" -ss Root -sr LocalMachine      MakeCert.exe -r -pe -sky exchange -n "CN=MachineB" -ss Root -sr LocalMachine      这里需要注意的是"CN=MachineA"中的服务器名,需要用FQDN,比如MachineA在域cos.com,那么就需要用"CN=MachineA.cos.com",而不是MachineA。

3、在MachineA中,从证书中的计算机帐号Trusted Root Certificate Authority Node区到处证书CertA,并导入到Personal 区域(导出时需要同时导出私钥)。在MachineB也做同样的操作。

39492122_1.JPG

4、在MachineA将CertA的公钥导出到文件CertA.cer,并导入到MachineB的计算机帐号中的Trusted Root Certificate Authority Node区域和Personal区域。同样将CertB的公钥导出到MachineA的计算机帐号中的Trusted Root Certificate Authority Node区域和Personal区域。

5、配置MSDTC,启用WS-AT协议。

注册程序集wsatui.dll(可以在Windows SDKs的bin目录找到该文件,默认安装目录是C:\Program Files\Microsoft SDKs\Windows\v6.0\Bin),执行命令:

regasm /codebase C:\Program Files\Microsoft SDKs\Windows\v6.0\Bin\wsatui.dll

6、执行了上面的操作後,打开MSDTC的配置,就会看到多了一个WS-AT的Tab。在里面配置一下相关的参数:

(1)选择启用WS-AT

(2)设置Https端口,默认是443,但为了避免冲突,我设成了1443

(3)设置Endpoint Certificate,对于MachineA,选择CertA,对于MachineB,选择CertB

(4)设置Authorized certificates,对于MachineA,选择CertB,对于MachineA,选择CertA(如果有多台服务器参与分布式事务,可以选择多个cert)

39492122_2.JPG

到此为止已经配置好启用WS-AT协议了,接下来就可以写WCF程序来跑跑WS-AT协议了。

第二步:写WCF程序

和一般的WCF程序差不多,唯一的区别就是配置上有所不同,和需要在Contract的方法上面加一些特性。对于接口方法,加上特性:[TransactionFlow(TransactionFlowOption.Mandatory)]。对于实现类,加上特性:[OperationBehavior(TransactionScopeRequired=true)]

39492122_3.gif39492122_3.gif    [ServiceContract()]

39492122_3.gifpublicinterfaceICustomerService

39492122_4.gif{

39492122_5.gif        [OperationContract]

39492122_5.gif        [TransactionFlow(TransactionFlowOption.Mandatory)]

39492122_5.gifintUpdate(intcustomerID);

39492122_5.gif

39492122_5.gif        [OperationContract]

39492122_5.gifstringGetCustomerName(intcustomerID);

39492122_5.gif        

39492122_6.gif    }39492122_3.gif

39492122_3.gifpublicclassCustomerService : ICustomerService

39492122_4.gif{

39492122_5.gif        [OperationBehavior(TransactionScopeRequired=true)]

39492122_5.gifpublicintUpdate(intcustomerID)

39492122_7.gif

39492122_8.gif39492122_9.gif{

39492122_5.giftry39492122_7.gif

39492122_8.gif39492122_9.gif{

39492122_5.gif                Console.WriteLine("Update Customer

39492122_9.gif");

39492122_5.gifusing(SqlConnection cn=newSqlConnection("Server=.;Integrated security=true;initial catalog=learningsite"))

39492122_7.gif

39492122_8.gif39492122_9.gif{

39492122_5.gif                    cn.Open();

39492122_5.gif                    SqlCommand cmd=newSqlCommand("Update Customers Set CustomerName=CustomerName + Cast(@CustomerID as varchar(10)) where customerID = @customerID", cn);

39492122_5.gif                    cmd.Parameters.AddWithValue("@CustomerID", customerID);

39492122_5.gifreturncmd.ExecuteNonQuery()>0?0:-1;

39492122_10.gif                }39492122_10.gif            }39492122_5.gifcatch(Exception ex)

39492122_7.gif

39492122_8.gif39492122_9.gif{

39492122_5.gif                Console.WriteLine(ex.ToString());

39492122_5.gifreturn-1;

39492122_10.gif            }39492122_10.gif        }39492122_5.gif                

39492122_5.gifpublicstringGetCustomerName(intcustomerID)

39492122_7.gif

39492122_8.gif39492122_9.gif{

39492122_5.gifstringnow=DateTime.Now.ToString();

39492122_5.gif            Console.WriteLine("CustomerName");

39492122_5.gifreturn"CustomerName";

39492122_10.gif        }39492122_6.gif    }

配置文件方面,我们使用customBinding(当然,也可以使用wsHttpBinding,它只支持WS-AT协议)。客户端配置如下:

39492122_3.gif39492122_3.gif39492122_3.gif39492122_3.gif39492122_3.gif39492122_3.gif39492122_3.gif39492122_3.gif39492122_3.gif39492122_3.gif39492122_3.gif39492122_3.gif39492122_3.gif39492122_3.gif39492122_3.gif39492122_3.gif39492122_3.gif39492122_3.gif39492122_3.gif39492122_3.gif39492122_3.gif39492122_3.gif39492122_3.gif39492122_3.gif             bindingConfiguration="httpWSAT"contract="ICustomerService"name="ICustomerService">39492122_3.gif39492122_3.gif39492122_3.gif39492122_3.gif39492122_3.gif             bindingConfiguration="httpWSAT"contract="WCFTransactionClient.OrderService.IOrderService"39492122_3.gif             name="IOrderService">39492122_3.gif39492122_3.gif39492122_3.gif39492122_3.gif39492122_3.gif39492122_3.gif

服务器端配置:

39492122_3.gif<?xml  version="1.0" encoding="utf-8"?>39492122_3.gif39492122_3.gif39492122_3.gif39492122_3.gif39492122_3.gif39492122_3.gif39492122_3.gif39492122_3.gif39492122_3.gif39492122_3.gif39492122_3.gif39492122_3.gif39492122_3.gif39492122_3.gif39492122_3.gif39492122_3.gif39492122_3.gif39492122_3.gif39492122_3.gif39492122_3.gif39492122_3.gif39492122_3.gif39492122_3.gif39492122_3.gif39492122_3.gif39492122_3.gif39492122_3.gif39492122_3.gif39492122_3.gif                 contract="WCFTransactionLib.ICustomerService"/>39492122_3.gif39492122_3.gif39492122_3.gif39492122_3.gif39492122_3.gif39492122_3.gif39492122_3.gif39492122_3.gif                 contract="WCFTransactionLib.IOrderService"/>39492122_3.gif39492122_3.gif39492122_3.gif39492122_3.gif39492122_3.gif39492122_3.gif39492122_3.gif39492122_3.gif39492122_3.gif

配置文件里面有一点需要注意的,就是在endpoint address和baseAddress中使用的地址中的服务器地址必须使用和生成X.509证书一样的地址,比如必须用http://MachineA.cos.com,而不是http://192.168.1.101或者http://MachineA。这个是ssl证书的要求:)

废话少说了,先附上测试用的源代码吧

/Files/walkinhill/wcftransactiondemosolutionnew.zip

已经写了不少了,只好把通过分析WCF程序之间交互的消息来看看WS-AT的原理的。只好留作下一篇在写WS-AT消息的内容和WS-AT和OleTx协议的一些差别了:)

参考资料:

http://msdn2.microsoft.com/en-us/library/ms733943.aspx

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值