内容简介:上一篇文章(
前言
上一篇文章( https://segmentfault.com/a/11... )我们在springboot2.1.3上集成了lcn5.0.2并简单做了一个lcn模式的demo。LCN官网将源码都给了出来,但是分析源码的部分目前还不是很多,这篇文章主要分析一下LCN模式源码
事务控制原理
分析源码之前,我们首先看一下LCN整体的框架模型:
TX-LCN由两大模块组成, TxClient、TxManager。TxClient作为模块的依赖框架,提供TX-LCN的标准支持,TxManager作为分布式事务的控制放。事务发起方或者参与反都由TxClient端来控制。
原理图:
lcn模式
不难发现,开启处理的地方在拦截器(com.codingapi.txlcn.tc.aspect.TransactionAspect)里面
@Around("lcnTransactionPointcut() && !txcTransactionPointcut()" + "&& !tccTransactionPointcut() && !txTransactionPointcut()") public Object runWithLcnTransaction(ProceedingJoinPoint point) throws Throwable { //将执行分布式事务的方法放在DTXInfo对象里面 DTXInfo dtxInfo = DTXInfo.getFromCache(point); LcnTransaction lcnTransaction = dtxInfo.getBusinessMethod().getAnnotation(LcnTransaction.class); dtxInfo.setTransactionType(Transactions.LCN); dtxInfo.setTransactionPropagation(lcnTransaction.propagation()); //调用方法,正式开启(或继续,这里取决于是否是事务发起方)分布式事务 return dtxLogicWeaver.runTransaction(dtxInfo, point::proceed); }
走进runTransaction方法,我们可以看到一下内容(伪代码,方便分析)
public class DTXLogicWeaver { //执行分布式事务的核心方法 public Object runTransaction(){ //1.拿到当前模块的事务上下文和全局事务上下文 DTXLocalContext dtxLocalContext = DTXLocalContext.getOrNew(); TxContext txContext; // ---------- 保证每个模块在一个DTX下只会有一个TxContext ---------- if (globalContext.hasTxContext()) { // 有事务上下文的获取父上下文 txContext = globalContext.txContext(); dtxLocalContext.setInGroup(true);//加入事务组 log.debug("Unit[{}] used parent's TxContext[{}].", dtxInfo.getUnitId(), txContext.getGroupId()); } else { // 没有的开启本地事务上下文 txContext = globalContext.startTx();//下层创建了事务组 } //2.设置本地事务上下文的一些参数 if (Objects.nonNull(dtxLocalContext.getGroupId())) { dtxLocalContext.setDestroy(false); } dtxLocalContext.setUnitId(dtxInfo.getUnitId()); dtxLocalContext.setGroupId(txContext.getGroupId());//从全局上下文获取 dtxLocalContext.setTransactionType(dtxInfo.getTransactionType()); //3.设置分布式事务参数 TxTransactionInfo info = new TxTransactionInfo(); info.setBusinessCallback(business);//业务执行器(核心) info.setGroupId(txContext.getGroupId());//从全局上下文获取 info.setUnitId(dtxInfo.getUnitId()); info.setPointMethod(dtxInfo.getBusinessMethod()); info.setPropagation(dtxInfo.getTransactionPropagation()); info.setTransactionInfo(dtxInfo.getTransactionInfo()); info.setTransactionType(dtxInfo.getTransactionType()); info.setTransactionStart(txContext.isDtxStart()); //4.LCN事务处理器 try { return transactionServiceExecutor.transactionRunning(info); } finally { // 线程执行业务完毕清理本地数据 if (dtxLocalContext.isDestroy()) { // 通知事务执行完毕 synchronized (txContext.getLock()) { txContext.getLock().notifyAll(); } // TxContext生命周期是? 和事务组一样(不与具体模块相关的) if (!dtxLocalContext.isInGroup()) { globalContext.destroyTx(); } DTXLocalContext.makeNeverAppeared(); TracingContext.tracing().destroy(); } log.debug("<---- TxLcn end ---->"); } } }
执行业务操作
/** * 事务业务执行 * * @param info info * @return Object * @throws Throwable Throwable */ public Object transactionRunning(TxTransactionInfo info) throws Throwable { // 1. 获取事务类型 String transactionType = info.getTransactionType(); // 2. 获取事务传播状态 DTXPropagationState propagationState = propagationResolver.resolvePropagationState(info); // 2.1 如果不参与分布式事务立即终止 if (propagationState.isIgnored()) { return info.getBusinessCallback().call(); } // 3. 获取本地分布式事务控制器 DTXLocalControl dtxLocalControl = txLcnBeanHelper.loadDTXLocalControl(transactionType, propagationState); // 4. 织入事务操作 try { // 4.1 记录事务类型到事务上下文 Set<String> transactionTypeSet = globalContext.txContext(info.getGroupId()).getTransactionTypes(); transactionTypeSet.add(transactionType); dtxLocalControl.preBusinessCode(info); // 4.2 业务执行前 txLogger.txTrace( info.getGroupId(), info.getUnitId(), "pre business code, unit type: {}", transactionType); // 4.3 执行业务 Object result = dtxLocalControl.doBusinessCode(info); // 4.4 业务执行成功 txLogger.txTrace(info.getGroupId(), info.getUnitId(), "business success"); dtxLocalControl.onBusinessCodeSuccess(info, result); return result; } catch (TransactionException e) { txLogger.error(info.getGroupId(), info.getUnitId(), "before business code error"); throw e; } catch (Throwable e) { // 4.5 业务执行失败 txLogger.error(info.getGroupId(), info.getUnitId(), Transactions.TAG_TRANSACTION, "business code error"); dtxLocalControl.onBusinessCodeError(info, e); throw e; } finally { // 4.6 业务执行完毕 dtxLocalControl.postBusinessCode(info); } }
以上所述就是小编给大家介绍的《LCN(5.0.2) lcn模式源码分析(二)》,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对 码农网 的支持!
猜你喜欢:- 从源码角度理解Java设计模式——装饰者模式 原 荐
- 设计模式之发布订阅模式(5) Spring Events源码解析
- EventBus源码剖析(3) — 线程模式
- Mybatis源码解读-设计模式总结
- 深入理解《单例模式》之源码分析
- Seata AT 模式启动源码分析
本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们。
Algorithms
Robert Sedgewick、Kevin Wayne / Addison-Wesley Professional / 2011-3-19 / USD 89.99
Essential Information about Algorithms and Data Structures A Classic Reference The latest version of Sedgewick,s best-selling series, reflecting an indispensable body of knowledge developed over the ......一起来看看 《Algorithms》 这本书的介绍吧!