baomidou / dynamic-datasource

dynamic datasource for springboot 多数据源 动态数据源 主从分离 读写分离 分布式事务
https://www.kancloud.cn/tracy5546/dynamic-datasource/2264611
Apache License 2.0
4.68k stars 1.19k forks source link

多数据源 + eureka-feign-mybatis-seata 通过feign调用,调用方无法回滚 #339

Closed aqHi closed 3 years ago

aqHi commented 3 years ago

Please fill it out carefully, or it will be closed. 请认真填写,不然会直接关闭。

Enviroment

JDK Version(required): 1.8

SpringBoot Version(required): 2.3.5.RELEASE

dynamic-datasource-spring-boot-starter Version(required):3.2.1

druid Version(optional):

Describe what happened

服务A , B 均为为多数据源 ,eureka 为注册中心 ,A中方法开启全局事务,通过feign调用B,A中异常B无法回滚。

参考过seata官方的demo: https://github.com/seata/seata-samples/tree/master/springcloud-eureka-feign-mybatis-seata 也参考过: https://github.com/dynamic-datasource/dynamic-datasource-samples/tree/master/tx-seata-sample

对分布式事务不是很熟悉,想请教下问题出在哪儿 , 另外有没有 tx-seata-sample 集成 eureka + feign 的 demo ,感谢🙏


   @Autowired
    private OrderService orderService;

    @Transactional
    @GlobalTransactional(rollbackFor = Exception.class)
    public Receipt pay() {
        ...
        orderService.create();
    }

A中 OrderService 调用B的方法

@FeignClient(value = "xxx-b")
public interface OrderService {
    ...
    void create();
}
public class OrderService {

     // @Transactional(propagation = Propagation.REQUIRES_NEW) 加不加都不行
    public void create(){

    }
}
spring:
  datasource:
    dynamic:
      seata: true    #开启seata代理,开启后默认每个数据源都代理,如果某个不需要代理可单独关闭
      seata-mode: AT #支持XA及AT模式,默认AT
      primary: aaaa-a #记得设置一个默认数据源
      datasource: 
      ....略

seata:
  enabled: true
  application-id: xxxx-a
  # 事务分组
  tx-service-group: service-group-001
  enable-auto-data-source-proxy: false   #一定要是false
  service:
    vgroup-mapping:
      #key与上面的tx-service-group的值对应
      service-group-001: seata-server
  config:
    type: file
  registry:
    type: eureka
    # RegistryEurekaProperties
    eureka:
      serviceUrl: ${eureka.client.service-url.defaultZone}
      application: xxxx-a
      weight: 1

spring:
  datasource:
    dynamic:
      seata: true    #开启seata代理,开启后默认每个数据源都代理,如果某个不需要代理可单独关闭
      seata-mode: AT #支持XA及AT模式,默认AT
      primary: bbbb-b #记得设置一个默认数据源
      datasource: 
      ....略

seata:
  enabled: true
  application-id: xxxx-b
  # 事务分组
  tx-service-group: service-group-001
  enable-auto-data-source-proxy: false   #一定要是false
  service:
    vgroup-mapping:
      #key与上面的tx-service-group的值对应
      service-group-001: seata-server
  config:
    type: file
  registry:
    type: eureka
    # RegistryEurekaProperties
    eureka:
      serviceUrl: ${eureka.client.service-url.defaultZone}
      application: xxxx-b
      weight: 1

Expected Result:

Actual Result:

If there is an exception,or aop invalid,please attach the exception trace:

Just paste your stack trace here!

Steps to reproduce

huayanYu commented 3 years ago

初步分析是XID不同步,请查看seata相关文档

aqHi commented 3 years ago

@Slf4j
@Configuration
public class FeignXidRequestInterceptor implements RequestInterceptor {
    @Override
    public void apply(RequestTemplate template) {
        String xid = RootContext.getXID();
        if (StringUtils.isNotBlank(xid)) {
            log.info("feign 获得分布式事务xid:" + xid);
        } else {
            log.debug("feign 获得分布式事务xid为空");
        }
        template.header(RootContext.KEY_XID, xid);
    }
}