RedTx - SpringCloud 分布式事务 构件 分享

在使用spring cloud 分布式 app时候, 对于跨app的transaction管理, 可以使用阿里的SETA, 也就是阿里开源分布式事务框架FESCAR,
https://github.com/seata/seata

只是有时候只需要其中一小部分功能, 不想复杂化。

本文介绍的就是一个简化的分布式事务构件RedTx.
https://github.com/dong099/RedTx

steps to use RedTX open source projects

新建 RedTx server(refer to consul-service-mgr)
  1. pom.xml

  com.sc
  redtx-mgr
  1.0

  1. add one annotation -@RedtxServer on springboot main class
@RedtxServer
@SpringBootApplication
public class RedTxServer {
...
}
  1. check the sample configuration - application.yml (redis and host/port setup)
redtx:
  mgr:
    host: ${REDTX_SERVER_NAME:172.10.1.63}
    port: ${REDTX_SERVER_PORT:9011}
    txTimeout: 6000
  1. start this app, it should show:
=========================================================
RedTx Server runs on hotst/port: 172.10.1.63:9011 
=========================================================
新建 RedTx client app (refer to consul-service-a/b/c)
  1. pom.xml

  com.sc
  redtx-core
  1.0

  1. add annotations

a). springboot main class - @EnableRedTx

@EnableRedTx
@SpringBootApplication
public class ServiceAApplication {
...
}

b). transaction method on service class - @RedTxTransaction

@Service
@Slf4j
public class DemoServiceImpl implements DemoService {
 
    @Autowired
    private FeignServiceBClient serviceBClient;
    
    @Autowired
    private FeignServiceCClient serviceCClient;

    @Override
    @RedTxTransaction
    public String execRedTx(String value, String rollbackFlag) {
        
        //codes on this section
        log.debug("now enter into A - service - {}, {}", value, rollbackFlag);
        
        String bResult = serviceBClient.runRedTx(value);        
        log.debug("now called B - service- Result - {}", bResult);
        
        String cResult = serviceCClient.runRedTx(value);
        log.debug("now called C - service- Result - {}", cResult);
     
        return "success";
    }
}
  1. check the configuration pointing to RedTx Server
redtx:
  client:
    tx-timeout: 30000
    mgrAddrs: ${REDTX_SERVER:172.10.1.63:9011}
  1. start this client app, it will show:
=========================================================
Netty Client connected to server successfully! RedtxClientConfig [txTimeout=6000, mgrAddrs=172.10.1.63:9011, txSyncCallTimeout=3000]
=========================================================

下文提供的是调试结果简介

启动RedTx Server and spring cloud apps
[root@hadoopnode4 sts]# export REDTX_SERVER=172.10.1.63:9011
[root@hadoopnode4 sts]# java -jar consul-service-a.jar 
[root@hadoopnode4 sts]# java -jar consul-service-b.jar 
[root@hadoopnode4 sts]# java -jar consul-service-c.jar 

[root@hadoopnode3 sts]# export REDTX_SERVER_NAME=172.10.1.63
[root@hadoopnode3 sts]# export REDTX_SERVER_PORT=9011
[root@hadoopnode3 sts]# java -jar consul-service-mgr.jar 
app部署情况一览
image.png
client/server 启动没有先后, 会自动彼此重连
image.png
启动测试url

失败(rollback设置为true, 或者先填入db等同的重复key数据):

curl -i -H "Authorization: Bearer 1b87cdd8-39f5-46f1-b0a2-87f374a2793d" http://172.10.28.8:8900/svca/runRedTx -d "value=mygod72&rollbackFlag=false"
HTTP/1.1 200 OK
X-RateLimit-Remaining: 3
X-RateLimit-Burst-Capacity: 4
X-RateLimit-Replenish-Rate: 4
Content-Type: application/json;charset=UTF-8
Content-Length: 112

{"resultObj":"NoObj","resultCode":"fail","resultMessage":"Sorry, the network has some issue, please try again!"}

成功:

