Milo源码解析(五)

深入解析Try阶段

上一篇博客介绍了InitiatorMiloTransactionHandler是如何处理事务发起者发起的调用,try阶段完成后执行confirmPhase,否则执行cancelPhase,在解析这两个方法之前我们先再回到tryPhase方法里面看一下,milo框架当创建完事务日志(READY阶段)并且绑定到当前线程之后调用了pjp.proceed(),执行到这里就会进入到payment方法,payment方法最重要的两个地方就是通过openFeign远程调用了库存服务扣减库存和账户服务扣减余额。
在这里插入图片描述
在这里插入图片描述
扣减库存和扣减账户是分别通过两个FeignClient去执行的,而这两个FeignClient的扣减方法上都是带有@MiloTCC注解的,对于Milo框架来说分布式事务所有的参与者都必须带@MiloTCC注解。所以当执行扣减库存和扣减账户时的远程调用也将被Milo框架拦截,只有创建订单、扣减库存和扣减账户都顺序完成,Try阶段才算完成。
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
当调用扣减库存的远程调用方法时stockInter.decreaseStock(stockReq),也会进入到handleAspectPointcutMethod,这时候MiloTransactionContext的值就不为空了,事务上下文保存着事务id,事务阶段为TRYING,角色为INITIATOR。接着进入到if逻辑部分,事务上下文将角色设置称为CONSUMER,那么根据之前的解析,将交给ConsumerMiloTransactionHandler处理。
在这里插入图片描述
在这里插入图片描述
ConsumerMiloTransactionHandler会先判断事务上下文的阶段,显然现在还是TRYING阶段,那么Milo将会根据事务上下文创建参与者MiloParticipantBean包含了confirm调用和cancel调用Bean并和事务id绑定,这是为后面的confirm阶段或者cancel阶段准备的,接着更新到事务日志表,这是事务日志milo_order_log对应的记录上参与者就会变成两个,最后调用pjp.proceed(),此时真正发起远程,进入到cloud-stock服务。
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
进入到cloud-stock服务的decrease方法,该方法同样标注了@MiloTCC(confirmMethod = “decreaseStockConfirm”,cancelMethod = “decreaseStockCancel”),那么同样会被Milo框架拦截,又一次进入到SpringCloudMiloTransactionAspectHandler。
在这里插入图片描述
如果你通过debug执行demo断点调试你会发现,此时上下文是为空的,但是可以在else逻辑从从Header获取到上下文,并且角色为CONSUMER,接着被修改为PROVIDER,根据之前的解析会交给ProviderMiloTransactionHandler处理。那么这里为什么可以从Header获取到上下文呢?当然就是cloud-order发起远程调用的时候传递过来的,那么cloud-order是如何传递事务上下文的呢?
在这里插入图片描述
答案就在milo-springcloud模块,MiloFeignTransactionContextInterceptor通过实现RequestInterceptor拦截到feign的远程调用。
在这里插入图片描述
先从线程本地获取到事务上下文,紧接着通过requestTemplate添加Header参数,键为MILO_TRANSACTION_CONTEXT,值为MiloTransactionContext的JSON后的值。因为开启Hystrix之后,远程调用会采用新的线程所以需要在线程间传递事务上下文,否则执行远程调用的线程将从线程本地拿不到事务上下文,如果没有开启Hystrix,那么不会有这个问题,因为远程调用的线程和payment的执行线程为同一个。
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
知道了事务上下文是如何传递的之后,我们回到之前说的milo-stock的decrease方法被拦截之后将交给ProviderMiloTransactionHandler处理,进入到ProviderMiloTransactionHandler的handle方法,根据MiloTransactionContext,switch case会走到TRYING,通过miloTransactionExecutor去创建并保存事务日志到库里面,此时milo_stock_log将会生成新的一条记录,接着执行pjp.proceed()去执行扣减库存逻辑
在这里插入图片描述
执行完扣减库存的到操作后执行扣减账户,处理的逻辑和扣减存一样,到这里Try阶段就基本解析完毕了。

我的公众号

Alt

发布了122 篇原创文章 · 获赞 127 · 访问量 93万+

猜你喜欢

转载自blog.csdn.net/u010739551/article/details/102795476