Spring Boot 应用中的事务管理与 Feign 调用问题分析及解决
创始人
2024-11-14 06:39:33
0

Spring Boot 应用中的事务管理与 Feign 调用问题分析及解决

  • Spring Boot 应用中的事务管理与 Feign 调用问题分析及解决
    • 问题背景
    • 问题分析
      • 可能的原因
    • 解决方案
      • 方案一:提交事务后再调用 Feign
      • 方案二:使用 `PROPAGATION_REQUIRES_NEW`
      • 方案三:使用 `@Async` 异步调用
    • 总结

Spring Boot 应用中的事务管理与 Feign 调用问题分析及解决

在微服务架构下,遇到这样的场景:一个服务需要调用另一个服务的接口来进行一系列操作,而这些操作又需要保证事务的一致性。然而,在实际开发过程中,可能会遇到一些问题,比如事务中所做的更改无法被 Feign 调用所看到。本文将以开发中遇到的一个问题当做一个例子来探讨这一问题及其解决方案。

问题背景

有一个内部商家管理模块,其主要职责是添加新的商家。在这个过程中,需要做如下几件事(已简化):

  1. 创建商家信息,并分配相应的角色。
  2. 为商家分配会员。

在这个过程中,为了保证数据的一致性和完整性,需要在方法上使用 @Transactional 注解。然而,在添加完商家之后,尝试调用 purchaseAPI.addMember 方法为商家分配会员时,发现无法获取到刚刚添加的 sys_supplier 商家信息。

问题分析

这个问题的根本原因在于事务隔离级别和 Feign 调用之间的交互。当在一个事务中执行了一系列操作后,这些操作所产生的数据更改只有在事务提交之后才会对外可见。而在同一事务中,Feign 调用实际上是在一个新的上下文中执行的,这意味着它不会看到未提交的更改。

可能的原因

  1. 事务隔离级别:默认情况下,Spring 的事务隔离级别是 ISOLATION_DEFAULT,这意味着它会使用底层数据库的默认隔离级别。如果数据库默认隔离级别是 READ_COMMITTEDREPEATABLE_READ,那么在事务中更新的数据在当前事务提交之前对其他事务不可见。

  2. Feign 调用与事务:Feign 调用实际上是在当前事务之外发生的,这意味着它不会受到当前事务的影响。因此,如果您在事务中更新了数据,Feign 调用将不会看到这些未提交的更改。

解决方案

方案一:提交事务后再调用 Feign

确保在调用 Feign 服务之前先提交事务。这可以通过将 Feign 调用放在事务范围之外来实现。例如:

@Override public void internalSupplierAdd(InternalSupplierDTO internalSupplierDTO, LoginUser loginUser) {     // ... (之前的代码)      //6.添加内部供应商     SysSupplier sysSupplier = new SysSupplier();     BeanUtils.copyProperties(internalSupplierDTO, sysSupplier);     sysSupplierMapper.insert(sysSupplier);      // 提交事务     PlatformTransactionManager transactionManager = TransactionAspectSupport.currentTransactionManager();     TransactionDefinition def = new DefaultTransactionDefinition();     TransactionStatus status = transactionManager.getTransaction(def);     transactionManager.commit(status);      //7.为商家分配会员     Result memberLevelResult = purchaseAPI.addMemberAndLevel(tenantId);     if (!memberLevelResult.isSuccess()) {         //接口请求失败         throw new JeecgBootException("分配会员出错!");     }      //...(后面的代码)  } 

方案二:使用 PROPAGATION_REQUIRES_NEW

如果希望在同一个方法中保持事务的原子性,但又需要确保 Feign 调用能够看到最新的数据,可以使用 PROPAGATION_REQUIRES_NEW 传播行为。这将创建一个新的事务,即使在当前事务中也是如此。

@Override @Transactional(propagation = Propagation.REQUIRES_NEW, rollbackFor = Exception.class) public void internalSupplierAdd(InternalSupplierDTO internalSupplierDTO, LoginUser loginUser) {     // ... (之前的代码)      //6.添加商家     SysSupplier sysSupplier = new SysSupplier();     BeanUtils.copyProperties(internalSupplierDTO, sysSupplier);     sysSupplierMapper.insert(sysSupplier);      //7.为商家分配会员     Result memberLevelResult = purchaseAPI.addMemberAndLevel(tenantId);     if (!memberLevelResult.isSuccess()) {         //接口请求失败         throw new JeecgBootException("分配会员出错!");     }      //...(之后的代码) } 

方案三:使用 @Async 异步调用

如果分配会员的操作不是必须同步完成的,可以考虑使用异步调用来避免阻塞事务。

@Override @Transactional(rollbackFor = Exception.class) public void internalSupplierAdd(InternalSupplierDTO internalSupplierDTO, LoginUser loginUser) {     // ... (之前的代码)      //6.添加商家     SysSupplier sysSupplier = new SysSupplier();     BeanUtils.copyProperties(internalSupplierDTO, sysSupplier);     sysSupplierMapper.insert(sysSupplier);      //7.为商家分配会员     asyncPurchaseService.addMemberAndLevelAsync(tenantId);      //... (之后的代码) }  // 异步服务 @Service public class AsyncPurchaseService {      @Autowired     private PurchaseAPI purchaseAPI;      @Async     public void addMemberAndLevelAsync(Integer tenantId) {         Result memberLevelResult = purchaseAPI.addMemberAndLevel(tenantId);         if (!memberLevelResult.isSuccess()) {             //接口请求失败             throw new JeecgBootException("分配会员出错!");         }     } } 

总结

通过以上分析和解决方案,可以有效地解决事务中 Feign 调用无法看到未提交更改的问题。选择哪种解决方案取决于具体需求和场景。无论是通过手动提交事务、使用特定的事务传播行为还是使用异步调用,都可以确保数据的一致性和事务的完整性。

相关内容

热门资讯

绝活儿辅助!广西老友玩老是输怎... 绝活儿辅助!广西老友玩老是输怎么办(辅助挂)都是真的有辅助app(讲解有挂)在进入广西老友玩老是输怎...
法门辅助!福建13水插件(辅助... 法门辅助!福建13水插件(辅助挂)一贯是有辅助技巧(有挂技术)1、许多玩家不知道福建13水插件辅助怎...
办法辅助!潮友会app下载官方... 办法辅助!潮友会app下载官方辅助器(辅助挂)真是真的是有辅助app(有挂教程)该软件可以轻松地帮助...
妙招辅助!邯郸胡乐挂辅助(辅助... 妙招辅助!邯郸胡乐挂辅助(辅助挂)好像存在有辅助插件(有挂方略)1、上手简单,内置详细流程视频教学,...
教程书辅助!乐酷辅助(辅助挂)... 教程书辅助!乐酷辅助(辅助挂)其实存在有辅助脚本(有挂细节)乐酷辅助能透视中分为三种模型:乐酷辅助模...
学习辅助!决战卡五星辅助(辅助... 学习辅助!决战卡五星辅助(辅助挂)本来真的是有辅助软件(有人有挂)学习辅助!决战卡五星辅助(辅助挂)...
绝活辅助!边锋嘉兴麻将辅助器(... 绝活辅助!边锋嘉兴麻将辅助器(辅助挂)真是真的有辅助神器(新版有挂)1、边锋嘉兴麻将辅助器公共底牌简...
举措辅助!枫叶辅助器(辅助挂)... 举措辅助!枫叶辅助器(辅助挂)本来存在有辅助技巧(竟然有挂)1、下载好枫叶辅助器正确养号方法之后点击...
讲义辅助!点我达辅助(辅助挂)... 讲义辅助!点我达辅助(辅助挂)一直存在有辅助技巧(有人有挂)1、点我达辅助辅助器安装包、点我达辅助辅...
模块辅助!威信茶馆有挂的吗(辅... 模块辅助!威信茶馆有挂的吗(辅助挂)一直真的是有辅助脚本(揭秘有挂)1、玩家可以在威信茶馆有挂的吗线...