seata-samples icon indicating copy to clipboard operation
seata-samples copied to clipboard

springboot tcc sample keeps blocking

Open dreamoftch opened this issue 6 years ago • 2 comments

i run the latest sample code(commit id is: 145b2cf95b1af3124f7d169c1339e0ed764f8efc) follow the guide

both seata server and the provider application run ok, but SpringbootTccTransactionApplication keeps blocking.

when i use jstack to find what happened, i see this:

"main" #1 prio=5 os_prio=31 tid=0x00007ff4e382d800 nid=0x1903 in Object.wait() [0x0000700007fb3000]
   java.lang.Thread.State: WAITING (on object monitor)
	at java.lang.Object.wait(Native Method)
	at java.lang.Object.wait(Object.java:502)
	at io.seata.core.rpc.netty.RmRpcClient.lambda$getPoolKeyFunction$0(RmRpcClient.java:153)
	- locked <0x000000076af19e58> (a java.lang.Object)
	at io.seata.core.rpc.netty.RmRpcClient$$Lambda$58/1183701566.apply(Unknown Source)
	at io.seata.core.rpc.netty.NettyClientChannelManager.doConnect(NettyClientChannelManager.java:196)
	at io.seata.core.rpc.netty.NettyClientChannelManager.acquireChannel(NettyClientChannelManager.java:102)
	- locked <0x000000076af19d50> (a java.lang.Object)
	at io.seata.core.rpc.netty.AbstractRpcRemotingClient.sendMsgWithResponse(AbstractRpcRemotingClient.java:226)
	at io.seata.core.rpc.netty.AbstractRpcRemotingClient.sendMsgWithResponse(AbstractRpcRemotingClient.java:233)
	at io.seata.rm.AbstractResourceManager.branchRegister(AbstractResourceManager.java:67)
	at io.seata.rm.DefaultResourceManager.branchRegister(DefaultResourceManager.java:96)
	at io.seata.rm.tcc.interceptor.ActionInterceptorHandler.doTccActionLogStore(ActionInterceptorHandler.java:118)
	at io.seata.rm.tcc.interceptor.ActionInterceptorHandler.proceed(ActionInterceptorHandler.java:69)
	at io.seata.spring.tcc.TccActionInterceptor.invoke(TccActionInterceptor.java:85)
	at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:185)
	at org.springframework.aop.framework.CglibAopProxy$DynamicAdvisedInterceptor.intercept(CglibAopProxy.java:688)
	at org.apache.dubbo.common.bytecode.proxy0$$EnhancerBySpringCGLIB$$e08bc0cf.prepare(<generated>)
	at io.seata.samples.tcc.springboot.dubbo.service.TccTransactionService.doTransactionCommit(TccTransactionService.java:32)
	at io.seata.samples.tcc.springboot.dubbo.service.TccTransactionService$$FastClassBySpringCGLIB$$e1c6fcc.invoke(<generated>)
	at org.springframework.cglib.proxy.MethodProxy.invoke(MethodProxy.java:204)
	at org.springframework.aop.framework.CglibAopProxy$CglibMethodInvocation.invokeJoinpoint(CglibAopProxy.java:746)
	at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:163)
	at io.seata.spring.annotation.GlobalTransactionalInterceptor$1.execute(GlobalTransactionalInterceptor.java:104)
	at io.seata.tm.api.TransactionalTemplate.execute(TransactionalTemplate.java:64)
	at io.seata.spring.annotation.GlobalTransactionalInterceptor.handleGlobalTransaction(GlobalTransactionalInterceptor.java:101)
	at io.seata.spring.annotation.GlobalTransactionalInterceptor.invoke(GlobalTransactionalInterceptor.java:76)
	at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:185)
	at org.springframework.aop.framework.CglibAopProxy$DynamicAdvisedInterceptor.intercept(CglibAopProxy.java:688)
	at io.seata.samples.tcc.springboot.dubbo.service.TccTransactionService$$EnhancerBySpringCGLIB$$81f65c15.doTransactionCommit(<generated>)
	at io.seata.samples.tcc.springboot.dubbo.starter.SpringbootTccTransactionApplication.transactionCommitDemo(SpringbootTccTransactionApplication.java:51)
	at io.seata.samples.tcc.springboot.dubbo.starter.SpringbootTccTransactionApplication.main(SpringbootTccTransactionApplication.java:42)

   Locked ownable synchronizers:
	- None

after looking at the source code in io.seata.core.rpc.netty.RmRpcClient:

            String resourceIds = getMergedResourceKeys();
            synchronized (ResourceManager.RESOURCE_LOCK) {
                while (StringUtils.isNullOrEmpty(resourceIds)) {
                    try {
                        ResourceManager.RESOURCE_LOCK.wait();
                    } catch (InterruptedException exx) {
                        LOGGER.error("wait resourceIds interrupted error:{}", exx.getMessage(), exx);
                    }
                    resourceIds = getMergedResourceKeys();
                }
            }

i found the reason leads to blocking is that SpringbootTccTransactionApplication which acts as TM does not have RM inside, but ActionInterceptorHandler invokes the branchRegister method, which finally requires RM resources, thus code goes into ResourceManager.RESOURCE_LOCK.wait().

i found that the synchronized control code was added by @slievrly , which comments bugfix:rm channel register null resource (#1401), so @slievrly could you help look at this problem?

thanks so much ...

dreamoftch avatar Oct 22 '19 14:10 dreamoftch

i changed seata version from 0.9.0 to 0.8.0, it works

dreamoftch avatar Oct 23 '19 03:10 dreamoftch

@dreamoftch please update to the latest version.

slievrly avatar Mar 17 '20 10:03 slievrly