您的位置:首页 > 其它

使用“消息服务框架”(MSF)实现分布式事务的三阶段提交协议(电商创建订单的示例)

2018-01-31 18:26 2106 查看

1,示例解决方案介绍

在上一篇 《消息服务框架(MSF)应用实例之分布式事务三阶段提交协议的实现》中,我们分析了分布式事务的三阶段提交协议的原理,现在我们来看看如何使用消息服务框架(MSF)来具体实现并且看用它来实现的一些优势。

首先,从Github克隆项目源码,地址:https://github.com/bluedoctor/MSF-DistTransExample

解决方案如下图:

<?xml version="1.0" encoding="utf-8"?>
<configuration>
<appSettings>
<add key="IOCConfigFile" value=".\IOCConfig.xml" />
<add key="ServerIP" value="127.0.0.1" />
<add key="ServerPort" value="12345" />
<add key="ProductUri" value="net.tcp://127.0.0.1:12306"/>
<add key="OrderUri" value="net.tcp://127.0.0.1:12308"/>
<!--MSF_DTS_Uri 分布式事务控制器服务连接地址-->
<add key="MSF_DTS_Uri" value="net.tcp://127.0.0.1:12345"/>
<!-- 全局缓存配置
GlobalCacheProvider="CacheServer" 将使用分布式的缓存服务器,这时候需要配置 CacheConfigFile,其它值将使用本地的缓存
CacheConfigFile :缓存服务器的地址的配置文件,也就是本 ServiceHost 运行的另外一些实例
-->
<add key="GlobalCacheProvider" value="" />
<add key="CacheConfigFile" value="CacheServerCfg.xml" />
<!-- 全局缓存配置结束 -->
<!--PDF.NET SQL 日志记录配置(for 4.0)开始
记录执行的SQL语句,关闭此功能请将SaveCommandLog 设置为False,或者设置DataLogFile 为空;
如果DataLogFile 的路径中包括~符号,表示SQL日志路径为当前Web应用程序的根目录;
如果DataLogFile 不为空且为有效的路径,当系统执行SQL出现了错误,即使SaveCommandLog 设置为False,会且仅仅记录出错的这些SQL语句;
如果DataLogFile 不为空且为有效的路径,且SaveCommandLog 设置为True,则会记录所有的SQL查询。
在正式生产环境中,如果不需要调试系统,请将SaveCommandLog 设置为False 。
-->
<add key="SaveCommandLog" value="False" />
<add key="DataLogFile" value=".\SqlLog.txt" />
<!--LogExecutedTime 需要记录的时间,如果该值等于0会记录所有查询,否则只记录大于该时间的查询。单位毫秒。-->
<add key="LogExecutedTime" value="0" />
<!--PDF.NET SQL 日志记录配置 结束-->
<add key="ClientSettingsProvider.ServiceUri" value="" />
</appSettings>
<connectionStrings>
<!--SOD for SQL Server ,框架会自动创建需要的库  -->
<add name="OrdersDb" connectionString="Data Source=.;Initial Catalog=OrdersDb;Integrated Security=True" providerName="SqlServer"/>
<add name="ProductsDb" connectionString="Data Source=.;Initial Catalog=ProductsDb;Integrated Security=True" providerName="SqlServer"/>

