当前位置: 首页 > news >正文

[转载]WCF系列_分布式事务(下)

[转载]WCF系列_分布式事务(下)

浏览到chnking的WCF的分布式事务处理不错,转载过来分享一下。

1、 WCF分布式事务例子
这里也用转账的例子说事。
用户在系统A和系统B都有账户,账户间的资金可以互转,系统A的资金减少多少,系统B的相应账户的资金就增加多少。
系统A机器上有数据库AccountA,系统B机器上有数据库AccountB,数据库的结构一样,都有一个数据表Account,结构如下:

 
为了演示TxF事务性文件,在系统B中增加了一个写文件的操作,记录本次转账操作的信息。转账的所有操作步骤:系统A上账户上减少金额,系统B上记录转账信息文件,系统B上相应账户资金增加这三个操作都在一个事务流中,要么全部完成,要么全部回滚。
系统A和系统B分别在服务器A和服务器B上。系统A在账户上减少金额后调用系统B的WCF服务,在系统B中继续增加账户资金,生成转账信息文件。

下面开始这个例子的完整过程。
1.1.   建立系统B转账WCF服务
建立服务契约:
[ServiceContract]
public interface IAccountB
{
    [OperationContract]
    [TransactionFlow(TransactionFlowOption.Allowed)]
    void deposit(int depositorid, double amount);
}
服务契约就一个方法deposit,其中depositorid表示账户id,amount表示要从系统A转账到系统B的金额。
TransactionFlow这个属性指示operation是否跟随调用端的事务流,参数含义:
TransactionFlowOption.NotAllowed:表示此operation不跟随传入的事务流,不参与分布式事务。
TransactionFlowOption.Allowed:表示此opreation可以跟随传入的事务流,如果有传入的事务流则参与,如果没有传入的事务流则不参与,但是可以启动本地的事务。
TransactionFlowOption.Mandatory:表示此operation必须跟随传入的事务,参与分布式事务,如果调用此operation的客户端没有事务流则抛出异常。

下面是服务实现:

  View Code

服务实现了deposit操作。
[OperationBehavior(TransactionScopeRequired = true)],这里的TransactionScopeRequired = true表示这个操作在TransactionScope内执行,加上前面OperationContract上的TransactionFlowOption.Allowed 允许跟随事务的设置,这个deposit的操作将会参与客户端发起的分布式事务。
实现的deposit操作中完成两个任务,先转账信息写入c:\test.txt文件,这里写文件操作使用了TxF事务性文件操作TransactedFile.Open,关于TxF的操作部分的代码微软有提供,在本文中提供的代码中包含了这部分源码。使用事务性文件操作,在事务中的其他事务资源操作失败后,文件操作也会回滚。

1.2.   建立系统A转账客户端
系统A是个Console应用:

  View Code


1.3.   配置使用OleTransactions协议
先测试使用OleTransactions分布式事务协议,下面是使用OleTransactions时在客户端和服务端需要的服务和配置。

1.3.1.   配置文件
系统B上WCF服务的配置文件:

  View Code

系统A WCF客户端的配置文件

  View Code

 
1.3.2.   配置RPC
使用OleTx协议时,要通过RPC协议在DTC事务管理器之间通讯,RPC本身使用135端口,还要使用数量不定的1024端口以上的动态端口。所以防火墙必须要开放135端口和1024端口以后的所有端口。
但是要开放所有1024以上的端口又是很危险的事情,最好能把RPC使用的端口限制在一定的范围,然后防火墙只开放这个范围的端口。
可以通过修改注册表来达到这个目的:
运行Regedt32.exe打开注册表,在以下注册表项下添加 Internet 项:HKEY_LOCAL_MACHINE\Software\Microsoft\Rpc,在 Internet 项下,添加值“Ports”(MULTI_SZ)、“PortsInternetAvailable”(REG_SZ) 和“UseInternetPorts”(REG_SZ)。
在本示例中,使用了端口 5000 到 5100(含 5000 和 5100),因此该新注册表项将显示为以下形式:
Ports:REG_MULTI_SZ: 5000-5100
PortsInternetAvailable:REG_SZ:Y
UseInternetPorts:REG_SZ:Y

