原文在这里:如何使用Seata保证Dubbo微服务间的一致性。

从这里下载sample代码,master分支,最新的代码提交日期是2019.9.16,修订号cd10c5a。本文代码在模块dubbo里。

开发环境:win10、idea 2019.1.3、JDK1.8。

准备

在本机新建数据库fescar_demo,并修改jdbc.properties里的三处用户名、密码。

使用seata-samples\dubbo\src\main\resources\sql下的SQL脚本,新建表:undo_logstorage_tblorder_tblaccount_tbl
为了方便观察数据,新建表undo_log_my,语句与undo_log相同。新建触发器,插入undo_log表后,将内容copy一份再插入undo_log_my

CREATE TRIGGER copy_undo_log
AFTER INSERT ON undo_log
FOR EACH ROW
INSERT INTO undo_log_my
VALUES (NEW.id, NEW.branch_id, NEW.xid, NEW.context, NEW.rollback_info, NEW.log_status, NEW.log_created, NEW.log_modified, NEW.ext);

修改log4j.properties为:

log4j.rootLogger = debug,stdout### output console ###
log4j.appender.stdout = org.apache.log4j.ConsoleAppender
log4j.appender.stdout.Target = System.out
log4j.appender.stdout.layout = org.apache.log4j.PatternLayout
log4j.appender.stdout.layout.ConversionPattern = [%-5p] %d{yyyy-MM-dd HH:mm:ss,SSS} method:%l%n%m%nlog4j.logger.java.sql.Connection=DEBUG
log4j.logger.java.sql.Statement=DEBUG
log4j.logger.java.sql.ResultSet=DEBUG
log4j.logger.java.sql.PreparedStatement=DEBUG

在本地安装Zookeeper,网上的资料有很多,此处略。通过命令行执行:D:\ProgramFiles\zookeeper-3.4.6\bin\zkServer.cmd

修改4处的Dubbo配置:

    <!--<dubbo:registry address="multicast://127.0.0.1:1234?unicast=false" />--><!--support etcd --><!--<dubbo:registry address="etcd3://127.0.0.1:2379/org.apache.dubbo.registry.RegistryService" />--><!--support zk--><dubbo:registry address="zookeeper://localhost:2181" /><!--support nacos--><!--<dubbo:registry address="nacos://127.0.0.1:8848"/>-->

seata-samples\dubbo模块依赖了seata-all 0.8.0 版本,下载相应版本的seata-server-0.8.0.zip,通过命令行执行:D:\ThirdPartiesFiles\seata\seata-server-0.8.0\bin\seata-server.bat

模拟正常的业务流程