<!-- SOD for SQL Server LocalDB
注意:请将下面的连接字符串,修改为你VS 里面打开的数据库文件的连接字符串
<add name="OrdersDb" connectionString="Data Source=(LocalDB)\MSSQLLocalDB;AttachDbFilename=~\DataBase\OrdersDB_data.mdf;Integrated Security=True;Connect Timeout=30" providerName="SqlServer"/>
<add name="ProductsDb" connectionString="Data Source=(LocalDB)\MSSQLLocalDB;AttachDbFilename=~\DataBase\ProductsDB_data.mdf;Integrated Security=True;Connect Timeout=30" providerName="SqlServer"/>
-->
<!-- MSSQLLocalDB 连接示例
<add name="OrdersDb" connectionString="Data Source=(LocalDB)\MSSQLLocalDB;AttachDbFilename=E:\Git\MSF-DistTransExample\Host\DataBase\OrdersDB_data.mdf;Integrated Security=True;Connect Timeout=30" providerName="SqlServer"/>
<add name="ProductsDb" connectionString="Data Source=(LocalDB)\MSSQLLocalDB;AttachDbFilename=E:\Git\MSF-DistTransExample\Host\DataBase\ProductsDB_data.mdf;Integrated Security=True;Connect Timeout=30" providerName="SqlServer"/>
-->
<!-- SOD for Access 2007 ,2013,2016
<add name="OrdersDb" connectionString="Provider=Microsoft.ACE.OLEDB.12.0;Data Source=~\DataBase\OrdersDb.accdb;Persist Security Info=False;" providerName="Access"/>
<add name="ProductsDb" connectionString="Provider=Microsoft.ACE.OLEDB.12.0;Data Source=~\DataBase\Products.accdb;Persist Security Info=False;" providerName="Access"/>
-->
<!-- SOD for Access 2000,2003
<add name="OrdersDb" connectionString="Provider=Microsoft.Jet.OLEDB.4.0;Data Source=~\DataBase\OrdersDb.mdb;Persist Security Info=False;" providerName="Access"/>
<add name="ProductsDb" connectionString="Provider=Microsoft.Jet.OLEDB.4.0;Data Source=~\DataBase\Products.mdb;Persist Security Info=False;" providerName="Access"/>
-->
<!-- SOD for SQLite
<add name="OrdersDb" connectionString="Data Source=DataBase\OrdersDb.db;" providerName="PWMIS.DataProvider.Data.SQLite,PWMIS.SQLiteClient"/>
<add name="ProductsDb" connectionString="Data Source=DataBase\Products.db;" providerName="PWMIS.DataProvider.Data.SQLite,PWMIS.SQLiteClient"/>
-->
</connectionStrings>
<startup>
<supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.0" />
</startup>
<system.web>
<membership defaultProvider="ClientAuthenticationMembershipProvider">
<providers>
<add name="ClientAuthenticationMembershipProvider" type="System.Web.ClientServices.Providers.ClientFormsAuthenticationMembershipProvider, System.Web.Extensions, Version=4.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35" serviceUri="" />
</providers>
</membership>
<roleManager defaultProvider="ClientRoleProvider" enabled="true">
<providers>
<add name="ClientRoleProvider" type="System.Web.ClientServices.Providers.ClientRoleProvider, System.Web.Extensions, Version=4.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35" serviceUri="" cacheTimeout="86400" />
</providers>
</roleManager>
</system.web>
</configuration>


View Code
配置文件中配置了多种数据库连接方式,根据你的情况具体选择。当前是SqlServer.

然后,按照下图输入相关的信息:



由于我现在的测试环境是SQLSERVER数据库,所以不需要初始化数据库。选择启动事务协调器,测试程序会帮我们启动 协调器服务宿主进程,商品服务宿主进程和订单服务宿主进程。之后,我们在客户端控制台输入 12308,这是订单服务的端口号,接着客户端就会调用订单服务准备创建订单。

6.2,测试结果

下面是各种情况下的测试结果,分为订单创建成功和创建失败两种情况。注意我们在分析真正的测试数据之前,要先跑一次服务进行预热,也就是先进行一次测试,取第二次以后的测试结果。

6.2.1,订单创建成功:

分布式协调服务:

[2018-01-31 17:13:45.807]订阅消息-- From: 127.0.0.1:53276
[2018-01-31 17:13:45.807]正在处理服务请求--From: 127.0.0.1:53276,Identity:WMI2114256838
>>[PMID:1]Service://DTCService/AttendTransaction/System.String=1b975548-afac-4e7a-be6d-5821bce38ce7
DTC Service Callback [127.0.0.1:53276-WMI2114256838] Message:CanCommit
[2018-01-31 17:13:45.853]订阅消息-- From: 127.0.0.1:53278
[2018-01-31 17:13:45.854]正在处理服务请求--From: 127.0.0.1:53278,Identity:WMI2114256838
>>[PMID:1]Service://DTCService/AttendTransaction/System.String=1b975548-afac-4e7a-be6d-5821bce38ce7
DTC Service Callback [127.0.0.1:53278-WMI2114256838] Message:CanCommit
DTC Service Callback [127.0.0.1:53276-WMI2114256838] Message:PreCommit
DTC Service Callback [127.0.0.1:53278-WMI2114256838] Message:PreCommit
DTC Service Callback [127.0.0.1:53278-WMI2114256838] Message:DoCommit
DTC Service Callback [127.0.0.1:53278-WMI2114256838] Message:Completed
DTC Current Use time:0.042516(s)
[2018-01-31 17:13:45.897]请求处理完毕(43.0236ms)--To: 127.0.0.1:53278,Identity:WMI2114256838
>>[PMID:1]消息长度:4字节 -------
result:True
Reponse Message OK.
DTC Service Callback [127.0.0.1:53276-WMI2114256838] Message:DoCommit
[2018-01-31 17:13:45.898]取消订阅-- From: 127.0.0.1:53278
DTC Service Callback [127.0.0.1:53276-WMI2114256838] Message:Completed
DTC Current Use time:0.1009371(s)
[2018-01-31 17:13:45.909]请求处理完毕(101.9327ms)--To: 127.0.0.1:53276,Identity:WMI2114256838
>>[PMID:1]消息长度:4字节 -------
result:True
Reponse Message OK.
[2018-01-31 17:13:45.912]取消订阅-- From: 127.0.0.1:53276


订单服务:

[2018-01-31 17:13:45.798]订阅消息-- From: 127.0.0.1:53275
[2018-01-31 17:13:45.801]正在处理服务请求--From: 127.0.0.1:53275,Identity:WMI2114256838
>>[PMID:1]Service://OrderService/CreateOrder/System.Int32=2000&System.Int32=100&System.Collections.Generic.List`1[[DistTransDto.BuyProductDto, DistTransDto, Version%Eqv;1.0.0.0, Culture%Eqv;neutral, PublicKeyToken%Eqv;null]]=[{"ProductId":1,"BuyNumber":3},{"ProductI
MSF DTC(1b975548-afac-4e7a-be6d-5821bce38ce7) Resource at 17:13:45.809 receive DTC Controller state:CanCommit
[2018-01-31 17:13:45.879]请求处理完毕(77.9367ms)--To: 127.0.0.1:53275,Identity:WMI2114256838
>>[PMID:1]消息长度:4字节 -------
result:True
MSF DTC(1b975548-afac-4e7a-be6d-5821bce38ce7) Resource at 17:13:45.879 receive DTC Controller state:PreCommit
MSF DTC(1b975548-afac-4e7a-be6d-5821bce38ce7) 1PC,Child moniter task has started at time:17:13:45.879
Reponse Message OK.
[2018-01-31 17:13:45.888]取消订阅-- From: 127.0.0.1:53275
MSF DTC(1b975548-afac-4e7a-be6d-5821bce38ce7) 2PC,Child moniter task has started at time:17:13:45.888
MSF DTC(1b975548-afac-4e7a-be6d-5821bce38ce7) 1PC,Child moniter task find DistTrans3PCState has changed,Now is ACK_Yes_2PC,task break!
MSF DTC(1b975548-afac-4e7a-be6d-5821bce38ce7) Resource at 17:13:45.898 receive DTC Controller state:DoCommit
MSF DTC(1b975548-afac-4e7a-be6d-5821bce38ce7) Try Commit..
MSF DTC(1b975548-afac-4e7a-be6d-5821bce38ce7) Try Commit..OK
MSF DTC(1b975548-afac-4e7a-be6d-5821bce38ce7) Resource at 17:13:45.903 receive DTC Controller state:Completed
MSF DTC(1b975548-afac-4e7a-be6d-5821bce38ce7) 3PC Request Completed,use time:0.1019383 seconds.
MSF DTC(1b975548-afac-4e7a-be6d-5821bce38ce7) 2PC,Child moniter task find DistTrans3PCState has changed,Now is Completed,task break!
MSF DTC(1b975548-afac-4e7a-be6d-5821bce38ce7) Controller Process Reuslt:True,Receive time:17:13:45.913