在所有参与事务的机器上都必须启动RPC服务,并配置RPC使用的动态端口,防火墙开放这些动态端口。

1.3.3.   DTC服务
发起事务的服务器的DTC服务必须启动,参与事务的服务器的DTC服务可以不启动。
在事务内要调用跨越进程或机器的服务,事务需要提升级别到DTC管理器,如果发起事务的服务器的DTC服务未启动,则会抛出异常:“试图提升事务时失败。服务器xxx上的MSDTC不可用。”

1.3.4.   测试
将系统B的WCF服务发布至IIS,系统A调用WCF的地址指向系统B发布的服务地址,测试结果,发送到WCF的消息和返回的消息:

  View Code

注意在请求消息的header中有<OleTxTransaction>标签,这个标签用来标示采用OleTxTransaction分布式事务协议。

  View Code


1.4.   配置使用WS-AtomicTransaction协议
1.4.1.   配置文件
将服务端和客户端的配置文件中的:
<transactionFlow transactionProtocol="OleTransactions" />
改成:
<transactionFlow transactionProtocol="WSAtomicTransactionOctober2004" />

1.4.2.   配置WS-AT
要让DTC支持WS-AT协议需要配置参与分布式事务的所有机器的证书,安装WS-AT的DTC的UI等等,配置过程还比较复杂,详细步骤参见微软文档:配置 WS-Atomic事务支持(http://msdn.microsoft.com/zh-cn/library/ms733943.aspx)
配置好的界面如下:

 
WS-AT事务管理器之间的通讯使用SSL安全通道传输,所以每台参与WS-AT事务的机器都必须配置证书和相应的https的端口。
WS-AT的UI界面虽然安装在DTC中,但是WS-AT事务并不依赖于DTC服务,所以所有参与WS-AT事务的机器的DTC服务不必启动。

1.4.3.   测试
抓通讯数据包,这时的消息如下:

  View Code

可以看出使用WS-AT协议时,消息的header部分比使用OleTransactions协议时复杂的多,注意header部分里的:
<Address xmlns="http://schemas.xmlsoap.org/ws/2004/08/addressing">https://win7-pc:1443/WsatService/Registration/Coordinator/</Address>
这是发起WS-AT事务机器的WS-AT事务管理器的地址,参与WS-AT事务的别的机器都要向这个地址来注册本地事务和报告本地事务的完成情况,以便WS-AT事务管理器协调整个分布式事务,来决定提交整个事务还是回滚整个事务。
返回消息:

  View Code

但是在抓数据包是发现一个问题,就是从消息的header看是显示使用WS-AT协议,但是从抓的数据包看依然是使用的OleTransactions协议处理的事务,通过RPC协议协调事务,下面是部分截图:


DCERPC显示是RPC协议,ctx_id: 1 906b0ce0-c70b-1067-b317-00dd010662da显示了事务id。
原来由于OleTransactions协议的开销远比WS-AT协议小,所以微软的默认设计是即使指定使用WS-AT协议,仍然义无反顾的使用OleTransactions协议。所以这时你的机器上要是DTC和RPC的端口没有配置好,就会报错。
要想真正使用WS-AT协议需要手工在注册表中增加一个key:
在注册表HKLM\SOFTWARE\Microsoft\WSAT\3.0下增加一个名为“OleTxUpgradeEnabled”的DWord值,这个key表示在指定WS-AT协议时是否升级使用OleTransactions协议,0表示不升级(即表示使用WS-AT协议),1表示升级(即表示使用OleTransactions协议),默认是1,所以默认时即使你指定使用WS-AT协议,实际上还是被OleTransactions协议替换了。设置为0即可使用WS-AT协议了。
使用WS-AT协议时,事务协调不依赖于DTC,也不走RPC协议,只通过WS-AT配置中的https端口通过SSL进行事务管理器之间的通讯。WS-AT协议是业界标准,只要实现了这个协议的系统都能进行互操作,当然不能依赖于微软的专有RPC协议。

代码下载:
WCF-ATTransTest客户端.rar
WCF-ATTransTest服务端.rar

原文链接:《WCF系列_分布式事务(上)》《WCF系列_分布式事务(下)》
另一了解:《 WCF 分布式事务-应用》

本文转自SanMaoSpace博客园博客,原文链接:http://www.cnblogs.com/SanMaoSpace/p/3266289.html,如需转载请自行联系原作者

相关文章:

  • EF基础知识小记五(一对多、多对多处理)
  • 智能语音控制中心 - 树莓派、Nanopi、Orangepi语音识别控制
  • NFS启动时报错Linux NFS:could not open connection for tcp6
  • 【vuex入门系列02】mutation接收单个参数和多个参数
  • 性能与性价比的平衡,阿里云第二代入门级实例T5详解
  • 13个绚丽的Jquery 界面设计
  • 20162321王彪 2017-2018《程序设计与数据结构》第五周学习总结
  • 剪我一根头发,就要做我一天女人。
  • VS2008 F5不能调试情况一例
  • 短路径算法-Dijkstra算法的应用之单词转换(词梯问题)
  • C++多线程中调用python api函数
  • Gridview的footer模板中放置控件实现添加功能
  • 如何更高效地使用 OkHttp
  • BZOJ-3713[PA2014]Iloczyn
  • Spring绑定请求参数过程以及使用@InitBinder来注册自己的属性处理器
  • 【翻译】babel对TC39装饰器草案的实现
  • 【干货分享】SpringCloud微服务架构分布式组件如何共享session对象
  • 0基础学习移动端适配
  • C# 免费离线人脸识别 2.0 Demo
  • C++入门教程(10):for 语句
  • CAP 一致性协议及应用解析
  • CentOS6 编译安装 redis-3.2.3
  • GitUp, 你不可错过的秀外慧中的git工具
  • gops —— Go 程序诊断分析工具
  • JavaScript类型识别
  • NSTimer学习笔记
  • PHP 使用 Swoole - TaskWorker 实现异步操作 Mysql
  • React-flux杂记
  • Redash本地开发环境搭建
  • SAP云平台运行环境Cloud Foundry和Neo的区别
  • Wamp集成环境 添加PHP的新版本
  • 番外篇1:在Windows环境下安装JDK
  • 关于 Linux 进程的 UID、EUID、GID 和 EGID
  • 聊聊hikari连接池的leakDetectionThreshold
  • 区块链分支循环
  • 再谈express与koa的对比
  • 教程:使用iPhone相机和openCV来完成3D重建(第一部分) ...
  • ​草莓熊python turtle绘图代码(玫瑰花版)附源代码
  • ​业务双活的数据切换思路设计(下)
  • $refs 、$nextTic、动态组件、name的使用
  • (Matlab)使用竞争神经网络实现数据聚类
  • (阿里云万网)-域名注册购买实名流程
  • (八)Spring源码解析:Spring MVC
  • (超详细)语音信号处理之特征提取
  • (附源码)计算机毕业设计SSM智慧停车系统
  • (六)Hibernate的二级缓存
  • (欧拉)openEuler系统添加网卡文件配置流程、(欧拉)openEuler系统手动配置ipv6地址流程、(欧拉)openEuler系统网络管理说明
  • (深入.Net平台的软件系统分层开发).第一章.上机练习.20170424
  • (十) 初识 Docker file
  • (十三)Java springcloud B2B2C o2o多用户商城 springcloud架构 - SSO单点登录之OAuth2.0 根据token获取用户信息(4)...
  • (转)EXC_BREAKPOINT僵尸错误
  • (转载)PyTorch代码规范最佳实践和样式指南
  • ./mysql.server: 没有那个文件或目录_Linux下安装MySQL出现“ls: /var/lib/mysql/*.pid: 没有那个文件或目录”...
  • .java 9 找不到符号_java找不到符号
  • .Net CF下精确的计时器