项目场景:
相关背景:
微服务场景下,配置了统一全局异常处理,导致seata在AT模式下无法正常回滚问题
spring boot版本 2.2.2 cloud 版本 Hoxton.RELEASE
seata版本1.4
问题描述:
假设服务A调用服务B, 服务B发生异常,由于全局异常处理的存在(@ControllerAdvice), seata 无法拦截到B服务的异常,从而导致分布式事务未生效解决方案:
利用AOP拦截@GlobalTransactional 检查是否发生异常,如有异常,则回滚事务
上代码
/**
* seata AT模式下事务异常回滚操作, 仅需在全局事务发起端配置此Handle
*/
@Slf4j
@Aspect
@Component
public class ATTransactionalHandler {
@Pointcut("@annotation(io.seata.spring.annotation.GlobalTransactional)")
public void txAnnotation(){
}
@AfterThrowing(throwing = "throwable", pointcut = "txAnnotation()")
public void doAfterReturning(Throwable throwable) {
GlobalTransaction globalTransaction =
GlobalTransactionContext.getCurrent();
if (globalTransaction == null) {
return;
}
log.info("AOP------- 全局事务回滚--
---xid:{}------》", globalTransaction.getXid());
try {
globalTransaction.rollback();
} catch (TransactionException e) {
e.printStackTrace();
}
}
}
由于AOP只能处理主事务端异常,而无法处理从事务端异常,而且我们配置了全局异常处理,所以rpc一定会有返回值
所以在每个全局事务方法最后, 需要判断rpc是否发生异常
发生异常则抛出RuntimeException, 配置的aop拦截则会回滚事务