商品服务:

[2018-01-31 17:13:45.848]正在处理服务请求--From: 127.0.0.1:53277,Identity:WMI2114256838
>>[PMID:1]Service://ProductService/UpdateProductOnhand/System.String=1b975548-afac-4e7a-be6d-5821bce38ce7&System.Collections.Generic.List`1[[DistTransDto.BuyProductDto, DistTransDto, Version%Eqv;1.0.0.0, Culture%Eqv;neutral, PublicKeyToken%Eqv;null]]=[{"ProductId":1
MSF DTC(1b975548-afac-4e7a-be6d-5821bce38ce7) Resource at 17:13:45.855 receive DTC Controller state:CanCommit
----------1,-Session ID:1b975548-afac-4e7a-be6d-5821bce38ce7----------
MSF DTC(1b975548-afac-4e7a-be6d-5821bce38ce7) 1PC,Child moniter task has started at time:17:13:45.856
[2018-01-31 17:13:45.856]请求处理完毕(8.011ms)--To: 127.0.0.1:53277,Identity:WMI2114256838
>>[PMID:1]消息长度:97字节 -------
result:[{"StoreHouse":"广州","ProductId":1,"BuyNumber":3},{"StoreHouse":"广州","ProductId":2,"BuyNumber":1}]
Reponse Message OK.
[2018-01-31 17:13:45.857]取消订阅-- From: 127.0.0.1:53277
[2018-01-31 17:13:45.858]订阅消息-- From: 127.0.0.1:53277
[2018-01-31 17:13:45.867]正在处理服务请求--From: 127.0.0.1:53277,Identity:WMI2114256838
>>[RMID:0]Service://ProductService/GetProductInfo/System.Int32=1
---------2,--Session ID:1b975548-afac-4e7a-be6d-5821bce38ce7----------
[2018-01-31 17:13:45.868]请求处理完毕(1.0005ms)--To: 127.0.0.1:53277,Identity:WMI2114256838
>>[RMID:0]消息长度:53字节 -------
result:{"ID":1,"Onhand":88,"Price":10.0,"ProductName":"商品0"}
[2018-01-31 17:13:45.869]正在处理服务请求--From: 127.0.0.1:53277,Identity:WMI2114256838
>>[RMID:0]Service://ProductService/GetProductInfo/System.Int32=2
---------2,--Session ID:1b975548-afac-4e7a-be6d-5821bce38ce7----------
[2018-01-31 17:13:45.869]请求处理完毕(0.5005ms)--To: 127.0.0.1:53277,Identity:WMI2114256838
>>[RMID:0]消息长度:53字节 -------
result:{"ID":2,"Onhand":96,"Price":11.0,"ProductName":"商品1"}
[2018-01-31 17:13:45.870]取消订阅-- From: 127.0.0.1:53277
MSF DTC(1b975548-afac-4e7a-be6d-5821bce38ce7) Resource at 17:13:45.888 receive DTC Controller state:PreCommit
MSF DTC(1b975548-afac-4e7a-be6d-5821bce38ce7) 2PC,Child moniter task has started at time:17:13:45.889
MSF DTC(1b975548-afac-4e7a-be6d-5821bce38ce7) Resource at 17:13:45.890 receive DTC Controller state:DoCommit
MSF DTC(1b975548-afac-4e7a-be6d-5821bce38ce7) Try Commit..
MSF DTC(1b975548-afac-4e7a-be6d-5821bce38ce7) Try Commit..OK
MSF DTC(1b975548-afac-4e7a-be6d-5821bce38ce7) Resource at 17:13:45.895 receive DTC Controller state:Completed
MSF DTC(1b975548-afac-4e7a-be6d-5821bce38ce7) 3PC Request Completed,use time:0.0470229 seconds.
MSF DTC(1b975548-afac-4e7a-be6d-5821bce38ce7) 1PC,Child moniter task find DistTrans3PCState has changed,Now is Completed,task break!
MSF DTC(1b975548-afac-4e7a-be6d-5821bce38ce7) Controller Process Reuslt:True,Receive time:17:13:45.900
MSF DTC(1b975548-afac-4e7a-be6d-5821bce38ce7) 2PC,Child moniter task find DistTrans3PCState has changed,Now is Completed,task break!


