Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

optimize: branch register resource only at RM server end #5399

Merged
merged 44 commits into from
Jan 8, 2024
Merged
Show file tree
Hide file tree
Changes from 7 commits
Commits
Show all changes
44 commits
Select commit Hold shift + click to select a range
8d2e41a
resolve fence to rm
sunrui1225 Feb 26, 2023
505f7c5
parserInterfaceToProxy eliminate aop proxy.
sunrui1225 Feb 28, 2023
61aae61
Merge branch '2.x' into resolve_fence_to_rm
sunrui1225 Mar 1, 2023
968c8d0
reimport
sunrui1225 Mar 1, 2023
bb1a55c
Merge remote-tracking branch 'origin/resolve_fence_to_rm' into resolv…
sunrui1225 Mar 1, 2023
4c3875d
Merge branch '2.x' into resolve_fence_to_rm
sunrui1225 Mar 3, 2023
7cbf600
bugfix register serviceClass
sunrui1225 Mar 3, 2023
543eb5a
Merge branch '2.x' into resolve_fence_to_rm
sunrui1225 Mar 26, 2023
ddaaa91
parse the business needed enhancement beans by bean definition.
sunrui1225 May 21, 2023
26dc039
Merge branch 'seata:2.x' into resolve_fence_to_rm
sunrui1225 May 21, 2023
38361ba
check style
sunrui1225 May 21, 2023
5cca5c4
check style
sunrui1225 May 21, 2023
d98f3ab
Revert "check style"
sunrui1225 May 21, 2023
daeaafc
check style
sunrui1225 May 22, 2023
002935e
check style
sunrui1225 May 22, 2023
e56a8b2
update the NeedEnhanceEnum GLOBAL_TRANSACTIONAL_BEAN
sunrui1225 May 23, 2023
fa6e3bf
use ReflectionUtil.getClassByName
sunrui1225 May 23, 2023
c42030e
enhancement: parse if it needs proxy by bean class
sunrui1225 Jun 15, 2023
22455a3
update tcc registerResource
sunrui1225 Jun 19, 2023
e6c90fe
Merge remote-tracking branch 'origin/2.x' into resolve_fence_to_rm
sunrui1225 Jun 19, 2023
80b175e
Merge branch '2.x' into resolve_fence_to_rm
sunrui1225 Jun 26, 2023
43f0bcc
Merge branch '2.x' into resolve_fence_to_rm
sunrui1225 Jun 30, 2023
b34ae57
Merge branch '2.x' into resolve_fence_to_rm
funky-eyes Oct 27, 2023
f4030a5
Merge remote-tracking branch 'origin/2.x' into resolve_fence_to_rm
sunrui1225 Dec 16, 2023
3ec392b
merge conflict resolve
sunrui1225 Dec 16, 2023
c3ffb17
Merge branch 'resolve_fence_to_rm' of github.com:sunrui1225/seata int…
sunrui1225 Dec 16, 2023
1da082e
Merge branch '2.x' into resolve_fence_to_rm
sunrui1225 Dec 16, 2023
bfa742a
Merge branch '2.x' into resolve_fence_to_rm
funky-eyes Dec 21, 2023
93b32cf
Update integration-tx-api/src/main/java/io/seata/integration/tx/api/i…
funky-eyes Dec 21, 2023
8c23358
Update integration-tx-api/src/main/java/io/seata/integration/tx/api/i…
funky-eyes Dec 21, 2023
e5cfe2c
Update integration-tx-api/src/main/java/io/seata/integration/tx/api/i…
funky-eyes Dec 21, 2023
6719fe7
Merge branch '2.x' into resolve_fence_to_rm
sunrui1225 Dec 23, 2023
83e4dae
Merge branch 'resolve_fence_to_rm' of github.com:sunrui1225/seata int…
sunrui1225 Dec 23, 2023
78c7121
add logs : Only the methods of classes with two phase annotations can…
sunrui1225 Dec 23, 2023
378fc00
fix : bean definition class name null issue.
sunrui1225 Dec 23, 2023
2df4c80
check style
sunrui1225 Dec 23, 2023
95c6903
add change log
sunrui1225 Dec 23, 2023
057c581
add change log
sunrui1225 Dec 23, 2023
3055c18
Merge branch '2.x' into resolve_fence_to_rm
funky-eyes Dec 23, 2023
79288d6
Merge branch '2.x' into resolve_fence_to_rm
funky-eyes Dec 29, 2023
076a8fc
add comments.
sunrui1225 Dec 29, 2023
a0fbe96
Merge remote-tracking branch 'origin/resolve_fence_to_rm' into resolv…
sunrui1225 Dec 29, 2023
967bfd6
Update integration-tx-api/src/main/java/io/seata/integration/tx/api/u…
funky-eyes Jan 4, 2024
5af4071
Merge branch '2.x' into resolve_fence_to_rm
funky-eyes Jan 8, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,6 @@
import io.seata.integration.tx.api.interceptor.SeataInterceptorPosition;
import io.seata.integration.tx.api.interceptor.TwoPhaseBusinessActionParam;
import io.seata.integration.tx.api.interceptor.handler.AbstractProxyInvocationHandler;
import io.seata.integration.tx.api.remoting.RemotingDesc;
import io.seata.rm.tcc.api.TwoPhaseBusinessAction;
import org.slf4j.MDC;