curl -i -H "Authorization: Bearer 1b87cdd8-39f5-46f1-b0a2-87f374a2793d" http://172.10.28.8:8900/svca/runRedTx -d "value=mygod73&rollbackFlag=false"
HTTP/1.1 200 OK
X-RateLimit-Remaining: 3
X-RateLimit-Burst-Capacity: 4
X-RateLimit-Replenish-Rate: 4
Set-Cookie: JSESSIONID=73AD3811B7E8722BC7F0A632E77F3621; Path=/; HttpOnly
X-Content-Type-Options: nosniff
X-XSS-Protection: 1; mode=block
Cache-Control: no-cache, no-store, max-age=0, must-revalidate
Pragma: no-cache
Expires: 0
X-Frame-Options: DENY
Content-Type: text/plain;charset=UTF-8
Content-Length: 7
Date: Fri, 12 Jul 2019 10:15:21 GMT
success
检查每个db table数据插入情况, 应该是一致的
查看日志 (失败部分 consul-service-a.log)

[2019-07-12 18:11:58:315] [INFO ] [Thread: main] [method:com.redtx.core.netty.NettyClientBootstrap.run(NettyClientBootstrap.java:85)]
=========================================================

[2019-07-12 18:11:58:315] [INFO ] [Thread: main] [method:com.redtx.core.netty.NettyClientBootstrap.run(NettyClientBootstrap.java:86)]
Netty Client connected to server successfully! RedtxClientConfig [txTimeout=30000, mgrAddrs=172.10.1.63:9011, txSyncCallTimeout=3000]

[2019-07-12 18:11:58:316] [INFO ] [Thread: main] [method:com.redtx.core.netty.NettyClientBootstrap.run(NettyClientBootstrap.java:87)]
=========================================================

[2019-07-12 18:13:03:229] [DEBUG] [Thread: http-nio-8901-exec-7] [method:com.redtx.core.http.CallChainUtil.callGetter(CallChainUtil.java:40)]
getting groupId:

[2019-07-12 18:13:03:294] [DEBUG] [Thread: http-nio-8901-exec-7] [method:com.redtx.core.aop.TransactionAspect.transactionRunning(TransactionAspect.java:51)]
now get into AOP transactionRunning [value, rollbackFlag], [mygod72, false] 

[2019-07-12 18:13:03:298] [DEBUG] [Thread: http-nio-8901-exec-7] [method:com.redtx.core.tx.RedTxInfo.getFromCache(RedTxInfo.java:48)]
get txMethodId RedTxInfo [targetClazz=class com.sc.svca.service.DemoServiceImpl, businessMethod=public java.lang.String com.sc.svca.service.DemoServiceImpl.execRedTx(java.lang.String,java.lang.String), txMethodId=String com.sc.svca.service.DemoServiceImpl.execRedTx(String,String)]

[2019-07-12 18:13:03:303] [DEBUG] [Thread: http-nio-8901-exec-7] [method:com.redtx.core.tx.RedTxService.execTx(RedTxService.java:28)]
started local RedTxContext!

[2019-07-12 18:13:03:309] [DEBUG] [Thread: http-nio-8901-exec-7] [method:com.redtx.core.tx.RedTxService.execTx(RedTxService.java:42)]
redTxContextManager.startTx(), txHolder 

[2019-07-12 18:13:03:321] [DEBUG] [Thread: http-nio-8901-exec-7] [method:com.redtx.core.tx.RedTxService.execTx(RedTxService.java:49)]
 current module's txHolder 

[2019-07-12 18:13:03:342] [DEBUG] [Thread: http-nio-8901-exec-7] [method:com.sc.svca.service.DemoServiceImpl.execRedTx(DemoServiceImpl.java:27)]
now enter into A - service - mygod72, false

[2019-07-12 18:13:04:270] [INFO ] [Thread: hystrix-consul-service-b-1] [method:com.sc.cmn.config.FeginOAuth2Interceptor.apply(FeginOAuth2Interceptor.java:44)]
=session-id: 0829A9CFBEE9B588BD2A5A6FD9EEA91B

