seata eureka 全局事务编号传递关键代码
网文大部分是基于dobbo的分析,eureka传递xid(全局事务编号)的分析目前还没找到,断点跟踪了seata-sample的工程
seata-sample地址:https://github.com/seata/seata-samples
seata版本:0.6.1
关键依赖
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-alibaba-seata</artifactId>
<version>0.9.1.BUILD-SNAPSHOT</version>
<exclusions>
<exclusion>
<groupId>io.seata</groupId>
<artifactId>seata-spring</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>io.seata</groupId>
<artifactId>seata-all</artifactId>
<version>${seata.version}</version>
</dependency>
构建feign请求头
package org.springframework.cloud.alibaba.seata.rest;
import io.seata.core.context.RootContext;
import java.io.IOException;
import org.springframework.http.HttpRequest;
import org.springframework.http.client.ClientHttpRequestExecution;
import org.springframework.http.client.ClientHttpRequestInterceptor;
import org.springframework.http.client.ClientHttpResponse;
import org.springframework.http.client.support.HttpRequestWrapper;
import org.springframework.util.StringUtils;
public class SeataRestTemplateInterceptor implements ClientHttpRequestInterceptor {
public SeataRestTemplateInterceptor() {
}
public ClientHttpResponse intercept(HttpRequest httpRequest, byte[] bytes, ClientHttpRequestExecution clientHttpRequestExecution) throws IOException {
HttpRequestWrapper requestWrapper = new HttpRequestWrapper(httpRequest);
String xid = RootContext.getXID();
if(!StringUtils.isEmpty(xid)) {
//构建请求头
requestWrapper.getHeaders().add("TX_XID", xid);
}
return clientHttpRequestExecution.execute(requestWrapper, bytes);
}
}
获取xid放入seata上下文
package org.springframework.cloud.alibaba.seata.web;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
public class SeataHandlerInterceptorConfiguration implements WebMvcConfigurer {
public SeataHandlerInterceptorConfiguration() {
}
public void addInterceptors(InterceptorRegistry registry) {
//注册HandlerInterceptor,拦截所有请求
registry.addInterceptor(new SeataHandlerInterceptor()).addPathPatterns(new String[]{"/**"});
}
}
package org.springframework.cloud.alibaba.seata.web;
import io.seata.core.context.RootContext;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.util.StringUtils;
import org.springframework.web.servlet.HandlerInterceptor;
public class SeataHandlerInterceptor implements HandlerInterceptor {
private static final Logger log = LoggerFactory.getLogger(SeataHandlerInterceptor.class);
public SeataHandlerInterceptor() {
}
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) {
String xid = RootContext.getXID();
String rpcXid = request.getHeader("TX_XID");
//获取全局事务编号
if(log.isDebugEnabled()) {
log.debug("xid in RootContext {} xid in RpcContext {}", xid, rpcXid);
}
if(xid == null && rpcXid != null) {
//设置全局事务编号
RootContext.bind(rpcXid);
if(log.isDebugEnabled()) {
log.debug("bind {} to RootContext", rpcXid);
}
}
return true;
}
public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception e) {
String rpcXid = request.getHeader("TX_XID");
if(!StringUtils.isEmpty(rpcXid)) {
String unbindXid = RootContext.unbind();
if(log.isDebugEnabled()) {
log.debug("unbind {} from RootContext", unbindXid);
}
if(!rpcXid.equalsIgnoreCase(unbindXid)) {
log.warn("xid in change during RPC from {} to {}", rpcXid, unbindXid);
if(unbindXid != null) {
RootContext.bind(unbindXid);
log.warn("bind {} back to RootContext", unbindXid);
}
}
}
}
}
以上就是服务中心基于eureka的feign调用时传递及获取xid(全局事务编号)的核心代码