外国的免费网站网站高端建设网站企业
概述
业务中经常会遇到分布式事务失效的场景;通常情况下分析下两边的xid
是否一致,就可以初步判定原因;
我这边正好遇到openfeign
调用时其中一个rm抛异常,其他rm没回滚的现象;
排查了下发现tm和第一个rm
注册到seata
的xid
就不通;
然后看了下相关代码,发现openfeign
的拦截器中没有对xid
进行传递,后续传递xid
之后,分布式事务后面回滚就ok
了;
当前环境
jdk:1.8
seata-spring-boot-starter:1.6.1
spring-cloud-dependencies:2021.0.5
spring-cloud-alibaba-dependencies:2021.0.5.0
解决方案
在feign拦截器中传递seata的xid
package com.xxx.xxx.xxx.config;import cn.dev33.satoken.exception.SaTokenException;
import cn.dev33.satoken.stp.StpUtil;
import cn.hutool.core.util.StrUtil;
import feign.RequestInterceptor;
import feign.RequestTemplate;
import io.seata.core.context.RootContext;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;import javax.annotation.Resource;@Configuration
public class FeignConfig {@Beanpublic RequestInterceptor requestInterceptor() {// 添加拦截器,所有内部服务调用都带上tokenreturn new RequestInterceptor() {@Overridepublic void apply(RequestTemplate requestTemplate) {//feign seata xid传递seataHeadProcess(requestTemplate);}};}/*** 传递seata的全局xid*/private void seataHeadProcess(RequestTemplate requestTemplate){// 从 seata 的 RootContext 中获取当前 XIDString xid = RootContext.getXID();if (StrUtil.isBlank(xid)) return;requestTemplate.header(RootContext.KEY_XID, xid);}
}
源码分析
一般springboot
中的先找xxxAutoConfiguration
然后在SeataAutoConfiguration
的同级目录下发现了SeataHttpAutoConfiguration
,就是这个了;
然后一路点进去,最后发现在
io.seata.integration.http.TransactionPropagationInterceptor
中就看到了关于http
请求头中xid
的相关处理