性能总结:

订单创建成功的情况下,分布式协调器服务总共耗时 0.042516(s),订单服务耗时0.1019383秒,商品服务耗时0.0470229秒。

总体上,执行一个创建订单的分布式事务,耗时在50毫秒以内。

6.2.2,订单创建失败:

分布式协调服务:

[2018-01-31 17:04:11.669]订阅消息-- From: 127.0.0.1:53201
[2018-01-31 17:04:11.670]正在处理服务请求--From: 127.0.0.1:53201,Identity:WMI2114256838
>>[PMID:1]Service://DTCService/AttendTransaction/System.String=76d175cc-5d40-4d05-adfb-94158b5c2215
DTC Service Callback [127.0.0.1:53201-WMI2114256838] Message:CanCommit
[2018-01-31 17:04:11.679]订阅消息-- From: 127.0.0.1:53203
[2018-01-31 17:04:11.680]正在处理服务请求--From: 127.0.0.1:53203,Identity:WMI2114256838
>>[PMID:1]Service://DTCService/AttendTransaction/System.String=76d175cc-5d40-4d05-adfb-94158b5c2215
DTC Service Callback [127.0.0.1:53203-WMI2114256838] Message:CanCommit
DTC Service Callback [127.0.0.1:53201-WMI2114256838] Message:Abort
DTC Service Callback [127.0.0.1:53201-WMI2114256838] Message:Completed
DTC Service Callback [127.0.0.1:53203-WMI2114256838] Message:Abort
DTC Current Use time:0.0434914(s)
[2018-01-31 17:04:11.715]请求处理完毕(45.0015ms)--To: 127.0.0.1:53201,Identity:WMI2114256838
>>[PMID:1]消息长度:4字节 -------
result:True
Reponse Message OK.
DTC Service Callback [127.0.0.1:53203-WMI2114256838] Message:Completed
[2018-01-31 17:04:11.717]取消订阅-- From: 127.0.0.1:53201
DTC Current Use time:0.0400005(s)
[2018-01-31 17:04:11.724]请求处理完毕(44.4941ms)--To: 127.0.0.1:53203,Identity:WMI2114256838
>>[PMID:1]消息长度:4字节 -------
result:True
Reponse Message OK.
[2018-01-31 17:04:11.731]取消订阅-- From: 127.0.0.1:53203


订单服务:

[2018-01-31 17:04:11.662]订阅消息-- From: 127.0.0.1:53200
[2018-01-31 17:04:11.665]正在处理服务请求--From: 127.0.0.1:53200,Identity:WMI2114256838
>>[PMID:1]Service://OrderService/CreateOrder/System.Int32=2000&System.Int32=100&System.Collections.Generic.List`1[[DistTransDto.BuyProductDto, DistTransDto, Version%Eqv;1.0.0.0, Culture%Eqv;neutral, PublicKeyToken%Eqv;null]]=[{"ProductId":1,"BuyNumber":3},{"ProductI
MSF DTC(76d175cc-5d40-4d05-adfb-94158b5c2215) Resource at 17:04:11.672 receive DTC Controller state:CanCommit
PDF.NET AdoHelper Query Error:
DataBase ErrorMessage:;违反了 PRIMARY KEY 约束 'PK__Orders__2CE8FBFB7F60ED59'。不能在对象 'dbo.Orders' 中插入重复键。
语句已终止。
SQL:INSERT INTO [Orders]([OerderID],[OrderName],[AmountPrice],[OwnerID],[OrderTime]) VALUES (@P0,@P1,@P2,@P3,@P4)
CommandType:Text
Parameters:
Parameter["@P0"]        =       "2000"                          //DbType=Int32
Parameter["@P1"]        =       "Prudoct:,商品0,商品1"
//DbType=String
Parameter["@P2"]        =       "41"                    //DbType=Single
Parameter["@P3"]        =       "100"                   //DbType=Int32
Parameter["@P4"]        =       "2018-1-31 17:04:11"                    //DbType=DateTime

MSF DTC(76d175cc-5d40-4d05-adfb-94158b5c2215) 1PC,Child moniter task has started at time:17:04:11.710
MSF DTC(76d175cc-5d40-4d05-adfb-94158b5c2215) Task Error:发生一个或多个错误。
MSF DTC(76d175cc-5d40-4d05-adfb-94158b5c2215) Try Rollback..
MSF DTC(76d175cc-5d40-4d05-adfb-94158b5c2215) Resource at 17:04:11.711 receive DTC Controller state:Abort
MSF DTC(76d175cc-5d40-4d05-adfb-94158b5c2215) Try Rollback..OK
MSF DTC(76d175cc-5d40-4d05-adfb-94158b5c2215) Try Rollback..
[2018-01-31 17:04:11.712]请求处理完毕(46.5004ms)--To: 127.0.0.1:53200,Identity:WMI2114256838
>>[PMID:1]消息长度:5字节 -------
result:False
Reponse Message OK.
MSF DTC(76d175cc-5d40-4d05-adfb-94158b5c2215) Try Rollback..OK
MSF DTC(76d175cc-5d40-4d05-adfb-94158b5c2215) Resource at 17:04:11.714 receive DTC Controller state:Completed
MSF DTC(76d175cc-5d40-4d05-adfb-94158b5c2215) 3PC Request Completed,use time:0.0469998 seconds.
[2018-01-31 17:04:11.716]取消订阅-- From: 127.0.0.1:53200
MSF DTC(76d175cc-5d40-4d05-adfb-94158b5c2215) Controller Process Reuslt:True,Receive time:17:04:11.719
MSF DTC(76d175cc-5d40-4d05-adfb-94158b5c2215) 1PC,Child moniter task find DistTrans3PCState has changed,Now is Completed,task break!


商品服务:

[2018-01-31 17:04:11.674]订阅消息-- From: 127.0.0.1:53202
[2018-01-31 17:04:11.675]正在处理服务请求--From: 127.0.0.1:53202,Identity:WMI2114256838
>>[PMID:1]Service://ProductService/UpdateProductOnhand/System.String=76d175cc-5d40-4d05-adfb-94158b5c2215&System.Collections.Generic.List`1[[DistTransDto.BuyProductDto, DistTransDto, Version%Eqv;1.0.0.0, Culture%Eqv;neutral, PublicKeyToken%Eqv;null]]=[{"ProductId":1
MSF DTC(76d175cc-5d40-4d05-adfb-94158b5c2215) Resource at 17:04:11.681 receive DTC Controller state:CanCommit
----------1,-Session ID:76d175cc-5d40-4d05-adfb-94158b5c2215----------
MSF DTC(76d175cc-5d40-4d05-adfb-94158b5c2215) 1PC,Child moniter task has started at time:17:04:11.682
[2018-01-31 17:04:11.682]请求处理完毕(7.5003ms)--To: 127.0.0.1:53202,Identity:WMI2114256838
>>[PMID:1]消息长度:97字节 -------
result:[{"StoreHouse":"广州","ProductId":1,"BuyNumber":3},{"StoreHouse":"广州","ProductId":2,"BuyNumber":1}]
Reponse Message OK.
[2018-01-31 17:04:11.685]取消订阅-- From: 127.0.0.1:53202
[2018-01-31 17:04:11.686]订阅消息-- From: 127.0.0.1:53202
[2018-01-31 17:04:11.687]正在处理服务请求--From: 127.0.0.1:53202,Identity:WMI2114256838
>>[RMID:0]Service://ProductService/GetProductInfo/System.Int32=1
---------2,--Session ID:76d175cc-5d40-4d05-adfb-94158b5c2215----------
[2018-01-31 17:04:11.688]请求处理完毕(1.5019ms)--To: 127.0.0.1:53202,Identity:WMI2114256838
>>[RMID:0]消息长度:53字节 -------
result:{"ID":1,"Onhand":88,"Price":10.0,"ProductName":"商品0"}
[2018-01-31 17:04:11.690]正在处理服务请求--From: 127.0.0.1:53202,Identity:WMI2114256838
>>[RMID:0]Service://ProductService/GetProductInfo/System.Int32=2
---------2,--Session ID:76d175cc-5d40-4d05-adfb-94158b5c2215----------
[2018-01-31 17:04:11.694]请求处理完毕(4ms)--To: 127.0.0.1:53202,Identity:WMI2114256838
>>[RMID:0]消息长度:53字节 -------
result:{"ID":2,"Onhand":96,"Price":11.0,"ProductName":"商品1"}
[2018-01-31 17:04:11.694]取消订阅-- From: 127.0.0.1:53202
MSF DTC(76d175cc-5d40-4d05-adfb-94158b5c2215) Resource at 17:04:11.714 receive DTC Controller state:Abort
MSF DTC(76d175cc-5d40-4d05-adfb-94158b5c2215) Try Rollback..
MSF DTC(76d175cc-5d40-4d05-adfb-94158b5c2215) Try Rollback..OK
MSF DTC(76d175cc-5d40-4d05-adfb-94158b5c2215) Resource at 17:04:11.717 receive DTC Controller state:Completed
MSF DTC(76d175cc-5d40-4d05-adfb-94158b5c2215) 3PC Request Completed,use time:0.0410005 seconds.
MSF DTC(76d175cc-5d40-4d05-adfb-94158b5c2215) 1PC,Child moniter task find DistTrans3PCState has changed,Now is Completed,task break!
MSF DTC(76d175cc-5d40-4d05-adfb-94158b5c2215) Controller Process Reuslt:True,Receive time:17:04:11.731


性能总结:

订单创建成功的情况下,分布式协调器服务总共耗时 0.0434914(s),订单服务耗时0.0469998秒,商品服务耗时0.0410005秒。

总体上,执行一个创建订单的分布式事务,耗时在50毫秒以内。

6.2.3,总体性能总结:

从上面的测试结果看到,不论是订单创建成功提交事务,还是订单创建失败回滚事务,总体上事务执行时间都在50毫秒以内,多次测试也没用发现某个事务节点严重等待耗时的情况。

7,并发下单性能测试

上面测试单个分布式事务执行在50毫秒以内,那么并发执行性能怎么样呢?

可以将客户端的代码稍加改造,如下:

