分布式事务解决方案之TCC Transaction 下篇
TCC Transaction 框架解析
核心通过拦截器构建事务上下文,经过反射进行confirm/cancel操作。
DTO
TransactionXid (Xid: 指一个XA事务。不同的数据库要不同的 Xid(每个数据库连接(分支)一个)) : formatId(XID 的格式标识符)、 globalTransactionId(全局事务ID)、branchQualifier(分支限定符)
TransactionContext (事务上下文) : TransactionXid 、attachments(附加属性)、status(状态<TCC>)
InvocationContext(方法调用上下文):targetClass、methodName、parameterTypes、args
Terminator(终结者):InvocationContext(确认调用的上下文)、InvocationContext(取消调用的上下文)
Participant(事务参与者):TransactionXid、 Terminator
Transaction 、TransactionContext、Participant 的 TransactionXid全局事务id一致
原因:commit/cancel操作,事务管理器TransactionManager根据Xid识别,调用Participant(参与者)下的 Terminator(终结者)的 InvocationContext(确认/取消 上下文)
配置
事务补偿注解.
/** * 事务补偿注解. */ @Retention(RetentionPolicy.RUNTIME) @Target({ ElementType.METHOD }) public @interface Compensable { public String confirmMethod() default ""; public String cancelMethod() default ""; }
TccTransactionContextAspect 可补偿事务拦截器 (PS:拦截器1)
用来构建Transaction和TransactionContext 一个主事务调用内保证Xid一致
/** * 可补偿事务拦截器。 */ public class CompensableTransactionInterceptor { static final Logger logger = Logger.getLogger(CompensableTransactionInterceptor.class.getSimpleName()); /** * 事务配置器 */ private TransactionConfigurator transactionConfigurator; /** * 设置事务配置器. * @param transactionConfigurator */ public void setTransactionConfigurator(TransactionConfigurator transactionConfigurator) { this.transactionConfigurator = transactionConfigurator; } /** * 拦截补偿方法. * @param pjp * @throws Throwable */ public Object interceptCompensableMethod(ProceedingJoinPoint pjp) throws Throwable { // 从拦截方法的参数中获取事务上下文 TransactionContext transactionContext = CompensableMethodUtils.getTransactionContextFromArgs(pjp.getArgs()); // 计算可补偿事务方法类型 MethodType methodType = CompensableMethodUtils.calculateMethodType(transactionContext, true); logger.debug("==>interceptCompensableMethod methodType:" + methodType.toString()); switch (methodType) { case ROOT: return rootMethodProceed(pjp); // 主事务方法的处理 case PROVIDER: return providerMethodProceed(pjp, transactionContext); // 服务提供者事务方法处理 default: return pjp.proceed(); // 其他的方法都是直接执行 } } /** * 主事务方法的处理. * @param pjp * @throws Throwable */ private Object rootMethodProceed(ProceedingJoinPoint pjp) throws Throwable { logger.debug("==>rootMethodProceed"); transactionConfigurator.getTransactionManager().begin(); // 事务开始(创建事务日志记录,并在当前线程缓存该事务日志记录) Object returnValue = null; // 返回值 try { logger.debug("==>rootMethodProceed try begin"); returnValue = pjp.proceed(); // Try (开始执行被拦截的方法) logger.debug("==>rootMethodProceed try end"); } catch (OptimisticLockException e) { logger.warn("==>compensable transaction trying exception.", e); throw e; //do not rollback, waiting for recovery job } catch (Throwable tryingException) { logger.warn("compensable transaction trying failed.", tryingException); transactionConfigurator.getTransactionManager().rollback(); throw tryingException; } logger.info("===>rootMethodProceed begin commit()"); transactionConfigurator.getTransactionManager().commit(); // Try检验正常后提交(事务管理器在控制提交) return returnValue; } /** * 服务提供者事务方法处理. * @param pjp * @param transactionContext * @throws Throwable */ private Object providerMethodProceed(ProceedingJoinPoint pjp, TransactionContext transactionContext) throws Throwable { logger.debug("==>providerMethodProceed transactionStatus:" + TransactionStatus.valueOf(transactionContext.getStatus()).toString()); switch (TransactionStatus.valueOf(transactionContext.getStatus())) { case TRYING: logger.debug("==>providerMethodProceed try begin"); // 基于全局事务ID扩展创建新的分支事务,并存于当前线程的事务局部变量中. transactionConfigurator.getTransactionManager().propagationNewBegin(transactionContext); logger.debug("==>providerMethodProceed try end"); return pjp.proceed(); case CONFIRMING: try { logger.debug("==>providerMethodProceed confirm begin"); // 找出存在的事务并处理. transactionConfigurator.getTransactionManager().propagationExistBegin(transactionContext); transactionConfigurator.getTransactionManager().commit(); // 提交 logger.debug("==>providerMethodProceed confirm end"); } catch (NoExistedTransactionException excepton) { //the transaction has been commit,ignore it. } break; case CANCELLING: try { logger.debug("==>providerMethodProceed cancel begin"); transactionConfigurator.getTransactionManager().propagationExistBegin(transactionContext); transactionConfigurator.getTransactionManager().rollback(); // 回滚 logger.debug("==>providerMethodProceed cancel end"); } catch (NoExistedTransactionException exception) { //the transaction has been rollback,ignore it. } break; } Method method = ((MethodSignature) (pjp.getSignature())).getMethod(); return ReflectionUtils.getNullValue(method.getReturnType()); } }
ResourceCoordinatorInterceptor TCC事务上下文切面拦截器 (PS:拦截器2)
构建事务Transaction中的参与者(终结者)信息
/** * 资源协调拦截器. */ public class ResourceCoordinatorInterceptor { static final Logger LOG = Logger.getLogger(ResourceCoordinatorInterceptor.class.getSimpleName()); /** * 事务配置器. */ private TransactionConfigurator transactionConfigurator; /** * 设置事务配置器. * @param transactionConfigurator */ public void setTransactionConfigurator(TransactionConfigurator transactionConfigurator) { this.transactionConfigurator = transactionConfigurator; } /** * 拦截事务上下文方法. * @param pjp * @throws Throwable */ public Object interceptTransactionContextMethod(ProceedingJoinPoint pjp) throws Throwable { LOG.debug("==>interceptTransactionContextMethod(ProceedingJoinPoint pjp)"); // 获取当前事务 Transaction transaction = transactionConfigurator.getTransactionManager().getCurrentTransaction(); // Trying(判断是否Try阶段的事务) if (transaction != null && transaction.getStatus().equals(TransactionStatus.TRYING)) { LOG.debug("==>TransactionStatus:" + transaction.getStatus().toString()); // 从参数获取事务上下文 TransactionContext transactionContext = CompensableMethodUtils.getTransactionContextFromArgs(pjp.getArgs()); // 获取事务补偿注解 Compensable compensable = getCompensable(pjp); // 计算方法类型 MethodType methodType = CompensableMethodUtils.calculateMethodType(transactionContext, compensable != null ? true : false); LOG.debug("==>methodType:" + methodType.toString()); switch (methodType) { case ROOT: generateAndEnlistRootParticipant(pjp); // 生成和登记根参与者 break; case CONSUMER: generateAndEnlistConsumerParticipant(pjp); // 生成并登记消费者的参与者 break; case PROVIDER: generateAndEnlistProviderParticipant(pjp); // 生成并登记服务提供者的参与者 break; } } LOG.debug("==>pjp.proceed(pjp.getArgs())"); return pjp.proceed(pjp.getArgs()); } /** * 生成和登记根参与者. * @param pjp * @return */ private Participant generateAndEnlistRootParticipant(ProceedingJoinPoint pjp) { LOG.debug("==>generateAndEnlistRootParticipant(ProceedingJoinPoint pjp)"); MethodSignature signature = (MethodSignature) pjp.getSignature(); Method method = signature.getMethod(); Compensable compensable = getCompensable(pjp); String confirmMethodName = compensable.confirmMethod(); // 确认方法 String cancelMethodName = compensable.cancelMethod(); // 取消方法 Transaction transaction = transactionConfigurator.getTransactionManager().getCurrentTransaction(); // 获取当前事务 TransactionXid xid = new TransactionXid(transaction.getXid().getGlobalTransactionId()); // 获取事务Xid LOG.debug("==>TransactionXid:" + TransactionXid.byteArrayToUUID(xid.getGlobalTransactionId()).toString() + "|" + TransactionXid.byteArrayToUUID(xid.getBranchQualifier()).toString()); Class targetClass = ReflectionUtils.getDeclaringType(pjp.getTarget().getClass(), method.getName(), method.getParameterTypes()); // 构建确认方法的提交上下文 InvocationContext confirmInvocation = new InvocationContext(targetClass, confirmMethodName, method.getParameterTypes(), pjp.getArgs()); // 构建取消方法的提交上下文 InvocationContext cancelInvocation = new InvocationContext(targetClass, cancelMethodName, method.getParameterTypes(), pjp.getArgs()); // 构建参与者对像 Participant participant = new Participant( xid, new Terminator(confirmInvocation, cancelInvocation)); transaction.enlistParticipant(participant); // 加入参与者 TransactionRepository transactionRepository = transactionConfigurator.getTransactionRepository(); transactionRepository.update(transaction); // 更新事务 return participant; } /** * 生成并登记消费者的参与者 * @param pjp * @return */ private Participant generateAndEnlistConsumerParticipant(ProceedingJoinPoint pjp) { LOG.debug("==>generateAndEnlistConsumerParticipant(ProceedingJoinPoint pjp)"); MethodSignature signature = (MethodSignature) pjp.getSignature(); Method method = signature.getMethod(); Transaction transaction = transactionConfigurator.getTransactionManager().getCurrentTransaction(); // 获取当前事务 TransactionXid xid = new TransactionXid(transaction.getXid().getGlobalTransactionId()); // 获取事务Xid LOG.debug("==>TransactionXid:" + TransactionXid.byteArrayToUUID(xid.getGlobalTransactionId()).toString() + "|" + TransactionXid.byteArrayToUUID(xid.getBranchQualifier()).toString()); // 获取事务上下文参数的位置 int position = CompensableMethodUtils.getTransactionContextParamPosition(((MethodSignature) pjp.getSignature()).getParameterTypes()); // 给服务接口的TransactionContext参数设值 pjp.getArgs()[position] = new TransactionContext(xid, transaction.getStatus().getId()); // 构建事务上下文 Object[] tryArgs = pjp.getArgs(); // 获取服务接口参数 Object[] confirmArgs = new Object[tryArgs.length]; // 确认提交参数 Object[] cancelArgs = new Object[tryArgs.length]; // 取消提交参数 System.arraycopy(tryArgs, 0, confirmArgs, 0, tryArgs.length); // 数组拷贝 confirmArgs[position] = new TransactionContext(xid, TransactionStatus.CONFIRMING.getId()); // 构建事务确认上下文 System.arraycopy(tryArgs, 0, cancelArgs, 0, tryArgs.length); // 数组拷贝 cancelArgs[position] = new TransactionContext(xid, TransactionStatus.CANCELLING.getId()); // 构建事务取消上下文 Class targetClass = ReflectionUtils.getDeclaringType(pjp.getTarget().getClass(), method.getName(), method.getParameterTypes()); // 构建确认方法的提交上下文 InvocationContext confirmInvocation = new InvocationContext(targetClass, method.getName(), method.getParameterTypes(), confirmArgs); // 构建取消方法的提交上下文 InvocationContext cancelInvocation = new InvocationContext(targetClass, method.getName(), method.getParameterTypes(), cancelArgs); // 构建参与者对像 Participant participant = new Participant( xid, new Terminator(confirmInvocation, cancelInvocation)); transaction.enlistParticipant(participant); // 加入到参与者 TransactionRepository transactionRepository = transactionConfigurator.getTransactionRepository(); transactionRepository.update(transaction); // 更新事务 return participant; } /** * 生成并登记服务提供者的参与者 * @param pjp * @return */ private Participant generateAndEnlistProviderParticipant(ProceedingJoinPoint pjp) { MethodSignature signature = (MethodSignature) pjp.getSignature(); Method method = signature.getMethod(); Compensable compensable = getCompensable(pjp); String confirmMethodName = compensable.confirmMethod(); String cancelMethodName = compensable.cancelMethod(); Transaction transaction = transactionConfigurator.getTransactionManager().getCurrentTransaction(); TransactionXid xid = new TransactionXid(transaction.getXid().getGlobalTransactionId()); LOG.debug("==>TransactionXid:" + TransactionXid.byteArrayToUUID(xid.getGlobalTransactionId()).toString() + "|" + TransactionXid.byteArrayToUUID(xid.getBranchQualifier()).toString()); Class targetClass = ReflectionUtils.getDeclaringType(pjp.getTarget().getClass(), method.getName(), method.getParameterTypes()); // 构建确认方法的提交上下文 InvocationContext confirmInvocation = new InvocationContext(targetClass, confirmMethodName, method.getParameterTypes(), pjp.getArgs()); // 构建取消方法的提交上下文 InvocationContext cancelInvocation = new InvocationContext(targetClass, cancelMethodName, method.getParameterTypes(), pjp.getArgs()); // 事务的ID不变,参与者的分支ID是新生成的 Participant participant = new Participant( xid, new Terminator(confirmInvocation, cancelInvocation)); transaction.enlistParticipant(participant); TransactionRepository transactionRepository = transactionConfigurator.getTransactionRepository(); transactionRepository.update(transaction); return participant; } /** * 根据切点,获取事务注解. * @param pjp * @return */ private Compensable getCompensable(ProceedingJoinPoint pjp) { LOG.debug("==>getCompensable(ProceedingJoinPoint pjp)"); MethodSignature signature = (MethodSignature) pjp.getSignature(); // 获取签名 Method method = signature.getMethod(); // 获取方法 Compensable compensable = method.getAnnotation(Compensable.class); // 获取注解 if (compensable == null) { Method targetMethod = null; try { // 获取目标方法 targetMethod = pjp.getTarget().getClass().getMethod(method.getName(), method.getParameterTypes()); if (targetMethod != null) { compensable = targetMethod.getAnnotation(Compensable.class); } } catch (NoSuchMethodException e) { compensable = null; } } return compensable; } }
/** * 事务配置器接口 */ public interface TransactionConfigurator { /** * 获取事务管理器. * @return */ public TransactionManager getTransactionManager(); /** * 获取事务库. * @return */ public TransactionRepository getTransactionRepository(); /** * 获取事务恢复配置. * @return */ public RecoverConfig getRecoverConfig(); }
** * TCC事务配置器. */ public class TccTransactionConfigurator implements TransactionConfigurator { /** * 事务库 */ @Autowired private TransactionRepository transactionRepository; /** * 事务恢复配置 */ @Autowired(required = false) private RecoverConfig recoverConfig = DefaultRecoverConfig.INSTANCE; /** * 根据事务配置器创建事务管理器. */ private TransactionManager transactionManager = new TransactionManager(this); /** * 获取事务管理器. */ @Override public TransactionManager getTransactionManager() { return transactionManager; } /** * 获取事务库. */ @Override public TransactionRepository getTransactionRepository() { return transactionRepository; } /** * 获取事务恢复配置. */ @Override public RecoverConfig getRecoverConfig() { return recoverConfig; } }
TransactionManager 事务管理器 核心方法 begin、commit、rollback
** * 事务管理器. */ public class TransactionManager { static final Logger LOG = Logger.getLogger(TransactionManager.class.getSimpleName()); /** * 事务配置器 */ private TransactionConfigurator transactionConfigurator; public TransactionManager(TransactionConfigurator transactionConfigurator) { this.transactionConfigurator = transactionConfigurator; } /** * 定义当前线程的事务局部变量. */ private ThreadLocal<Transaction> threadLocalTransaction = new ThreadLocal<Transaction>(); /** * 事务开始(创建事务日志记录,并将该事务日志记录存入当前线程的事务局部变量中) */ public void begin() { LOG.debug("==>begin()"); Transaction transaction = new Transaction(TransactionType.ROOT); // 事务类型为ROOT:1 LOG.debug("==>TransactionType:" + transaction.getTransactionType().toString() + ", Transaction Status:" + transaction.getStatus().toString()); TransactionRepository transactionRepository = transactionConfigurator.getTransactionRepository(); transactionRepository.create(transaction); // 创建事务记录,写入事务日志库 threadLocalTransaction.set(transaction); // 将该事务日志记录存入当前线程的事务局部变量中 } /** * 基于全局事务ID扩展创建新的分支事务,并存于当前线程的事务局部变量中. * @param transactionContext */ public void propagationNewBegin(TransactionContext transactionContext) { Transaction transaction = new Transaction(transactionContext); LOG.debug("==>propagationNewBegin TransactionXid:" + TransactionXid.byteArrayToUUID(transaction.getXid().getGlobalTransactionId()).toString() + "|" + TransactionXid.byteArrayToUUID(transaction.getXid().getBranchQualifier()).toString()); transactionConfigurator.getTransactionRepository().create(transaction); threadLocalTransaction.set(transaction); } /** * 找出存在的事务并处理. * @param transactionContext * @throws NoExistedTransactionException */ public void propagationExistBegin(TransactionContext transactionContext) throws NoExistedTransactionException { TransactionRepository transactionRepository = transactionConfigurator.getTransactionRepository(); Transaction transaction = transactionRepository.findByXid(transactionContext.getXid()); if (transaction != null) { LOG.debug("==>propagationExistBegin TransactionXid:" + TransactionXid.byteArrayToUUID(transaction.getXid().getGlobalTransactionId()).toString() + "|" + TransactionXid.byteArrayToUUID(transaction.getXid().getBranchQualifier()).toString()); transaction.changeStatus(TransactionStatus.valueOf(transactionContext.getStatus())); threadLocalTransaction.set(transaction); } else { throw new NoExistedTransactionException(); } } /** * 提交. */ public void commit() { LOG.debug("==>TransactionManager commit()"); Transaction transaction = getCurrentTransaction(); transaction.changeStatus(TransactionStatus.CONFIRMING); LOG.debug("==>update transaction status to CONFIRMING"); transactionConfigurator.getTransactionRepository().update(transaction); try { LOG.info("==>transaction begin commit()"); transaction.commit(); transactionConfigurator.getTransactionRepository().delete(transaction); } catch (Throwable commitException) { LOG.error("compensable transaction confirm failed.", commitException); throw new ConfirmingException(commitException); } } /** * 获取当前事务. * @return */ public Transaction getCurrentTransaction() { return threadLocalTransaction.get(); } /** * 回滚事务. */ public void rollback() { Transaction transaction = getCurrentTransaction(); transaction.changeStatus(TransactionStatus.CANCELLING); transactionConfigurator.getTransactionRepository().update(transaction); try { LOG.info("==>transaction begin rollback()"); transaction.rollback(); transactionConfigurator.getTransactionRepository().delete(transaction); } catch (Throwable rollbackException) { LOG.error("compensable transaction rollback failed.", rollbackException); throw new CancellingException(rollbackException); } } }
从服务api 引入 maven 依赖
tcc-transaction-api
TransactionContext 放在第一个参数,拦截器2才可以执行
从服务impl 引入 maven 依赖
<dependency>
<groupId>org.mengyun</groupId>
<artifactId>tcc-transaction-spring</artifactId>
</dependency>
<dependency>
<groupId>org.mengyun</groupId>
<artifactId>tcc-transaction-api</artifactId>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
</dependency>
spring-context 引入
<import resource="classpath:tcc-transaction.xml" />
配置spring-mybatis tccDataSource (domain、tbSuffix 根据服务命名)
<bean id="transactionRepository" class="org.mengyun.tcctransaction.spring.repository.SpringJdbcTransactionRepository"> <property name="dataSource" ref="tccDataSource"/> <property name="domain" value="TARGET"/> <property name="tbSuffix" value="_TARGET"/> </bean>
主服务 try
@Compensable(confirmMethod = "confirmCompleteSuccessOrder",cancelMethod = "cancelCompleteSuccessOrder")
public void completeSuccessOrder(...){}
主服务confirm
@Transactional
public void confirmCompleteSuccessOrder(...){}
主服务cancel
@Transactional
public void cancelCompleteSuccessOrder(...){}
主服务调用从服务接口
void creditToAccountTcc(TransactionContext transactionContext
从服务try
void creditToAccountTcc(TransactionContext transactionContext,..)
@Transactional(rollbackFor = Exception.class)
@Compensable(confirmMethod = "",cancelMethod = "")
public void creditToAccountTcc(TransactionContext transactionContext...) {}
从服务confirm
@Transactional(rollbackFor = Exception.class)
public void confirmCreditToAccountTcc(TransactionContext transactionContext...) {}
从服务cancel
@Transactional(rollbackFor = Exception.class)
public void cancelCreditToAccountTcc(TransactionContext transactionContext...) {}
sql:
CREATE TABLE `TCC_TRANSACTION` ( `TRANSACTION_ID` int(11) NOT NULL AUTO_INCREMENT, `DOMAIN` varchar(100) DEFAULT NULL, `GLOBAL_TX_ID` varbinary(32) NOT NULL, `BRANCH_QUALIFIER` varbinary(32) NOT NULL, `CONTENT` varbinary(8000) DEFAULT NULL, `STATUS` int(11) DEFAULT NULL, `TRANSACTION_TYPE` int(11) DEFAULT NULL, `RETRIED_COUNT` int(11) DEFAULT NULL, `CREATE_TIME` datetime DEFAULT NULL, `LAST_UPDATE_TIME` datetime DEFAULT NULL, `VERSION` int(11) DEFAULT NULL, PRIMARY KEY (`TRANSACTION_ID`), UNIQUE KEY `UX_TX_BQ` (`GLOBAL_TX_ID`,`BRANCH_QUALIFIER`) ) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8;
正向流程
1-> 调用主服务try
1.1 -> 主服务--拦截器1(TransactionContext == null && isCompensable)
没有事务上下文信息,并且方法有事务注解的,为可补偿事务根方法(也就是事务发起者--ROOT)
-> 构建 Transaction
-> 保存db & threadLocal
-> pjp.proceed()
1.2 -> 主服务--拦截器2 ( Transaction status = try &&(TransactionContext == null && isCompensable ))
没有事务上下文信息,并且方法有事务注解的,为可补偿事务根方法(也就是事务发起者--ROOT)
-> 根据 ProceedingJoinPoint pjp(AspectJ) 获取类/方法/参数类型 反射得到 targetClass,Compensable标签获取方法名称 <cancelMethod,confirmMethod>,构建 Terminator(终结者)
-> 构建 Participant(事务参与者)<Transaction xid, Terminator>
-> 获取Transaction 保存 Participant
-> 更新db & threadLocal (版本和时间)
-> pjp.proceed()
1.3 -> 主服务try
-> 调用从服务try接口
1.4 -> 主服务--拦截器2 ( Transaction status = try &&(TransactionContext == null && !isCompensable ))
没有事务上下文信息,并且方法没有事务注解的,为可补偿事务服务消费者(参考者)方法(一般为被调用的服务接口--CONSUMER)
-> 获取 Transaction
-> 构建TransactionContext(new TransactionXid全局事务id一致)
-> pjp 获取所有参数,反射ParamType 定位 TransactionContext 在 agr[] 位置并 更新
-> pjp获取所有参数 copy confiArr、cancelArr ; 并同时更新 Arr中对应TransactionContext (状态不同cancel、confirm)
-> 同1.2构建 Terminator(与 1.2 不同:更新参数TransactionContext ; cancelMethod,confirmMethod是接口名 )
-> 同1.2构建 Participant
-> Transaction 保存 Participant
-> 更新db & threadLocal
-> pjp.proceed()
2 -> 调用从服务try
2.1 -> 从服务--拦截器1(TransactionContext != null && isCompensable)
有事务上下文信息,并且方法有事务注解的,为可补偿事务服务提供者方法(一般为被调用的服务接口的实现方法--PROVIDER)
-> 获取 TransactionContext xid,构建 Transaction
-> 保存db & threadLocal
-> pjp.proceed()
2.2 -> 从服务--拦截器2 ( Transaction status = try &&(TransactionContext != null && isCompensable ))
有事务上下文信息,并且方法有事务注解的,为可补偿事务服务提供者方法(一般为被调用的服务接口的实现方法--PROVIDER)
-> 获取 Transaction Xid
-> pjp获取所有参数 copy confiArr、cancelArr ;
-> 同上构建 Terminator
-> 同上构建 Participant
-> Transaction 保存 Participant
-> 更新db & threadLocal
-> pjp.proceed()
3.-> 1.1中 主服务--拦截器1 pjp.proceed() ,成功commit,失败rollback,异常
OptimisticLockException throw 等待回滚
3.1.1-> commit
-> 获取 Transaction 更新status (try -> confirm)
-> 调用 Transaction 的commit :遍历 Participant list (此处流程:主服务中的方法,从服务的接口在3.2详解)调用 Terminator 的 commit(invoke confirmInvocationContext)
-> beanFactory.getBean(targetClass) 若为空,则 invocationContext.getTargetClass().newInstance();
-> 找到要调用的目标方法target.getClass().getMethod(invocationContext.getMethodName(), invocationContext.getParameterTypes());
-> 调用服务方法,不被再次被拦截(confirm方法没有Compensable注解;Transaction status 不是try),所以直接执行远程服务 method.invoke(target, invocationContext.getArgs());
-> 删除Transaction
-> return 拦截
3.1.2-> 在 3.1 commit 遍历Participant list 当调用到 从服务try 的接口
-> 从服务--拦截器1 (TransactionContext != null && isCompensable)
有事务上下文信息,并且方法有事务注解的,为可补偿事务服务提供者方法(一般为被调用的服务接口的实现方法--PROVIDER)
-> 根据 TransactionContext xid找到 Transaction (domain过滤)
-> TransactionContext.status(Terminator的confirmInvocationContext的参数) = confirm 执行 commit
-> 与3.1.1 操作一致,
-> 更新 Transaction 更新status (try -> confirm)
.......
.......
3.2.1-> rollback
-> 与3.1.1 操作一致, 最后 method.invoke 是 Terminator 的cancelInvocationContext
3.2.2-> rollback
->同 3.1.2
异常流程
1 -> 启动定时任务
1.1-> 查询db 根据超过配置规定时间,没有超过最大重试次数,对应该服务domain 的 Transaction
1.2-> Transaction更新版本、时间和重试次数;
1.3 -> ransaction 是confirm状态则 进行commit操作; 是其他状态(try,cancel)全部rollback 操作
1.4 -> 1.3正常执行后 删除transaction
要求接口实现幂等性! 例如可能发生同时confirm从服务多次等情况: 主服务定时任务查询confirm状态,调用commit,调用从服务的confirm;从服务定时任务也调用了自身的confirm.....
反射涉及methods:
/** * 获取事务上下文参数的位置. * @param parameterTypes * @return */ public static int getTransactionContextParamPosition(Class<?>[] parameterTypes) { int i = -1; for (i = 0; i < parameterTypes.length; i++) { if (parameterTypes[i].equals(org.mengyun.tcctransaction.api.TransactionContext.class)) { break; } } return i; } /** * 从参数获取事务上下文. * @param args * @return */ public static TransactionContext getTransactionContextFromArgs(Object[] args) { TransactionContext transactionContext = null; for (Object arg : args) { if (arg != null && org.mengyun.tcctransaction.api.TransactionContext.class.isAssignableFrom(arg.getClass())) { transactionContext = (org.mengyun.tcctransaction.api.TransactionContext) arg; } } return transactionContext; } public static Class getDeclaringType(Class aClass, String methodName, Class<?>[] parameterTypes) { Method method = null; Class findClass = aClass; do { Class[] clazzes = findClass.getInterfaces(); for (Class clazz : clazzes) { try { method = clazz.getDeclaredMethod(methodName, parameterTypes); } catch (NoSuchMethodException e) { method = null; } if (method != null) { return clazz; } } findClass = findClass.getSuperclass(); } while (!findClass.equals(Object.class)); return aClass; }