[2019-07-12 18:13:04:289] [INFO ] [Thread: hystrix-consul-service-b-1] [method:com.sc.cmn.config.FeginOAuth2Interceptor.apply(FeginOAuth2Interceptor.java:44)]
=session-id: 0829A9CFBEE9B588BD2A5A6FD9EEA91B

[2019-07-12 18:13:04:291] [DEBUG] [Thread: hystrix-consul-service-b-1] [method:com.redtx.core.http.CallChainUtil.callSetter(CallChainUtil.java:26)]
passing groupId:3e2e806d7e3846b7a221707c07d3ede3

[2019-07-12 18:13:06:361] [DEBUG] [Thread: http-nio-8901-exec-7] [method:com.sc.svca.service.DemoServiceImpl.execRedTx(DemoServiceImpl.java:31)]
now called B - service- Result - success

[2019-07-12 18:13:06:391] [INFO ] [Thread: hystrix-consul-service-c-1] [method:com.sc.cmn.config.FeginOAuth2Interceptor.apply(FeginOAuth2Interceptor.java:44)]
=session-id: 0829A9CFBEE9B588BD2A5A6FD9EEA91B

[2019-07-12 18:13:06:393] [INFO ] [Thread: hystrix-consul-service-c-1] [method:com.sc.cmn.config.FeginOAuth2Interceptor.apply(FeginOAuth2Interceptor.java:44)]
=session-id: 0829A9CFBEE9B588BD2A5A6FD9EEA91B

[2019-07-12 18:13:06:394] [DEBUG] [Thread: hystrix-consul-service-c-1] [method:com.redtx.core.http.CallChainUtil.callSetter(CallChainUtil.java:26)]
passing groupId:3e2e806d7e3846b7a221707c07d3ede3

[2019-07-12 18:13:08:164] [DEBUG] [Thread: http-nio-8901-exec-7] [method:com.sc.svca.service.DemoServiceImpl.execRedTx(DemoServiceImpl.java:38)]
now called C - service- Result - Calling consul-service-c   FAILED! - FALLING BACK - with parameter - value:mygod72

[2019-07-12 18:13:08:168] [DEBUG] [Thread: http-nio-8901-exec-7] [method:com.redtx.core.netty.NettyClientBootstrap.getChannel(NettyClientBootstrap.java:54)]
try to get netty connection to server with config RedtxClientConfig [txTimeout=30000, mgrAddrs=172.10.1.63:9011, txSyncCallTimeout=3000]

[2019-07-12 18:13:08:189] [DEBUG] [Thread: nioEventLoopGroup-7-1] [method:com.redtx.core.netty.NettyClientHandler.channelRead0(NettyClientHandler.java:61)]
received txMsg from netty server : 

[2019-07-12 18:13:08:190] [INFO ] [Thread: nioEventLoopGroup-7-1] [method:com.redtx.core.netty.NettyClientHandler.channelRead0(NettyClientHandler.java:66)]
received sync msg - TxMsg(txStatus=1, groupId=3e2e806d7e3846b7a221707c07d3ede3, unitId=String com.sc.svca.service.DemoServiceImpl.execRedTx(String,String), txLauncher=true, msgStr=null) 

[2019-07-12 18:13:08:190] [DEBUG] [Thread: http-nio-8901-exec-7] [method:com.redtx.core.tx.RedTxExecutor.runBizMethod(RedTxExecutor.java:43)]
txLauncher get sync netty tx msg 

[2019-07-12 18:13:08:191] [INFO ] [Thread: http-nio-8901-exec-7] [method:com.redtx.core.tx.RedTxExecutor.runBizMethod(RedTxExecutor.java:46)]
Distributed Transaction already failed! thread name-http-nio-8901-exec-7, txHolder-txStatus-null

[2019-07-12 18:13:08:193] [ERROR] [Thread: nioEventLoopGroup-7-1] [method:com.redtx.core.ds.RedTxServiceImpl.undo(RedTxServiceImpl.java:262)]
Rollback(undo) is not needed for current module, group 3e2e806d7e3846b7a221707c07d3ede3 unit String com.sc.svca.service.DemoServiceImpl.execRedTx(String,String) with exception: No qualifying bean of type 'javax.sql.DataSource' available

