集成 spring-cloud-starter-alibaba-seata @GlobalTransactional 失效的问题

问题复现

设备健康 business 服务调用 admin 服务,前者制造异常并成功回滚,后者未出现异常但是并未回滚

 

源码分析

加上全局事务注解之后会走 io.seata.tm.api.TransactionalTemplate#execute 方法做事务相关处理;

该方法主要分为5个步骤:

第一步:获取当前全局事务

第二步:开启全局事务,并处理业务

第三步:业务异常则回滚事务

第四步:业务正常则提交事务

第五步:清理

 

 

问题定位

这次问题出现在第一步,从上下文获取当前全局事务

  

business 服务是全局事务的第一段,拿不到 xid 理所应当,会创建一个全局事务对象

 

admin 服务是全局事务的第二段,理论上 business 会把 xid 传递给 admin;

事实上发现 RootContext 并未获取到 xid,从而 admin 也创建一个全局事务对象;

这样一来,business 和 admin 各自创建了自己的全局事务,xid 不同,导致 business 能够正常回滚,admin 却提交了自己的事务。

 

个人猜测是 request 把 xid 丢失了,没有传递给下游;

果不其然 com.alibaba.cloud.seata.web.SeataHandlerInterceptor 打断点,却始终未进断点

 

这里能断定 com.alibaba.cloud.seata.web.SeataHandlerInterceptorConfiguration 未生效;

由于使用了 @ConditionalOnWebApplication,必须是 web mvc 项目才生效。

 

web mvc 自动配置 org.springframework.boot.autoconfigure.web.servlet.WebMvcAutoConfiguration 前提是没有 

org.springframework.web.servlet.config.annotation.WebMvcConfigurationSupport 这个 bean

 

所以罪魁祸首是 WebMvcConfigurationSupport

总结

项目总如果使用了 WebMvcConfigurationSupport 会直接导致 WebMvcConfigurer 不生效,那么需要将 SeataHandlerInterceptor 手动放到拦截器链路中;

个人建议实现 WebMvcConfigurer 而不是继承 WebMvcConfigurationSupport,这样的话一切都不会有问题。

seata 常见问题:http://seata.io/zh-cn/docs/overview/faq.html

posted @ 2021-12-28 11:28  来世还做程序员  阅读(2410)  评论(0编辑  收藏  举报