注释掉seata-samples\dubbo\src\main\java\io\seata\samples\dubbo\service\BusinessServiceImpl.java里的运行期异常:

    @Override@GlobalTransactional(timeoutMills = 300000, name = "dubbo-demo-tx")public void purchase(String userId, String commodityCode, int orderCount) {LOGGER.info("purchase begin ... xid: " + RootContext.getXID());storageService.deduct(commodityCode, orderCount);orderService.create(userId, commodityCode, orderCount);//throw new RuntimeException("xxx");}

启动账户服务 (DubboAccountServiceStarter),account_tbl表里被程序插入一条记录。

user_id money
U100001 999

启动库存服务 (DubboStorageServiceStarter),storage_tbl表里被程序插入一条记录。

commodity_code count
C00321 100

启动订单服务 (DubboOrderServiceStarter),order_tbl表里暂无记录。

运行BusinessService入口 (DubboBusinessTester),模拟业务逻辑:用户U100001购买了2件编号为C00321的商品,单价¥200(是硬编码),合计¥400。order_tbl表里被程序插入一条记录:

user_id commodity_code count monty
U100001 C00321 2 400

同时,account_tbl表被扣减400元:

user_id money
U100001 599

storage_tbl表被扣减2件库存:

commodity_code count
C00321 98

undo_log表里似乎没有记录?!其实是先被插入,后又被删除了。还好,我们定义了触发器,把插入到undo_log表里的数据拷贝一份到undo_log_my表。
id为1、2、3行的rollback_info列内容分别如下:

{"@class": "io.seata.rm.datasource.undo.BranchUndoLog","xid": "10.13.24.159:8091:2022944458","branchId": 2022944459,"sqlUndoLogs": ["java.util.ArrayList", [{"@class": "io.seata.rm.datasource.undo.SQLUndoLog","sqlType": "UPDATE","tableName": "storage_tbl","beforeImage": {"@class": "io.seata.rm.datasource.sql.struct.TableRecords","tableName": "storage_tbl","rows": ["java.util.ArrayList", [{"@class": "io.seata.rm.datasource.sql.struct.Row","fields": ["java.util.ArrayList", [{"@class": "io.seata.rm.datasource.sql.struct.Field","name": "id","keyType": "PrimaryKey","type": 4,"value": 1}, {"@class": "io.seata.rm.datasource.sql.struct.Field","name": "count","keyType": "NULL","type": 4,"value": 100}]]}]]},"afterImage": {"@class": "io.seata.rm.datasource.sql.struct.TableRecords","tableName": "storage_tbl","rows": ["java.util.ArrayList", [{"@class": "io.seata.rm.datasource.sql.struct.Row","fields": ["java.util.ArrayList", [{"@class": "io.seata.rm.datasource.sql.struct.Field","name": "id","keyType": "PrimaryKey","type": 4,"value": 1}, {"@class": "io.seata.rm.datasource.sql.struct.Field","name": "count","keyType": "NULL","type": 4,"value": 98}]]}]]}}]]
}
{"@class": "io.seata.rm.datasource.undo.BranchUndoLog","xid": "10.13.24.159:8091:2022944458","branchId": 2022944460,"sqlUndoLogs": ["java.util.ArrayList", [{"@class": "io.seata.rm.datasource.undo.SQLUndoLog","sqlType": "UPDATE","tableName": "account_tbl","beforeImage": {"@class": "io.seata.rm.datasource.sql.struct.TableRecords","tableName": "account_tbl","rows": ["java.util.ArrayList", [{"@class": "io.seata.rm.datasource.sql.struct.Row","fields": ["java.util.ArrayList", [{"@class": "io.seata.rm.datasource.sql.struct.Field","name": "id","keyType": "PrimaryKey","type": 4,"value": 1}, {"@class": "io.seata.rm.datasource.sql.struct.Field","name": "money","keyType": "NULL","type": 4,"value": 999}]]}]]},"afterImage": {"@class": "io.seata.rm.datasource.sql.struct.TableRecords","tableName": "account_tbl","rows": ["java.util.ArrayList", [{"@class": "io.seata.rm.datasource.sql.struct.Row","fields": ["java.util.ArrayList", [{"@class": "io.seata.rm.datasource.sql.struct.Field","name": "id","keyType": "PrimaryKey","type": 4,"value": 1}, {"@class": "io.seata.rm.datasource.sql.struct.Field","name": "money","keyType": "NULL","type": 4,"value": 599}]]}]]}}]]
}
{"@class": "io.seata.rm.datasource.undo.BranchUndoLog","xid": "10.13.24.159:8091:2022944458","branchId": 2022944461,"sqlUndoLogs": ["java.util.ArrayList", [{"@class": "io.seata.rm.datasource.undo.SQLUndoLog","sqlType": "INSERT","tableName": "order_tbl","beforeImage": {"@class": "io.seata.rm.datasource.sql.struct.TableRecords$EmptyTableRecords","tableName": "order_tbl","rows": ["java.util.ArrayList", []]},"afterImage": {"@class": "io.seata.rm.datasource.sql.struct.TableRecords","tableName": "order_tbl","rows": ["java.util.ArrayList", [{"@class": "io.seata.rm.datasource.sql.struct.Row","fields": ["java.util.ArrayList", [{"@class": "io.seata.rm.datasource.sql.struct.Field","name": "id","keyType": "PrimaryKey","type": 4,"value": 1}, {"@class": "io.seata.rm.datasource.sql.struct.Field","name": "user_id","keyType": "NULL","type": 12,"value": "U100001"}, {"@class": "io.seata.rm.datasource.sql.struct.Field","name": "commodity_code","keyType": "NULL","type": 12,"value": "C00321"}, {"@class": "io.seata.rm.datasource.sql.struct.Field","name": "count","keyType": "NULL","type": 4,"value": 2}, {"@class": "io.seata.rm.datasource.sql.struct.Field","name": "money","keyType": "NULL","type": 4,"value": 400}]]}]]}}]]
}

其中,

  • xid:全局事务ID。
  • branchId:分支事务ID,上例中,模拟了3个分支事务,即帐户事务、库存事务和订单事务。
  • beforeImage:全局事务开启前,某表的数据镜像。
  • afterImage:全局事务提交后,某表的数据镜像。

seata-server-0.8.0控制台日志:

2019-09-23 13:30:02.635 INFO [NettyServerNIOWorker_1_8]io.seata.common.loader.EnhancedServiceLoader.loadFile:237 -load Codec[SEATA] extension by class[io.seata.codec.seata.SeataCodec]
2019-09-23 13:30:02.656 INFO [ServerHandlerThread_1_500]io.seata.core.rpc.DefaultServerMessageListenerImpl.onRegRmMessage:114 -rm register success,message:RegisterRMRequest{resourceIds='jdbc:mysql://localhost:3306/fescar_demo', applicationId='dubbo-demo-account-service', transactionServiceGroup='my_test_tx_group'},channel:[id: 0x50a72bc6, L:/127.0.0.1:8091 - R:/127.0.0.1:57990]
2019-09-23 13:30:06.832 INFO [NettyServerNIOWorker_2_8]io.seata.core.rpc.DefaultServerMessageListenerImpl.onRegTmMessage:131 -checkAuth for client:127.0.0.1:58025 vgroup:my_test_tx_group ok
2019-09-23 13:30:43.055 INFO [ServerHandlerThread_2_500]io.seata.core.rpc.DefaultServerMessageListenerImpl.onRegRmMessage:114 -rm register success,message:RegisterRMRequest{resourceIds='jdbc:mysql://localhost:3306/fescar_demo', applicationId='dubbo-demo-storage-service', transactionServiceGroup='my_test_tx_group'},channel:[id: 0x95fcbabd, L:/127.0.0.1:8091 - R:/127.0.0.1:58063]
2019-09-23 13:30:47.421 INFO [NettyServerNIOWorker_4_8]io.seata.core.rpc.DefaultServerMessageListenerImpl.onRegTmMessage:131 -checkAuth for client:127.0.0.1:58105 vgroup:my_test_tx_group ok
2019-09-23 13:31:20.231 INFO [ServerHandlerThread_3_500]io.seata.core.rpc.DefaultServerMessageListenerImpl.onRegRmMessage:114 -rm register success,message:RegisterRMRequest{resourceIds='jdbc:mysql://localhost:3306/fescar_demo', applicationId='dubbo-demo-order-service', transactionServiceGroup='my_test_tx_group'},channel:[id: 0x449ee88a, L:/127.0.0.1:8091 - R:/127.0.0.1:58132]
2019-09-23 13:31:24.532 INFO [NettyServerNIOWorker_6_8]io.seata.core.rpc.DefaultServerMessageListenerImpl.onRegTmMessage:131 -checkAuth for client:127.0.0.1:58187 vgroup:my_test_tx_group ok
2019-09-23 13:32:03.105 INFO [NettyServerNIOWorker_7_8]io.seata.core.rpc.DefaultServerMessageListenerImpl.onRegTmMessage:131 -checkAuth for client:127.0.0.1:58256 vgroup:my_test_tx_group ok
2019-09-23 13:32:03.124 INFO [batchLoggerPrint_1]io.seata.core.rpc.DefaultServerMessageListenerImpl.run:199 -SeataMergeMessage timeout=300000,transactionName=dubbo-demo-tx
,clientIp:127.0.0.1,vgroup:my_test_tx_group2019-09-23 13:32:03.479 INFO [ServerHandlerThread_5_500]io.seata.common.loader.EnhancedServiceLoader.loadFile:237 -load Locker[file] extension by class[io.seata.server.lock.memory.MemoryLocker]
2019-09-23 13:32:03.480 INFO [batchLoggerPrint_1]io.seata.core.rpc.DefaultServerMessageListenerImpl.run:199 -SeataMergeMessage xid=10.13.24.159:8091:2022944458,branchType=AT,resourceId=jdbc:mysql://localhost:3306/fescar_demo,lockKey=storage_tbl:1
,clientIp:127.0.0.1,vgroup:my_test_tx_group2019-09-23 13:32:03.786 INFO [batchLoggerPrint_1]io.seata.core.rpc.DefaultServerMessageListenerImpl.run:199 -SeataMergeMessage xid=10.13.24.159:8091:2022944458,branchId=2022944459,resourceId=null,status=PhaseOne_Done,applicationData=null
,clientIp:127.0.0.1,vgroup:my_test_tx_group2019-09-23 13:32:04.079 INFO [batchLoggerPrint_1]io.seata.core.rpc.DefaultServerMessageListenerImpl.run:199 -SeataMergeMessage xid=10.13.24.159:8091:2022944458,branchType=AT,resourceId=jdbc:mysql://localhost:3306/fescar_demo,lockKey=account_tbl:1
,clientIp:127.0.0.1,vgroup:my_test_tx_group2019-09-23 13:32:04.476 INFO [batchLoggerPrint_1]io.seata.core.rpc.DefaultServerMessageListenerImpl.run:199 -SeataMergeMessage xid=10.13.24.159:8091:2022944458,branchId=2022944460,resourceId=null,status=PhaseOne_Done,applicationData=null
,clientIp:127.0.0.1,vgroup:my_test_tx_group2019-09-23 13:32:04.839 INFO [batchLoggerPrint_1]io.seata.core.rpc.DefaultServerMessageListenerImpl.run:199 -SeataMergeMessage xid=10.13.24.159:8091:2022944458,branchType=AT,resourceId=jdbc:mysql://localhost:3306/fescar_demo,lockKey=order_tbl:1
,clientIp:127.0.0.1,vgroup:my_test_tx_group2019-09-23 13:32:05.053 INFO [batchLoggerPrint_1]io.seata.core.rpc.DefaultServerMessageListenerImpl.run:199 -SeataMergeMessage xid=10.13.24.159:8091:2022944458,branchId=2022944461,resourceId=null,status=PhaseOne_Done,applicationData=null
,clientIp:127.0.0.1,vgroup:my_test_tx_group2019-09-23 13:32:05.069 INFO [batchLoggerPrint_1]io.seata.core.rpc.DefaultServerMessageListenerImpl.run:199 -SeataMergeMessage xid=10.13.24.159:8091:2022944458,extraData=null
,clientIp:127.0.0.1,vgroup:my_test_tx_group2019-09-23 13:32:05.098 INFO [NettyServerNIOWorker_7_8]io.seata.core.rpc.netty.RpcServer.handleDisconnect:300 -127.0.0.1:58256 to server channel inactive.
2019-09-23 13:32:05.099 INFO [NettyServerNIOWorker_7_8]io.seata.core.rpc.netty.RpcServer.handleDisconnect:305 -remove channel:[id: 0x5b96e442, L:0.0.0.0/0.0.0.0:8091 ! R:/127.0.0.1:58256]context:RpcContext{applicationId='dubbo-demo-app', transactionServiceGroup='my_test_tx_group', clientId='dubbo-demo-app:127.0.0.1:58256', channel=[id: 0x5b96e442, L:0.0.0.0/0.0.0.0:8091 ! R:/127.0.0.1:58256], resourceSets=null}
2019-09-23 13:32:05.972 INFO [AsyncCommitting_1]io.seata.server.coordinator.DefaultCore.doGlobalCommit:238 -Global[10.13.24.159:8091:2022944458] committing is successfully done.

模拟异常业务流程

停止seata-server-0.8.0(方便观察日志),停止上述三个服务,把所有表记录清空后,去掉那行注释,再依次启动seata-server-0.8.0和上述三个服务。
运行BusinessService入口 (DubboBusinessTester),由于在最后遇到了运行期异常,所有分支事务都回滚了。可以查看表记录进行验证。

seata-server-0.8.0控制台日志:

2019-09-23 13:53:45.383 INFO [NettyServerNIOWorker_1_8]io.seata.common.loader.EnhancedServiceLoader.loadFile:237 -load Codec[SEATA] extension by class[io.seata.codec.seata.SeataCodec]
2019-09-23 13:53:45.404 INFO [ServerHandlerThread_1_500]io.seata.core.rpc.DefaultServerMessageListenerImpl.onRegRmMessage:114 -rm register success,message:RegisterRMRequest{resourceIds='jdbc:mysql://localhost:3306/fescar_demo', applicationId='dubbo-demo-account-service', transactionServiceGroup='my_test_tx_group'},channel:[id: 0x58cc1116, L:/127.0.0.1:8091 - R:/127.0.0.1:59425]
2019-09-23 13:53:49.420 INFO [NettyServerNIOWorker_2_8]io.seata.core.rpc.DefaultServerMessageListenerImpl.onRegTmMessage:131 -checkAuth for client:127.0.0.1:59462 vgroup:my_test_tx_group ok
2019-09-23 13:54:17.672 INFO [ServerHandlerThread_2_500]io.seata.core.rpc.DefaultServerMessageListenerImpl.onRegRmMessage:114 -rm register success,message:RegisterRMRequest{resourceIds='jdbc:mysql://localhost:3306/fescar_demo', applicationId='dubbo-demo-storage-service', transactionServiceGroup='my_test_tx_group'},channel:[id: 0x8cc121f9, L:/127.0.0.1:8091 - R:/127.0.0.1:59484]
2019-09-23 13:54:21.686 INFO [NettyServerNIOWorker_4_8]io.seata.core.rpc.DefaultServerMessageListenerImpl.onRegTmMessage:131 -checkAuth for client:127.0.0.1:59519 vgroup:my_test_tx_group ok
2019-09-23 13:54:36.421 INFO [ServerHandlerThread_3_500]io.seata.core.rpc.DefaultServerMessageListenerImpl.onRegRmMessage:114 -rm register success,message:RegisterRMRequest{resourceIds='jdbc:mysql://localhost:3306/fescar_demo', applicationId='dubbo-demo-order-service', transactionServiceGroup='my_test_tx_group'},channel:[id: 0x4de3bb59, L:/127.0.0.1:8091 - R:/127.0.0.1:59547]
2019-09-23 13:54:40.656 INFO [NettyServerNIOWorker_6_8]io.seata.core.rpc.DefaultServerMessageListenerImpl.onRegTmMessage:131 -checkAuth for client:127.0.0.1:59594 vgroup:my_test_tx_group ok
2019-09-23 13:56:16.946 INFO [NettyServerNIOWorker_7_8]io.seata.core.rpc.DefaultServerMessageListenerImpl.onRegTmMessage:131 -checkAuth for client:127.0.0.1:59715 vgroup:my_test_tx_group ok
2019-09-23 13:56:16.961 INFO [batchLoggerPrint_1]io.seata.core.rpc.DefaultServerMessageListenerImpl.run:199 -SeataMergeMessage timeout=300000,transactionName=dubbo-demo-tx
,clientIp:127.0.0.1,vgroup:my_test_tx_group2019-09-23 13:56:17.273 INFO [batchLoggerPrint_1]io.seata.core.rpc.DefaultServerMessageListenerImpl.run:199 -SeataMergeMessage xid=10.13.24.159:8091:2022946012,branchType=AT,resourceId=jdbc:mysql://localhost:3306/fescar_demo,lockKey=storage_tbl:1
,clientIp:127.0.0.1,vgroup:my_test_tx_group2019-09-23 13:56:17.275 INFO [ServerHandlerThread_5_500]io.seata.common.loader.EnhancedServiceLoader.loadFile:237 -load Locker[file] extension by class[io.seata.server.lock.memory.MemoryLocker]
2019-09-23 13:56:17.583 INFO [batchLoggerPrint_1]io.seata.core.rpc.DefaultServerMessageListenerImpl.run:199 -SeataMergeMessage xid=10.13.24.159:8091:2022946012,branchId=2022946013,resourceId=null,status=PhaseOne_Done,applicationData=null
,clientIp:127.0.0.1,vgroup:my_test_tx_group2019-09-23 13:56:17.717 INFO [batchLoggerPrint_1]io.seata.core.rpc.DefaultServerMessageListenerImpl.run:199 -SeataMergeMessage xid=10.13.24.159:8091:2022946012,branchType=AT,resourceId=jdbc:mysql://localhost:3306/fescar_demo,lockKey=account_tbl:1
,clientIp:127.0.0.1,vgroup:my_test_tx_group2019-09-23 13:56:18.006 INFO [batchLoggerPrint_1]io.seata.core.rpc.DefaultServerMessageListenerImpl.run:199 -SeataMergeMessage xid=10.13.24.159:8091:2022946012,branchId=2022946014,resourceId=null,status=PhaseOne_Done,applicationData=null
,clientIp:127.0.0.1,vgroup:my_test_tx_group2019-09-23 13:56:18.279 INFO [batchLoggerPrint_1]io.seata.core.rpc.DefaultServerMessageListenerImpl.run:199 -SeataMergeMessage xid=10.13.24.159:8091:2022946012,branchType=AT,resourceId=jdbc:mysql://localhost:3306/fescar_demo,lockKey=order_tbl:1
,clientIp:127.0.0.1,vgroup:my_test_tx_group2019-09-23 13:56:18.490 INFO [batchLoggerPrint_1]io.seata.core.rpc.DefaultServerMessageListenerImpl.run:199 -SeataMergeMessage xid=10.13.24.159:8091:2022946012,branchId=2022946015,resourceId=null,status=PhaseOne_Done,applicationData=null
,clientIp:127.0.0.1,vgroup:my_test_tx_group2019-09-23 13:56:18.504 INFO [batchLoggerPrint_1]io.seata.core.rpc.DefaultServerMessageListenerImpl.run:199 -SeataMergeMessage xid=10.13.24.159:8091:2022946012,extraData=null
,clientIp:127.0.0.1,vgroup:my_test_tx_group2019-09-23 13:56:18.586 INFO [ServerHandlerThread_11_500]io.seata.server.coordinator.DefaultCore.doGlobalRollback:309 -Successfully rollbacked branch BR:2022946015/2022946012
2019-09-23 13:56:18.663 INFO [ServerHandlerThread_11_500]io.seata.server.coordinator.DefaultCore.doGlobalRollback:309 -Successfully rollbacked branch BR:2022946014/2022946012
2019-09-23 13:56:18.740 INFO [ServerHandlerThread_11_500]io.seata.server.coordinator.DefaultCore.doGlobalRollback:309 -Successfully rollbacked branch BR:2022946013/2022946012
2019-09-23 13:56:18.772 INFO [NettyServerNIOWorker_7_8]io.seata.core.rpc.netty.RpcServer.handleDisconnect:300 -127.0.0.1:59715 to server channel inactive.
2019-09-23 13:56:18.773 INFO [NettyServerNIOWorker_7_8]io.seata.core.rpc.netty.RpcServer.handleDisconnect:305 -remove channel:[id: 0x1059d682, L:0.0.0.0/0.0.0.0:8091 ! R:/127.0.0.1:59715]context:RpcContext{applicationId='dubbo-demo-app', transactionServiceGroup='my_test_tx_group', clientId='dubbo-demo-app:127.0.0.1:59715', channel=[id: 0x1059d682, L:0.0.0.0/0.0.0.0:8091 ! R:/127.0.0.1:59715], resourceSets=null}

undo_log_my表数据:

{"@class": "io.seata.rm.datasource.undo.BranchUndoLog","xid": "10.13.24.159:8091:2022946012","branchId": 2022946013,"sqlUndoLogs": ["java.util.ArrayList", [{"@class": "io.seata.rm.datasource.undo.SQLUndoLog","sqlType": "UPDATE","tableName": "storage_tbl","beforeImage": {"@class": "io.seata.rm.datasource.sql.struct.TableRecords","tableName": "storage_tbl","rows": ["java.util.ArrayList", [{"@class": "io.seata.rm.datasource.sql.struct.Row","fields": ["java.util.ArrayList", [{"@class": "io.seata.rm.datasource.sql.struct.Field","name": "id","keyType": "PrimaryKey","type": 4,"value": 1}, {"@class": "io.seata.rm.datasource.sql.struct.Field","name": "count","keyType": "NULL","type": 4,"value": 100}]]}]]},"afterImage": {"@class": "io.seata.rm.datasource.sql.struct.TableRecords","tableName": "storage_tbl","rows": ["java.util.ArrayList", [{"@class": "io.seata.rm.datasource.sql.struct.Row","fields": ["java.util.ArrayList", [{"@class": "io.seata.rm.datasource.sql.struct.Field","name": "id","keyType": "PrimaryKey","type": 4,"value": 1}, {"@class": "io.seata.rm.datasource.sql.struct.Field","name": "count","keyType": "NULL","type": 4,"value": 98}]]}]]}}]]
}
{"@class": "io.seata.rm.datasource.undo.BranchUndoLog","xid": "10.13.24.159:8091:2022946012","branchId": 2022946014,"sqlUndoLogs": ["java.util.ArrayList", [{"@class": "io.seata.rm.datasource.undo.SQLUndoLog","sqlType": "UPDATE","tableName": "account_tbl","beforeImage": {"@class": "io.seata.rm.datasource.sql.struct.TableRecords","tableName": "account_tbl","rows": ["java.util.ArrayList", [{"@class": "io.seata.rm.datasource.sql.struct.Row","fields": ["java.util.ArrayList", [{"@class": "io.seata.rm.datasource.sql.struct.Field","name": "id","keyType": "PrimaryKey","type": 4,"value": 1}, {"@class": "io.seata.rm.datasource.sql.struct.Field","name": "money","keyType": "NULL","type": 4,"value": 999}]]}]]},"afterImage": {"@class": "io.seata.rm.datasource.sql.struct.TableRecords","tableName": "account_tbl","rows": ["java.util.ArrayList", [{"@class": "io.seata.rm.datasource.sql.struct.Row","fields": ["java.util.ArrayList", [{"@class": "io.seata.rm.datasource.sql.struct.Field","name": "id","keyType": "PrimaryKey","type": 4,"value": 1}, {"@class": "io.seata.rm.datasource.sql.struct.Field","name": "money","keyType": "NULL","type": 4,"value": 599}]]}]]}}]]
}
{"@class": "io.seata.rm.datasource.undo.BranchUndoLog","xid": "10.13.24.159:8091:2022946012","branchId": 2022946015,"sqlUndoLogs": ["java.util.ArrayList", [{"@class": "io.seata.rm.datasource.undo.SQLUndoLog","sqlType": "INSERT","tableName": "order_tbl","beforeImage": {"@class": "io.seata.rm.datasource.sql.struct.TableRecords$EmptyTableRecords","tableName": "order_tbl","rows": ["java.util.ArrayList", []]},"afterImage": {"@class": "io.seata.rm.datasource.sql.struct.TableRecords","tableName": "order_tbl","rows": ["java.util.ArrayList", [{"@class": "io.seata.rm.datasource.sql.struct.Row","fields": ["java.util.ArrayList", [{"@class": "io.seata.rm.datasource.sql.struct.Field","name": "id","keyType": "PrimaryKey","type": 4,"value": 1}, {"@class": "io.seata.rm.datasource.sql.struct.Field","name": "user_id","keyType": "NULL","type": 12,"value": "U100001"}, {"@class": "io.seata.rm.datasource.sql.struct.Field","name": "commodity_code","keyType": "NULL","type": 12,"value": "C00321"}, {"@class": "io.seata.rm.datasource.sql.struct.Field","name": "count","keyType": "NULL","type": 4,"value": 2}, {"@class": "io.seata.rm.datasource.sql.struct.Field","name": "money","keyType": "NULL","type": 4,"value": 400}]]}]]}}]]
}

2019.10.15,更新:
在三个IP上,分别建库和表,正常、异常流程均可以运行。

IP/库名
jdbc:mysql://localhost:3306/fescar_demo account_tbl、undo_log
jdbc:mysql://x.x.x.x:3306/fescar_demo2 storage_tbl、undo_log
jdbc:mysql://y.y.y.y.y:3306/fescar_demo3 order_tbl、undo_log

可以把D:\ThirdPartiesFiles\seata\seata-server-0.8.0\conf\logback.xml里的日志级别改为DEBUG,摘录C:\Users\xxxxxx\logs\seata\seata-server.log:

2019-10-15 16:51:55,914 DEBUG read:RegisterRMRequest{resourceIds='jdbc:mysql://localhost:3306/fescar_demo', applicationId='dubbo-demo-account-service', transactionServiceGroup='my_test_tx_group'}2019-10-15 16:51:55,915 DEBUG io.seata.core.rpc.netty.RpcServer@e020b84 msgId:1, body:RegisterRMRequest{resourceIds='jdbc:mysql://localhost:3306/fescar_demo', applicationId='dubbo-demo-account-service', transactionServiceGroup='my_test_tx_group'}2019-10-15 16:51:55,942 INFO rm register success,message:RegisterRMRequest{resourceIds='jdbc:mysql://localhost:3306/fescar_demo', applicationId='dubbo-demo-account-service', transactionServiceGroup='my_test_tx_group'},channel:[id: 0x2584e631, L:/127.0.0.1:8091 - R:/127.0.0.1:64011]2019-10-15 16:52:00,142 DEBUG read:RegisterTMRequest{applicationId='dubbo-demo-account-service', transactionServiceGroup='my_test_tx_group'}2019-10-15 16:52:00,144 INFO checkAuth for client:127.0.0.1:64441 vgroup:my_test_tx_group ok2019-10-15 16:52:00,145 DEBUG send response:version=0.8.0,extraData=null,identified=true,resultCode=null,msg=null,channel:[id: 0x0c91081c, L:/127.0.0.1:8091 - R:/127.0.0.1:64441]略2019-10-15 17:06:59,383 DEBUG read:RegisterRMRequest{resourceIds='jdbc:mysql://x.x.x.x:3306/fescar_demo2', applicationId='dubbo-demo-storage-service', transactionServiceGroup='my_test_tx_group'}2019-10-15 17:06:59,387 DEBUG io.seata.core.rpc.netty.RpcServer@e020b84 msgId:1, body:RegisterRMRequest{resourceIds='jdbc:mysql://x.x.x.x:3306/fescar_demo2', applicationId='dubbo-demo-storage-service', transactionServiceGroup='my_test_tx_group'}2019-10-15 17:06:59,389 DEBUG send response:version=0.8.0,extraData=null,identified=true,resultCode=null,msg=null,channel:[id: 0xf4b11025, L:/127.0.0.1:8091 - R:/127.0.0.1:49825]2019-10-15 17:06:59,390 INFO rm register success,message:RegisterRMRequest{resourceIds='jdbc:mysql://x.x.x.x:3306/fescar_demo2', applicationId='dubbo-demo-storage-service', transactionServiceGroup='my_test_tx_group'},channel:[id: 0xf4b11025, L:/127.0.0.1:8091 - R:/127.0.0.1:49825]2019-10-15 17:07:03,515 DEBUG read:RegisterTMRequest{applicationId='dubbo-demo-storage-service', transactionServiceGroup='my_test_tx_group'}2019-10-15 17:07:03,519 INFO checkAuth for client:127.0.0.1:50843 vgroup:my_test_tx_group ok2019-10-15 17:07:03,519 DEBUG send response:version=0.8.0,extraData=null,identified=true,resultCode=null,msg=null,channel:[id: 0x0f621fd8, L:/127.0.0.1:8091 - R:/127.0.0.1:50843]略2019-10-15 17:08:45,880 DEBUG read:RegisterRMRequest{resourceIds='jdbc:mysql://y.y.y.y:3306/fescar_demo3', applicationId='dubbo-demo-order-service', transactionServiceGroup='my_test_tx_group'}2019-10-15 17:08:45,886 DEBUG io.seata.core.rpc.netty.RpcServer@e020b84 msgId:1, body:RegisterRMRequest{resourceIds='jdbc:mysql://y.y.y.y:3306/fescar_demo3', applicationId='dubbo-demo-order-service', transactionServiceGroup='my_test_tx_group'}2019-10-15 17:08:45,894 DEBUG send response:version=0.8.0,extraData=null,identified=true,resultCode=null,msg=null,channel:[id: 0x7817d65a, L:/127.0.0.1:8091 - R:/127.0.0.1:62315]2019-10-15 17:08:45,897 INFO rm register success,message:RegisterRMRequest{resourceIds='jdbc:mysql://y.y.y.y:3306/fescar_demo3', applicationId='dubbo-demo-order-service', transactionServiceGroup='my_test_tx_group'},channel:[id: 0x7817d65a, L:/127.0.0.1:8091 - R:/127.0.0.1:62315]2019-10-15 17:08:49,660 DEBUG read:RegisterTMRequest{applicationId='dubbo-demo-order-service', transactionServiceGroup='my_test_tx_group'}2019-10-15 17:08:49,661 INFO checkAuth for client:127.0.0.1:63286 vgroup:my_test_tx_group ok2019-10-15 17:08:49,663 DEBUG send response:version=0.8.0,extraData=null,identified=true,resultCode=null,msg=null,channel:[id: 0x821112d2, L:/127.0.0.1:8091 - R:/127.0.0.1:63286]略2019-10-15 17:23:41,174 DEBUG read:RegisterTMRequest{applicationId='dubbo-demo-app', transactionServiceGroup='my_test_tx_group'}2019-10-15 17:23:41,175 INFO checkAuth for client:127.0.0.1:63399 vgroup:my_test_tx_group ok2019-10-15 17:23:41,177 DEBUG send response:version=0.8.0,extraData=null,identified=true,resultCode=null,msg=null,channel:[id: 0x36c93da2, L:/127.0.0.1:8091 - R:/127.0.0.1:63399]2019-10-15 17:23:41,189 DEBUG read:SeataMergeMessage timeout=300000,transactionName=dubbo-demo-tx2019-10-15 17:23:41,190 DEBUG io.seata.core.rpc.netty.RpcServer@e020b84 msgId:3, body:SeataMergeMessage timeout=300000,transactionName=dubbo-demo-tx2019-10-15 17:23:41,200 DEBUG server received:SeataMergeMessage timeout=300000,transactionName=dubbo-demo-tx
,clientIp:127.0.0.1,vgroup:my_test_tx_group2019-10-15 17:23:41,208 DEBUG MANAGER[root.data] SESSION[io.seata.server.session.GlobalSession@109822dd] GLOBAL_ADD2019-10-15 17:23:41,280 DEBUG send response:MergeResultMessage xid=10.13.24.159:8091:2024857359;extraData=null;
,channel:[id: 0x36c93da2, L:/127.0.0.1:8091 - R:/127.0.0.1:63399]2019-10-15 17:23:41,334 DEBUG Transaction Timeout Check Begin: 12019-10-15 17:23:41,519 DEBUG 10.13.24.159:8091:2024857359 Begin 1571131421207 3000002019-10-15 17:23:41,558 DEBUG Transaction Timeout Check End. 2019-10-15 17:23:41,832 DEBUG read:SeataMergeMessage xid=10.13.24.159:8091:2024857359,branchType=AT,resourceId=jdbc:mysql://x.x.x.x:3306/fescar_demo2,lockKey=storage_tbl:32019-10-15 17:23:41,844 DEBUG io.seata.core.rpc.netty.RpcServer@e020b84 msgId:103, body:SeataMergeMessage xid=10.13.24.159:8091:2024857359,branchType=AT,resourceId=jdbc:mysql://x.x.x.x:3306/fescar_demo2,lockKey=storage_tbl:32019-10-15 17:23:41,860 DEBUG server received:SeataMergeMessage xid=10.13.24.159:8091:2024857359,branchType=AT,resourceId=jdbc:mysql://x.x.x.x:3306/fescar_demo2,lockKey=storage_tbl:3
,clientIp:127.0.0.1,vgroup:my_test_tx_group2019-10-15 17:23:41,898 INFO load Locker[file] extension by class[io.seata.server.lock.memory.MemoryLocker]2019-10-15 17:23:41,900 DEBUG MANAGER[root.data] SESSION[BR:2024857360/2024857359] BRANCH_ADD2019-10-15 17:23:41,905 DEBUG send response:MergeResultMessage BranchRegisterResponse: branchId=2024857360,result code =Success,getMsg =null
,channel:[id: 0xf4b11025, L:/127.0.0.1:8091 - R:/127.0.0.1:49825]2019-10-15 17:23:42,179 DEBUG read:SeataMergeMessage xid=10.13.24.159:8091:2024857359,branchId=2024857360,resourceId=null,status=PhaseOne_Done,applicationData=null2019-10-15 17:23:42,181 DEBUG io.seata.core.rpc.netty.RpcServer@e020b84 msgId:105, body:SeataMergeMessage xid=10.13.24.159:8091:2024857359,branchId=2024857360,resourceId=null,status=PhaseOne_Done,applicationData=null2019-10-15 17:23:42,182 DEBUG server received:SeataMergeMessage xid=10.13.24.159:8091:2024857359,branchId=2024857360,resourceId=null,status=PhaseOne_Done,applicationData=null
,clientIp:127.0.0.1,vgroup:my_test_tx_group2019-10-15 17:23:42,183 DEBUG MANAGER[root.data] SESSION[BR:2024857360/2024857359] GLOBAL_ADD2019-10-15 17:23:42,183 DEBUG send response:MergeResultMessage
,channel:[id: 0xf4b11025, L:/127.0.0.1:8091 - R:/127.0.0.1:49825]2019-10-15 17:23:42,287 DEBUG Transaction Timeout Check Begin: 12019-10-15 17:23:42,294 DEBUG 10.13.24.159:8091:2024857359 Begin 1571131421207 3000002019-10-15 17:23:42,323 DEBUG Transaction Timeout Check End. 2019-10-15 17:23:42,433 DEBUG read:SeataMergeMessage xid=10.13.24.159:8091:2024857359,branchType=AT,resourceId=jdbc:mysql://localhost:3306/fescar_demo,lockKey=account_tbl:12019-10-15 17:23:42,463 DEBUG io.seata.core.rpc.netty.RpcServer@e020b84 msgId:193, body:SeataMergeMessage xid=10.13.24.159:8091:2024857359,branchType=AT,resourceId=jdbc:mysql://localhost:3306/fescar_demo,lockKey=account_tbl:12019-10-15 17:23:42,522 DEBUG server received:SeataMergeMessage xid=10.13.24.159:8091:2024857359,branchType=AT,resourceId=jdbc:mysql://localhost:3306/fescar_demo,lockKey=account_tbl:1
,clientIp:127.0.0.1,vgroup:my_test_tx_group2019-10-15 17:23:42,540 DEBUG MANAGER[root.data] SESSION[BR:2024857361/2024857359] BRANCH_ADD2019-10-15 17:23:42,581 DEBUG send response:MergeResultMessage BranchRegisterResponse: branchId=2024857361,result code =Success,getMsg =null
,channel:[id: 0x2584e631, L:/127.0.0.1:8091 - R:/127.0.0.1:64011]2019-10-15 17:23:42,861 DEBUG read:SeataMergeMessage xid=10.13.24.159:8091:2024857359,branchId=2024857361,resourceId=null,status=PhaseOne_Done,applicationData=null2019-10-15 17:23:42,861 DEBUG io.seata.core.rpc.netty.RpcServer@e020b84 msgId:195, body:SeataMergeMessage xid=10.13.24.159:8091:2024857359,branchId=2024857361,resourceId=null,status=PhaseOne_Done,applicationData=null2019-10-15 17:23:42,863 DEBUG server received:SeataMergeMessage xid=10.13.24.159:8091:2024857359,branchId=2024857361,resourceId=null,status=PhaseOne_Done,applicationData=null
,clientIp:127.0.0.1,vgroup:my_test_tx_group2019-10-15 17:23:42,865 DEBUG MANAGER[root.data] SESSION[BR:2024857361/2024857359] GLOBAL_ADD2019-10-15 17:23:42,866 DEBUG send response:MergeResultMessage
,channel:[id: 0x2584e631, L:/127.0.0.1:8091 - R:/127.0.0.1:64011]2019-10-15 17:23:43,213 DEBUG read:SeataMergeMessage xid=10.13.24.159:8091:2024857359,branchType=AT,resourceId=jdbc:mysql://y.y.y.y:3306/fescar_demo3,lockKey=order_tbl:22019-10-15 17:23:43,217 DEBUG io.seata.core.rpc.netty.RpcServer@e020b84 msgId:92, body:SeataMergeMessage xid=10.13.24.159:8091:2024857359,branchType=AT,resourceId=jdbc:mysql://y.y.y.y:3306/fescar_demo3,lockKey=order_tbl:22019-10-15 17:23:43,218 DEBUG server received:SeataMergeMessage xid=10.13.24.159:8091:2024857359,branchType=AT,resourceId=jdbc:mysql://y.y.y.y:3306/fescar_demo3,lockKey=order_tbl:2
,clientIp:127.0.0.1,vgroup:my_test_tx_group2019-10-15 17:23:43,222 DEBUG MANAGER[root.data] SESSION[BR:2024857362/2024857359] BRANCH_ADD2019-10-15 17:23:43,222 DEBUG send response:MergeResultMessage BranchRegisterResponse: branchId=2024857362,result code =Success,getMsg =null
,channel:[id: 0x7817d65a, L:/127.0.0.1:8091 - R:/127.0.0.1:62315]2019-10-15 17:23:43,287 DEBUG Transaction Timeout Check Begin: 12019-10-15 17:23:43,287 DEBUG 10.13.24.159:8091:2024857359 Begin 1571131421207 3000002019-10-15 17:23:43,288 DEBUG Transaction Timeout Check End. 2019-10-15 17:23:43,494 DEBUG read:SeataMergeMessage xid=10.13.24.159:8091:2024857359,branchId=2024857362,resourceId=null,status=PhaseOne_Done,applicationData=null2019-10-15 17:23:43,495 DEBUG io.seata.core.rpc.netty.RpcServer@e020b84 msgId:94, body:SeataMergeMessage xid=10.13.24.159:8091:2024857359,branchId=2024857362,resourceId=null,status=PhaseOne_Done,applicationData=null2019-10-15 17:23:43,495 DEBUG server received:SeataMergeMessage xid=10.13.24.159:8091:2024857359,branchId=2024857362,resourceId=null,status=PhaseOne_Done,applicationData=null
,clientIp:127.0.0.1,vgroup:my_test_tx_group2019-10-15 17:23:43,496 DEBUG MANAGER[root.data] SESSION[BR:2024857362/2024857359] GLOBAL_ADD2019-10-15 17:23:43,498 DEBUG send response:MergeResultMessage
,channel:[id: 0x7817d65a, L:/127.0.0.1:8091 - R:/127.0.0.1:62315]2019-10-15 17:23:43,525 DEBUG read:SeataMergeMessage xid=10.13.24.159:8091:2024857359,extraData=null2019-10-15 17:23:43,526 DEBUG io.seata.core.rpc.netty.RpcServer@e020b84 msgId:5, body:SeataMergeMessage xid=10.13.24.159:8091:2024857359,extraData=null2019-10-15 17:23:43,528 DEBUG server received:SeataMergeMessage xid=10.13.24.159:8091:2024857359,extraData=null
,clientIp:127.0.0.1,vgroup:my_test_tx_group2019-10-15 17:23:43,532 DEBUG MANAGER[root.data] SESSION[io.seata.server.session.GlobalSession@109822dd] GLOBAL_UPDATE2019-10-15 17:23:43,532 DEBUG MANAGER[async.commit.data] SESSION[io.seata.server.session.GlobalSession@109822dd] GLOBAL_ADD2019-10-15 17:23:43,532 DEBUG MANAGER[async.commit.data] SESSION[io.seata.server.session.GlobalSession@109822dd] GLOBAL_UPDATE2019-10-15 17:23:43,533 DEBUG MANAGER[root.data] SESSION[io.seata.server.session.GlobalSession@109822dd] GLOBAL_UPDATE2019-10-15 17:23:43,533 DEBUG send response:MergeResultMessage globalStatus=Committed,ResultCode=Success,Msg=null
,channel:[id: 0x36c93da2, L:/127.0.0.1:8091 - R:/127.0.0.1:63399]2019-10-15 17:23:43,571 DEBUG inactive:ChannelHandlerContext(RpcServer#0, [id: 0x36c93da2, L:/127.0.0.1:8091 ! R:/127.0.0.1:63399])2019-10-15 17:23:43,574 INFO 127.0.0.1:63399 to server channel inactive.2019-10-15 17:23:43,579 INFO remove channel:[id: 0x36c93da2, L:/127.0.0.1:8091 ! R:/127.0.0.1:63399]context:RpcContext{applicationId='dubbo-demo-app', transactionServiceGroup='my_test_tx_group', clientId='dubbo-demo-app:127.0.0.1:63399', channel=[id: 0x36c93da2, L:/127.0.0.1:8091 ! R:/127.0.0.1:63399], resourceSets=null}2019-10-15 17:23:43,624 DEBUG read:services ping2019-10-15 17:23:43,625 DEBUG send response:services pong,channel:[id: 0x0f621fd8, L:/127.0.0.1:8091 - R:/127.0.0.1:50843]2019-10-15 17:23:43,625 DEBUG received PING from /127.0.0.1:508432019-10-15 17:23:44,287 DEBUG Transaction Timeout Check Begin: 12019-10-15 17:23:44,287 DEBUG Just got exactly the one [id: 0xf4b11025, L:/127.0.0.1:8091 - R:/127.0.0.1:49825] for dubbo-demo-storage-service:127.0.0.1:498252019-10-15 17:23:44,299 DEBUG 10.13.24.159:8091:2024857359 AsyncCommitting 1571131421207 3000002019-10-15 17:23:44,302 DEBUG Transaction Timeout Check End. 2019-10-15 17:23:44,319 DEBUG read:xid=10.13.24.159:8091:2024857359,branchId=2024857360,branchStatus=PhaseTwo_Committed,result code =Success,getMsg =null2019-10-15 17:23:44,320 DEBUG io.seata.core.rpc.netty.RpcServer@e020b84 msgId:1, future :io.seata.core.protocol.MessageFuture@1187af3c, body:xid=10.13.24.159:8091:2024857359,branchId=2024857360,branchStatus=PhaseTwo_Committed,result code =Success,getMsg =null2019-10-15 17:23:44,321 DEBUG MANAGER[async.commit.data] SESSION[BR:2024857360/2024857359] GLOBAL_ADD2019-10-15 17:23:44,321 DEBUG MANAGER[root.data] SESSION[BR:2024857360/2024857359] GLOBAL_ADD2019-10-15 17:23:44,322 DEBUG Just got exactly the one [id: 0x2584e631, L:/127.0.0.1:8091 - R:/127.0.0.1:64011] for dubbo-demo-account-service:127.0.0.1:640112019-10-15 17:23:44,337 DEBUG read:xid=10.13.24.159:8091:2024857359,branchId=2024857361,branchStatus=PhaseTwo_Committed,result code =Success,getMsg =null2019-10-15 17:23:44,338 DEBUG io.seata.core.rpc.netty.RpcServer@e020b84 msgId:2, future :io.seata.core.protocol.MessageFuture@43ae2d5, body:xid=10.13.24.159:8091:2024857359,branchId=2024857361,branchStatus=PhaseTwo_Committed,result code =Success,getMsg =null2019-10-15 17:23:44,338 DEBUG MANAGER[async.commit.data] SESSION[BR:2024857361/2024857359] GLOBAL_ADD2019-10-15 17:23:44,339 DEBUG MANAGER[root.data] SESSION[BR:2024857361/2024857359] GLOBAL_ADD2019-10-15 17:23:44,339 DEBUG Just got exactly the one [id: 0x7817d65a, L:/127.0.0.1:8091 - R:/127.0.0.1:62315] for dubbo-demo-order-service:127.0.0.1:623152019-10-15 17:23:44,346 DEBUG read:xid=10.13.24.159:8091:2024857359,branchId=2024857362,branchStatus=PhaseTwo_Committed,result code =Success,getMsg =null2019-10-15 17:23:44,347 DEBUG io.seata.core.rpc.netty.RpcServer@e020b84 msgId:3, future :io.seata.core.protocol.MessageFuture@57cd9c8d, body:xid=10.13.24.159:8091:2024857359,branchId=2024857362,branchStatus=PhaseTwo_Committed,result code =Success,getMsg =null2019-10-15 17:23:44,348 DEBUG MANAGER[async.commit.data] SESSION[BR:2024857362/2024857359] GLOBAL_ADD2019-10-15 17:23:44,348 DEBUG MANAGER[root.data] SESSION[BR:2024857362/2024857359] GLOBAL_ADD2019-10-15 17:23:44,348 DEBUG MANAGER[async.commit.data] SESSION[io.seata.server.session.GlobalSession@109822dd] GLOBAL_UPDATE2019-10-15 17:23:44,349 DEBUG MANAGER[root.data] SESSION[io.seata.server.session.GlobalSession@109822dd] GLOBAL_UPDATE2019-10-15 17:23:44,359 DEBUG MANAGER[async.commit.data] SESSION[io.seata.server.session.GlobalSession@109822dd] GLOBAL_REMOVE2019-10-15 17:23:44,360 DEBUG MANAGER[root.data] SESSION[io.seata.server.session.GlobalSession@109822dd] GLOBAL_REMOVE2019-10-15 17:23:44,360 INFO Global[10.13.24.159:8091:2024857359] committing is successfully done.

实践《如何使用Seata保证Dubbo微服务间的一致性》相关推荐

  1. 实践:《从头到脚撸一个多人视频聊天 — 前端 WebRTC 实战(一)》

    2019独角兽企业重金招聘Python工程师标准>>> 请先阅读原文,链接:从头到脚撸一个多人视频聊天 - 前端 WebRTC 实战(一),本文只涉及实践过程中的问题 1.video ...

  2. 【从头到脚】撸一个多人视频聊天 — 前端 WebRTC 实战(一)

    前言 [ 从头到脚 ]会作为一个系列文章来发布,它包括但不限于 WebRTC 多人视频,预计会有: WebRTC 实战(一):也就是本期,主要是基础讲解以及一对一的本地对等连接,网络对等连接. Web ...

  3. 从头到脚撸一个多人视频聊天 — WebRTC 实战(一)

    作者:江三疯,知乎.掘金账号同名,点击阅读原文查看作者 github. 前言 [ 从头到脚 ]会作为一个系列文章来发布,它包括但不限于 WebRTC 多人视频,预计会有: WebRTC 实战(一):也 ...

  4. 教你用WebRTC撸一个多人视频聊天

    之前公司准备用 webRTC 来实现视频聊天,研究了几天,撸了个 demo 出来,(虽然最后并没有采用这项技术,囧),但是还是写一个出来吧! WebRTC简单介绍 WebRTC (Web Real-T ...

  5. 【游戏开发实战】Unity从零开发多人视频聊天功能,无聊了就和自己视频聊天(附源码 | Mirror | 多人视频 | 详细教程)

    文章目录 一.前言 二.思考问题与解决方案 1.思考问题 2.解决方案 2.1.Unity中如何开启摄像头并对图像进行采样 2.2.图像如何中转给其他客户端 2.3.如何实现清晰度切换 2.4.客户端 ...

  6. Android 集成 Agora SDK 快速体验 RTC 版多人视频聊天|掘金技术征文

    RTC (Real-Time Communication) 作为实时通讯领域的"新贵",在互动直播.远程控制.多人视频会议.屏幕共享等领域广受好评,如果你还不了解 RTC ,Tak ...

  7. 如何简单的创建一个多人在线聊天室

    学习目标: 在本教程中,我们将要使用PHP和jQuery创建一个简单的在线聊天工具. 这种实用性的模块对于你想要有实时在线客户支持系统的网站可以说是完美. 废话不多说直接开始. 步骤1:HTML的代码 ...

  8. WebRTC实现多人视频聊天

    写在前面 实现房间内人员的视频聊天,由于并未很完善,所以需要严格按照步骤来,当然基于此完善,就是时间的问题了. 架构 整个设计架构如下: 图片来自于参考博文.我使用的是第一种Mesh 架构,无需任何流 ...

  9. (Agora声网)多人视频聊天应用的开发(三)多人聊天

    转载于:Android多人视频聊天应用的开发(三)多人聊天-玖哥的书房-51CTO博客 http://blog.51cto.com/dongfeng9ge/2104587 本系列文章结合声网官方在Gi ...

  10. (Agora声网)多人视频聊天应用的开发(二)一对一聊天

    转载于:Android多人视频聊天应用的开发(二)一对一聊天-玖哥的书房-51CTO博客 http://blog.51cto.com/dongfeng9ge/2095626 本系列文章结合声网官方在G ...

最新文章

  1. 你写的接口都测试吗?测什么?怎么测?
  2. Linq之Lambda表达式初步认识
  3. 雪城大学信息安全讲义 3.2 Set-UID 程序的漏洞
  4. 电子计算机专业211大学,这所高校不是211,但“计算机”实力远超985,被称“IT人才摇篮”...
  5. 思岚科技受邀2018高交会 携多项“黑科技”亮相
  6. python中定义类的关键字_在Python中,定义一个类使用什么关键字?
  7. DSP28335学习记录(二)——外部中断和定时器中断
  8. 【eoeAndroid社区索引】android数据存储之SQLite教程实例汇总
  9. 泛微服务器运维监控,泛微协同平台E-cology8后台维护手册-流程引擎(261页)-原创力文档...
  10. 【CMD】ping通ip
  11. 齐次线性方程组和非齐次线性方程组
  12. 两只小企鹅(Python实现)
  13. 重庆云阳2021云中高考成绩查询,2021年云阳县高考状元是谁及其成绩名单
  14. 华为研究院19级研究员几年心得终成趣谈网络协议文档
  15. html无边框网格,table没有网格线_html/css_WEB-ITnose
  16. 中鑫优配热点前瞻:循环经济+降解塑料+甲酸概念+高铁轨交
  17. 离散数学 极大元,极小元,最大元,最小元,上界,上确界,下界,下确界
  18. 孙陶然:有能力的第三个标准是有亮点
  19. CGB2104-Day20
  20. ExtJs之数据和ComboBox控件

热门文章

  1. 塔望3W消费战略全案丨阳澄湖牌大闸蟹:承诺就是价值,打响官方第一枪
  2. 数据架构:数据中心 主备、双活
  3. AEJoy —— 详解 AE 如何将 png 序列帧导出为 SVGA 动画文件
  4. javascript冷门吗_冷门JS技巧
  5. JBE、JNBE、JA、JL指令详解(从原理上)
  6. 洛谷P2678 Java解法
  7. XGBoost原理介绍
  8. fpga 级联fifo(VHDL)
  9. linux上运行gfortran,linux – gfortran:在64位系统中编译32位可执行文件
  10. 长城皮卡品牌CEO张昊保:皮卡是一个独特的品类,想玩门槛很高