查看日志 (成功部分 consul-service-a.log)
[2019-07-12 18:15:20:926] [DEBUG] [Thread: http-nio-8901-exec-7] [method:com.redtx.core.aop.TransactionAspect.transactionRunning(TransactionAspect.java:51)]
now get into AOP transactionRunning [value, rollbackFlag], [mygod73, false] 

[2019-07-12 18:15:20:927] [DEBUG] [Thread: http-nio-8901-exec-7] [method:com.redtx.core.tx.RedTxInfo.getFromCache(RedTxInfo.java:48)]
get txMethodId RedTxInfo [targetClazz=class com.sc.svca.service.DemoServiceImpl, businessMethod=public java.lang.String com.sc.svca.service.DemoServiceImpl.execRedTx(java.lang.String,java.lang.String), txMethodId=String com.sc.svca.service.DemoServiceImpl.execRedTx(String,String)]

[2019-07-12 18:15:20:928] [DEBUG] [Thread: http-nio-8901-exec-7] [method:com.redtx.core.tx.RedTxService.execTx(RedTxService.java:28)]
started local RedTxContext!

[2019-07-12 18:15:20:929] [DEBUG] [Thread: http-nio-8901-exec-7] [method:com.redtx.core.tx.RedTxService.execTx(RedTxService.java:42)]
redTxContextManager.startTx(), txHolder 

[2019-07-12 18:15:20:931] [DEBUG] [Thread: http-nio-8901-exec-7] [method:com.redtx.core.tx.RedTxService.execTx(RedTxService.java:49)]
 current module's txHolder 

[2019-07-12 18:15:20:932] [DEBUG] [Thread: http-nio-8901-exec-7] [method:com.sc.svca.service.DemoServiceImpl.execRedTx(DemoServiceImpl.java:27)]
now enter into A - service - mygod73, false

[2019-07-12 18:15:20:936] [INFO ] [Thread: hystrix-consul-service-b-2] [method:com.sc.cmn.config.FeginOAuth2Interceptor.apply(FeginOAuth2Interceptor.java:44)]
=session-id: 73AD3811B7E8722BC7F0A632E77F3621

[2019-07-12 18:15:20:937] [INFO ] [Thread: hystrix-consul-service-b-2] [method:com.sc.cmn.config.FeginOAuth2Interceptor.apply(FeginOAuth2Interceptor.java:44)]
=session-id: 73AD3811B7E8722BC7F0A632E77F3621

[2019-07-12 18:15:20:938] [DEBUG] [Thread: hystrix-consul-service-b-2] [method:com.redtx.core.http.CallChainUtil.callSetter(CallChainUtil.java:26)]
passing groupId:286c237bb4564deea75fca9713b1865f

[2019-07-12 18:15:21:007] [DEBUG] [Thread: http-nio-8901-exec-7] [method:com.sc.svca.service.DemoServiceImpl.execRedTx(DemoServiceImpl.java:31)]
now called B - service- Result - success

[2019-07-12 18:15:21:012] [INFO ] [Thread: hystrix-consul-service-c-2] [method:com.sc.cmn.config.FeginOAuth2Interceptor.apply(FeginOAuth2Interceptor.java:44)]
=session-id: 73AD3811B7E8722BC7F0A632E77F3621

[2019-07-12 18:15:21:013] [INFO ] [Thread: hystrix-consul-service-c-2] [method:com.sc.cmn.config.FeginOAuth2Interceptor.apply(FeginOAuth2Interceptor.java:44)]
=session-id: 73AD3811B7E8722BC7F0A632E77F3621

[2019-07-12 18:15:21:014] [DEBUG] [Thread: hystrix-consul-service-c-2] [method:com.redtx.core.http.CallChainUtil.callSetter(CallChainUtil.java:26)]
passing groupId:286c237bb4564deea75fca9713b1865f

[2019-07-12 18:15:21:114] [DEBUG] [Thread: http-nio-8901-exec-7] [method:com.sc.svca.service.DemoServiceImpl.execRedTx(DemoServiceImpl.java:38)]
now called C - service- Result - success