Expand All @@ -49,12 +48,12 @@ public class TccActionInterceptorHandler extends AbstractProxyInvocationHandler
private ActionInterceptorHandler actionInterceptorHandler = new ActionInterceptorHandler();

private Set<String> methodsToProxy;
private RemotingDesc remotingDesc;
private Object targetBean;

private Map<Method, TwoPhaseBusinessAction> parseAnnotationCache = new ConcurrentHashMap<>();

public TccActionInterceptorHandler(RemotingDesc remotingDesc, Set<String> methodsToProxy) {
this.remotingDesc = remotingDesc;
public TccActionInterceptorHandler(Object targetBean, Set<String> methodsToProxy) {
this.targetBean = targetBean;
this.methodsToProxy = methodsToProxy;
}

Expand Down Expand Up @@ -110,8 +109,8 @@ protected Object doInvoke(InvocationWrapper invocation) throws Throwable {
private TwoPhaseBusinessAction parseAnnotation(Method methodKey) throws NoSuchMethodException {
TwoPhaseBusinessAction result = parseAnnotationCache.computeIfAbsent(methodKey, method -> {
TwoPhaseBusinessAction businessAction = method.getAnnotation(TwoPhaseBusinessAction.class);
if (businessAction == null && remotingDesc.getServiceClass() != null) {
Set<Class<?>> interfaceClasses = ReflectionUtil.getInterfaces(remotingDesc.getServiceClass());
if (businessAction == null && targetBean.getClass() != null) {
Set<Class<?>> interfaceClasses = ReflectionUtil.getInterfaces(targetBean.getClass());
if (interfaceClasses != null) {
for (Class<?> interClass : interfaceClasses) {
try {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,21 +15,21 @@
*/
package io.seata.rm.tcc.interceptor.parser;

import java.lang.reflect.Field;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.util.Arrays;
import java.util.Collections;
import java.util.HashSet;
import java.util.Set;

import io.seata.common.util.ReflectionUtil;
import io.seata.integration.tx.api.interceptor.TxBeanParserUtils;
import io.seata.integration.tx.api.interceptor.handler.ProxyInvocationHandler;
import io.seata.integration.tx.api.interceptor.parser.DefaultResourceRegisterParser;
import io.seata.integration.tx.api.interceptor.parser.InterfaceParser;
import io.seata.integration.tx.api.remoting.RemotingDesc;
import io.seata.integration.tx.api.remoting.parser.DefaultRemotingParser;
import io.seata.rm.tcc.api.TwoPhaseBusinessAction;
import io.seata.rm.tcc.interceptor.TccActionInterceptorHandler;

import java.lang.reflect.Method;
import java.util.Arrays;
import java.util.Collections;
import java.util.HashSet;
import java.util.Set;
import org.springframework.aop.support.AopUtils;

/**
* @author leezongjie
Expand All @@ -38,39 +38,46 @@ public class TccActionInterceptorParser implements InterfaceParser {

@Override
public ProxyInvocationHandler parserInterfaceToProxy(Object target) {
boolean isTxRemotingBean = TxBeanParserUtils.isTxRemotingBean(target, target.toString());
if (isTxRemotingBean) {
RemotingDesc remotingDesc = DefaultRemotingParser.get().getRemotingBeanDesc(target);
if (remotingDesc != null) {
if (remotingDesc.isService()) {
DefaultResourceRegisterParser.get().registerResource(target);
}
if (remotingDesc.isReference()) {
//if it is a tcc remote reference
Set<String> methodsToProxy = tccProxyTargetMethod(remotingDesc);
if (remotingDesc != null && !methodsToProxy.isEmpty()) {
ProxyInvocationHandler proxyInvocationHandler = new TccActionInterceptorHandler(remotingDesc, methodsToProxy);
return proxyInvocationHandler;
}
}

// below only enhance the native business bean.
// eliminate without two phase annotation bean.
Set<String> methodsToProxy = this.tccProxyTargetMethod(target);
if (methodsToProxy.isEmpty()) {
return null;
}

// eliminate aop proxy.
if (AopUtils.isAopProxy(target)) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In the past, the result of being processed by the RPC framework would have been either a Reference Bean or a Service Bean. However, if you are not currently using this RPC framework handling, how do you ensure that the class is not proxy or that the TwoPhaseBusinessAction has the highest priority order?


在过去,被RPC框架处理后,最终得到的结果肯定是Reference Bean或者Service Bean。但是,如果当前不再使用这种RPC框架的处理方式来判断,如何保证这个类没有被代理过或者怎么保证TwoPhaseBusinessAction的切面优先级是最高的?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

之前这种方式确实有问题,不能保证,以下以一种思路:
利用spring 的 bean definition,提前在自动代理前得到各个类的引用关系,从而提前获取依赖关系,保存名字在Set中,然后在AOP自动代理的wrapIfNecessary中,判断是否存在。
在RM端,Set中保存的是 service指向的原生bean的name。
在TM端,Set中保存的是开启事务的bean的name。

return null;
}

// eliminate dubbo etc proxy bean.
Field[] fields = ReflectionUtil.getAllFields(target.getClass());
for (Field field : fields) {
if (field.getGenericType().equals(InvocationHandler.class)) {
return null;
}
}
return null;

// register resource and enhance with interceptor
DefaultResourceRegisterParser.get().registerResource(target);
return new TccActionInterceptorHandler(target, methodsToProxy);
}

/**
* is TCC proxy-bean/target-bean: LocalTCC , the proxy bean of sofa:reference/dubbo:reference
*
* @param remotingDesc the remoting desc
* @param target the target bean
* @return boolean boolean
*/
private Set<String> tccProxyTargetMethod(RemotingDesc remotingDesc) {
if (!remotingDesc.isReference() || remotingDesc == null) {

private Set<String> tccProxyTargetMethod(Object target) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

How to handle method overloading with the same method name


如何处理方法名相同都标注TwoPhaseBusinessAction注解的方法重载问题。

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

How to handle method overloading with the same method name

如何处理方法名相同都标注TwoPhaseBusinessAction注解的方法重载问题。

这个问题将由后续pr解决
This issue will be addressed by a follow-up PR

if (target == null) {
return Collections.emptySet();
}
Set<String> methodsToProxy = new HashSet<>();
//check if it is TCC bean
Class<?> tccServiceClazz = remotingDesc.getServiceClass();
Class<?> tccServiceClazz = target.getClass();
Set<Method> methods = new HashSet<>(Arrays.asList(tccServiceClazz.getMethods()));
Set<Class<?>> interfaceClasses = ReflectionUtil.getInterfaces(tccServiceClazz);
if (interfaceClasses != null) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,77 +15,66 @@
*/
package io.seata.rm.tcc.resource.parser;

import java.lang.annotation.Annotation;
import java.lang.reflect.Method;
import java.util.Arrays;
import java.util.HashSet;
import java.util.Set;

import io.seata.common.exception.FrameworkException;
import io.seata.common.util.ReflectionUtil;
import io.seata.integration.tx.api.interceptor.ActionContextUtil;
import io.seata.integration.tx.api.interceptor.TxBeanParserUtils;
import io.seata.integration.tx.api.interceptor.parser.RegisterResourceParser;
import io.seata.integration.tx.api.remoting.RemotingDesc;
import io.seata.integration.tx.api.remoting.parser.DefaultRemotingParser;
import io.seata.rm.DefaultResourceManager;
import io.seata.rm.tcc.TCCResource;
import io.seata.rm.tcc.api.BusinessActionContext;
import io.seata.rm.tcc.api.BusinessActionContextParameter;
import io.seata.rm.tcc.api.TwoPhaseBusinessAction;

import java.lang.annotation.Annotation;
import java.lang.reflect.Method;
import java.util.Arrays;
import java.util.HashSet;
import java.util.Set;

/**
* @author leezongjie
*/
public class TccRegisterResourceParser implements RegisterResourceParser {

@Override
public void registerResource(Object target) {
boolean isTxRemotingBean = TxBeanParserUtils.isTxRemotingBean(target, target.toString());
if (isTxRemotingBean) {
RemotingDesc remotingDesc = DefaultRemotingParser.get().getRemotingBeanDesc(target);
if (remotingDesc != null) {
if (remotingDesc.isService()) {
try {
//service bean, registry resource
Class<?> serviceClass = remotingDesc.getServiceClass();
Set<Method> methods = new HashSet<>(Arrays.asList(serviceClass.getMethods()));
Set<Class<?>> interfaceClasses = ReflectionUtil.getInterfaces(serviceClass);
if (interfaceClasses != null) {
for (Class<?> interClass : interfaceClasses) {
methods.addAll(Arrays.asList(interClass.getMethods()));
}
}
Object targetBean = remotingDesc.getTargetBean();
for (Method m : methods) {
TwoPhaseBusinessAction twoPhaseBusinessAction = m.getAnnotation(TwoPhaseBusinessAction.class);
if (twoPhaseBusinessAction != null) {
TCCResource tccResource = new TCCResource();
tccResource.setActionName(twoPhaseBusinessAction.name());
tccResource.setTargetBean(targetBean);
tccResource.setPrepareMethod(m);
tccResource.setCommitMethodName(twoPhaseBusinessAction.commitMethod());
tccResource.setCommitMethod(serviceClass.getMethod(twoPhaseBusinessAction.commitMethod(),
twoPhaseBusinessAction.commitArgsClasses()));
tccResource.setRollbackMethodName(twoPhaseBusinessAction.rollbackMethod());
tccResource.setRollbackMethod(serviceClass.getMethod(twoPhaseBusinessAction.rollbackMethod(),
twoPhaseBusinessAction.rollbackArgsClasses()));
// set argsClasses
tccResource.setCommitArgsClasses(twoPhaseBusinessAction.commitArgsClasses());
tccResource.setRollbackArgsClasses(twoPhaseBusinessAction.rollbackArgsClasses());
// set phase two method's keys
tccResource.setPhaseTwoCommitKeys(this.getTwoPhaseArgs(tccResource.getCommitMethod(),
twoPhaseBusinessAction.commitArgsClasses()));
tccResource.setPhaseTwoRollbackKeys(this.getTwoPhaseArgs(tccResource.getRollbackMethod(),
twoPhaseBusinessAction.rollbackArgsClasses()));
//registry tcc resource
DefaultResourceManager.get().registerResource(tccResource);
}
}
} catch (Throwable t) {
throw new FrameworkException(t, "parser remoting service error");
}
}
try {
//service bean, registry resource
Class<?> serviceClass = target.getClass();
this.executeRegisterResource(target, new HashSet<>(Arrays.asList(serviceClass.getMethods())), target.getClass());
Set<Class<?>> interfaceClasses = ReflectionUtil.getInterfaces(serviceClass);
for (Class<?> interClass : interfaceClasses) {
this.executeRegisterResource(target, new HashSet<>(Arrays.asList(interClass.getMethods())), interClass);
}
} catch (Throwable t) {
throw new FrameworkException(t, "parser remoting service error");
}
}

private void executeRegisterResource(Object target, Set<Method> methods, Class<?> targetServiceClass) throws NoSuchMethodException {
for (Method m : methods) {
TwoPhaseBusinessAction twoPhaseBusinessAction = m.getAnnotation(TwoPhaseBusinessAction.class);
if (twoPhaseBusinessAction != null) {
TCCResource tccResource = new TCCResource();
tccResource.setActionName(twoPhaseBusinessAction.name());
tccResource.setTargetBean(target);
tccResource.setPrepareMethod(m);
tccResource.setCommitMethodName(twoPhaseBusinessAction.commitMethod());
tccResource.setCommitMethod(targetServiceClass.getMethod(twoPhaseBusinessAction.commitMethod(),
twoPhaseBusinessAction.commitArgsClasses()));
tccResource.setRollbackMethodName(twoPhaseBusinessAction.rollbackMethod());
tccResource.setRollbackMethod(targetServiceClass.getMethod(twoPhaseBusinessAction.rollbackMethod(),
twoPhaseBusinessAction.rollbackArgsClasses()));
// set argsClasses
tccResource.setCommitArgsClasses(twoPhaseBusinessAction.commitArgsClasses());
tccResource.setRollbackArgsClasses(twoPhaseBusinessAction.rollbackArgsClasses());
// set phase two method's keys
tccResource.setPhaseTwoCommitKeys(this.getTwoPhaseArgs(tccResource.getCommitMethod(),
twoPhaseBusinessAction.commitArgsClasses()));
tccResource.setPhaseTwoRollbackKeys(this.getTwoPhaseArgs(tccResource.getRollbackMethod(),
twoPhaseBusinessAction.rollbackArgsClasses()));
//registry tcc resource
DefaultResourceManager.get().registerResource(tccResource);
}
}
}
Expand Down