apache / apache/incubator-seata-samples

springboot tcc sample keeps blocking

Open
#254 2 comments 0 reactions 0 assignees View on GitHub
Dominant language
Java
Stars
2.4k
Forks
2k
PR merge metrics
No merged PRs in 30d

Description

i run the latest sample code(commit id is: 145b2cf95b1af3124f7d169c1339e0ed764f8efc) follow [the guide ](https://github.com/seata/seata-samples/tree/master/tcc/springboot-tcc-sample)

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

when i use jstack to find what happened, i see this:
```text
"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()
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()
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()
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`:
```java
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 ...

Contributor guide

Open the contributing guide

Research direction

Reproduce the springboot-tcc-sample using commit 145b2cf95b1af3124f7d169c1339e0ed764f8efc, then read RmRpcClient, NettyClientChannelManager, ActionInterceptorHandler, and SpringbootTccTransactionApplication. Use the provided jstack trace and the RESOURCE_LOCK wait path to verify why startup blocks when the application acts as TM without RM resources. Done means the sample starts and completes its transaction demonstration without blocking.

Written by the indexing model from the issue text.

Assessment

Tech stack
java, spring-boot
Domain
backend, distributed-systems
Issue type
Bug
Difficulty
4/5
Estimated time
3-5 days
Activity status
Stale
Clarity
Mostly clear
Newbie friendliness
25/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.