[2019-07-12 18:15:21:116] [DEBUG] [Thread: http-nio-8901-exec-7] [method:com.redtx.core.netty.NettyClientBootstrap.getChannel(NettyClientBootstrap.java:54)]
try to get netty connection to server with config RedtxClientConfig [txTimeout=30000, mgrAddrs=172.10.1.63:9011, txSyncCallTimeout=3000]

[2019-07-12 18:15:21:124] [DEBUG] [Thread: nioEventLoopGroup-7-1] [method:com.redtx.core.netty.NettyClientHandler.channelRead0(NettyClientHandler.java:61)]
received txMsg from netty server : 

[2019-07-12 18:15:21:125] [INFO ] [Thread: nioEventLoopGroup-7-1] [method:com.redtx.core.netty.NettyClientHandler.channelRead0(NettyClientHandler.java:66)]
received sync msg - TxMsg(txStatus=0, groupId=286c237bb4564deea75fca9713b1865f, unitId=String com.sc.svca.service.DemoServiceImpl.execRedTx(String,String), txLauncher=true, msgStr=null) 

[2019-07-12 18:15:21:125] [DEBUG] [Thread: http-nio-8901-exec-7] [method:com.redtx.core.tx.RedTxExecutor.runBizMethod(RedTxExecutor.java:43)]
txLauncher get sync netty tx msg 

[2019-07-12 18:15:21:126] [DEBUG] [Thread: http-nio-8901-exec-7] [method:com.redtx.core.tx.RedTxService.execTx(RedTxService.java:57)]
 current module's txHolder after biz method 

[2019-07-12 18:15:21:127] [DEBUG] [Thread: http-nio-8901-exec-7] [method:com.redtx.core.netty.NettyClientBootstrap.getChannel(NettyClientBootstrap.java:54)]
try to get netty connection to server with config RedtxClientConfig [txTimeout=30000, mgrAddrs=172.10.1.63:9011, txSyncCallTimeout=3000]

[2019-07-12 18:15:21:131] [DEBUG] [Thread: http-nio-8901-exec-7] [method:com.redtx.core.tx.RedTxService.execTx(RedTxService.java:61)]
send netty msg 

[2019-07-12 18:15:21:132] [DEBUG] [Thread: http-nio-8901-exec-7] [method:com.redtx.core.tx.RedTxContext.remove(RedTxContext.java:38)]
Last clean on current module local context - RedTxContext(groupId=286c237bb4564deea75fca9713b1865f, unitId=String com.sc.svca.service.DemoServiceImpl.execRedTx(String,String), resource=null)

[2019-07-12 18:15:21:133] [DEBUG] [Thread: http-nio-8901-exec-7] [method:com.sc.svca.controller.RedTxTestController.execute(RedTxTestController.java:25)]
A - service  returned success

[2019-07-12 18:15:21:154] [DEBUG] [Thread: nioEventLoopGroup-7-1] [method:com.redtx.core.ds.RedTxServiceImpl.cleanUndo(RedTxServiceImpl.java:195)]
cleaned undo log DELETE FROM TXC_UNDO_LOG WHERE GROUP_ID=286c237bb4564deea75fca9713b1865f AND UNIT_ID=String com.sc.svca.service.DemoServiceImpl.execRedTx(String,String). 

[2019-07-12 18:15:21:169] [DEBUG] [Thread: nioEventLoopGroup-7-1] [method:com.redtx.core.netty.NettyClientHandler.channelRead0(NettyClientHandler.java:61)]
received txMsg from netty server : 

[2019-07-12 18:15:21:170] [DEBUG] [Thread: nioEventLoopGroup-7-1] [method:com.redtx.core.ds.RedTxServiceImpl.cleanUndo(RedTxServiceImpl.java:195)]
cleaned undo log DELETE FROM TXC_UNDO_LOG WHERE GROUP_ID=286c237bb4564deea75fca9713b1865f AND UNIT_ID=String com.sc.svca.service.DemoServiceImpl.execRedTx(String,String). 

你可能感兴趣的:(RedTx - SpringCloud 分布式事务 构件 分享)