private static void TestCreateOrder(Proxy client)
{
List<BuyProductDto> buyProducts = new List<BuyProductDto>();
buyProducts.Add(new BuyProductDto() {  ProductId=1, BuyNumber=3});
buyProducts.Add(new BuyProductDto() { ProductId =2, BuyNumber = 1 });

int orderId = 7000;
int userId = 100;

ServiceRequest request = new ServiceRequest();
request.ServiceName = "OrderService";
request.MethodName = "CreateOrder";
request.Parameters = new object[] { orderId,userId, buyProducts };

bool result=client.RequestServiceAsync<bool>(request).Result;
if(result)
Console.WriteLine("创建订单成功,订单号:{0}",orderId);
else
Console.WriteLine("创建订单失败,订单号:{0}", orderId);

Console.WriteLine("------开始并发下单测试,按任意键继续---------");
Console.ReadLine();

System.Diagnostics.Stopwatch sw = new System.Diagnostics.Stopwatch();
sw.Start();
int taskCount = 2;
List<Task> tasks = new List<Task>();
for (int i = 1; i <= taskCount; i++)
{
Proxy client1 = new Proxy();
client1.ServiceBaseUri = client.ServiceBaseUri;

ServiceRequest request1 = new ServiceRequest();
request1.ServiceName = "OrderService";
request1.MethodName = "CreateOrder";
request1.Parameters = new object[] { orderId+i, userId, buyProducts };
var task = client1.RequestServiceAsync<bool>(request1);
tasks.Add(task);
Console.WriteLine("添加第 {0}个任务.",i);
}
Console.WriteLine("{0} 个订单请求任务创建完成,开始等待所有任务执行完成!",taskCount);
Task.WaitAll(tasks.ToArray());
Console.WriteLine("所有任务执行完成!");
sw.Stop();
Console.WriteLine("总耗时:{0}(s),TPS:{1}",sw.Elapsed.TotalSeconds,(double)taskCount /sw.Elapsed.TotalSeconds);

}


上面程序中,变量 taskCount 表示要并发下单的任务数,TPS表示每秒处理的事务数,是一个常用的性能指标单位。

先以2个并发下单任务数测试,结果如下:

------开始并发下单测试,按任意键继续---------

添加第 1个任务.
添加第 2个任务.
2 个订单请求任务创建完成,开始等待所有任务执行完成!
所有任务执行完成!
总耗时:0.0503977(s),TPS:39.6843506747332


TPS接近40个,还可以;

再以3个并发任务数测试,结果如下:

------开始并发下单测试,按任意键继续---------

添加第 1个任务.
添加第 2个任务.
添加第 3个任务.
3 个订单请求任务创建完成,开始等待所有任务执行完成!
所有任务执行完成!
总耗时:0.3463996(s),TPS:8.66051808373913


3个并发后,性能下降很快,只有8个多TPS了。

直接测试10个并发,结果如下:

------开始并发下单测试,按任意键继续---------

添加第 1个任务.
添加第 2个任务.
添加第 3个任务.
添加第 4个任务.
添加第 5个任务.
添加第 6个任务.
添加第 7个任务.
添加第 8个任务.
添加第 9个任务.
添加第 10个任务.
10 个订单请求任务创建完成,开始等待所有任务执行完成!
所有任务执行完成!
总耗时:8.7288772(s),TPS:1.14562271537054


到10个并发后,TPS下降的很厉害,只有1个多了。

一直测试到50个并发,TPS也只有1个多,初步结论在10个以上并发TPS只能有1个多,看来在高并发下,分布式事务的性能的确不理想。

不过,本次测试的电商下单业务逻辑稍微有点复杂,其中构造订单的过程中需要反复查询几次商品库的信息,而且还有插入订单明细的操作,在数据库并发访问的时候很容易引起表锁,这也是性能下降很明显的原因。

如果是银行跨行转账这样比较简单的例子,可能性能要高些,大家可以自己去做个测试。

8,消息服务框架的分布式事务总结

消息服务框架(MSF)成功的实现了基于3阶段提交的分布式事务协议,并且事务执行性能在分布式环境下是可以接受的。

当前实现过程中,利用消息服务框架的长连接特性,它可以及时的发现网络异常情况而不会出现出现“傻等”的问题(等到超时),这可以保证分布式事务执行的可靠性和效率。

分布式事务在高并发下性能表现不理想,我们在实际项目中需要注意这个问题。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: 
相关文章推荐