apache / apache/incubator-seata-samples
springboot tcc sample keeps blocking
- 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
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