jeecg-boot的seata分布式事务没有回滚记录

运行低代码jeecg-boot的微服务中的分布式seata示例的的时候,发现了一个问题,库存服务在分布式事务失败的问题,没有回滚,这就尴尬了。进一步说明之前,先简单了解一下该示例的顺序图。

jeecg-boot的seata分布式事务没有回滚记录_第1张图片

可以看出这是一个典型的seata的分布式事务的例子,用户下单给订单服务,订单服务先生成一个一阶段订单,然后调用库存服务扣除商品库存服务,再调用钱包扣款,订单服务修改订单修改为下单成功,最后用户就可以看到接口返回下单成功。

我在测试的时候,发现库存服务执行成功,但是由于钱包服务的余额不足,扣款失败,整个分布式事务是失败的,但是库存服务扣掉的库存没有加回来。赶紧进行排查。先在每个微服务里头添加日志打印。

  log.info("RootContext.ID:{}",RootContext.getXID());

发现除了订单服务可以正常打印出

RootContext.ID:192.168.233.1:8091:3522101009186471944

其他服务的RootContext的ID为空,根据官方文档,这个值为空,表示该进程没有纳入分布式事务管理,这是为什么呢。折腾了一周,在官方的spring-cloud-alibaba的github代码中找到了seata的例子。spring-cloud-alibaba仓库

他那边没有这样的问题,对比了一下依赖,发现官方例子有spring-cloud-starter-alibaba-seata,而该例子没有,赶紧加上

  
            com.alibaba.cloud
            spring-cloud-starter-alibaba-seata
    

加了之后 ,原来为空的XID值非空了,库存服务在整个事务失败的时候,也能还原回来了。最后再分析一下代码,

spring-cloud-starter-alibaba-seata的包有SeataFeignClient 这个类,里头有这样一段代码,我给贴出来

/**
 * @author xiaojing
 */
public class SeataFeignClient implements Client {


	@Override
	public Response execute(Request request, Request.Options options) throws IOException {

		Request modifiedRequest = getModifyRequest(request);
		return this.delegate.execute(modifiedRequest, options);
	}

	private Request getModifyRequest(Request request) {

		String xid = RootContext.getXID();

		if (StringUtils.isEmpty(xid)) {
			return request;
		}

		Map> headers = new HashMap<>(MAP_SIZE);
		headers.putAll(request.headers());

		List seataXid = new ArrayList<>();
		seataXid.add(xid);
		headers.put(RootContext.KEY_XID, seataXid);

		return Request.create(request.method(), request.url(), headers, request.body(),
				request.charset());
	}

}

上面的代码就是往FeignClient的header添加一个头TX_XID,把XID 的值传递下去,根据官方说明Seata 全局事务的传播机制就是指事务上下文的传播,根本上,就是 XID 的应用运行时的传播方式。seata官方说明

之前由于没有加spring-cloud-starter-alibaba-seata,导致XID没有在微服务的feign调用之前传递,导致事务回滚失败。原因找到了

你可能感兴趣的:(Java,spring,cloud,分布式,java,开发语言,微服务)