使用“消息服务框架”(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阶段提交的分布式事务协议,并且事务执行性能在分布式环境下是可以接受的。当前实现过程中,利用消息服务框架的长连接特性,它可以及时的发现网络异常情况而不会出现出现“傻等”的问题(等到超时),这可以保证分布式事务执行的可靠性和效率。
分布式事务在高并发下性能表现不理想,我们在实际项目中需要注意这个问题。
相关文章推荐
- 消息服务框架(MSF)应用实例之分布式事务三阶段提交协议的实现
- 使用消息队列实现分布式事务-公认较为理想的分布式事务解决方案(三)
- 采用Best effort 1pc + 回滚补偿机制实现的一个distributed transaction (分布式事务框架).基于dubbo rpc服务上实现。
- 使用消息队列实现分布式事务-公认较为理想的分布式事务解决方案(三)
- 微服务框架Spring Cloud介绍 Part1: 使用事件和消息队列实现分布式事务
- [转载]使用消息队列实现分布式事务-公认较为理想的分布式事务解决方案
- Adhesive框架系列文章--WCF 分布式服务模块使用和实现
- 微服务框架Spring Cloud介绍 Part1: 使用事件和消息队列实现分布式事务
- 微服务框架Spring Cloud之使用事件和消息队列实现分布式事务
- 使用消息队列实现分布式事务-公认较为理想的分布式事务解决方案
- 微服务框架Spring Cloud介绍 Part1: 使用事件和消息队列实现分布式事务
- 基于JMS消息中间件的分布式系统初探究(一) - 通过JMS实现Web服务器与服务框架的通讯
- SignalR代理对象异常:Uncaught TypeError: Cannot read property 'client' of undefined 推出的结论 SignalR 简单示例 通过三个DEMO学会SignalR的三种实现方式 SignalR推送框架两个项目永久连接通讯使用 SignalR 集线器简单实例2 用SignalR创建实时永久长连接异步网络应用程序
- 跨数据库分布式实时事务 - 基于RabbitMQ实时消息队列服务实现
- C#编写Windows服务程序 (服务端),客户端使用 消息队列 实现淘宝 订单全链路效果
- C#编写Windows服务程序 (服务端),client使用 消息队列 实现淘宝 订单全链路效果
- 分享在Linux下使用OSGi.NET插件框架快速实现一个分布式服务集群的方法
- 使用消息队列实现分布式事务-公认较为理想的分布式事务解决方案
- 使用消息队列实现分布式事务-公认较为理想的分布式事务解决方案
- 服务使用CXF框架客户端使用Axis2框架的webservice实现方案