实现原理
api入口或者网关处生成traceId,调用服务时优先检查是否头部带有traceId,有则复用,没有则生成
实现方式
处理api相关traceId
1.通过filter复用或者生成traceId,并且将traceId输入到响应头中
java
import java.io.IOException;
import java.util.UUID;
import javax.servlet.FilterChain;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.slf4j.MDC;
import org.springframework.web.filter.OncePerRequestFilter;
public class TraceIdFilter extends OncePerRequestFilter {
public TraceIdFilter() {
}
protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException {
String traceId = request.getHeader("X-Trace-Id");
if (traceId == null) {
traceId = this.generateTraceId();
}
MDC.put("traceId", traceId);
response.setHeader("X-Trace-Id", traceId);
try {
filterChain.doFilter(request, response);
} finally {
MDC.clear();
}
}
private String generateTraceId() {
return UUID.randomUUID().toString().replace("-", "");
}
}
2、在对应项目中启用filter
java
@Configuration
public class WebFilterConfig {
@Bean
public FilterRegistrationBean<TraceIdFilter> loggingFilter() {
FilterRegistrationBean<TraceIdFilter> registrationBean = new FilterRegistrationBean<>();
registrationBean.setFilter(new TraceIdFilter());
registrationBean.addUrlPatterns("/*"); // 只对特定 URL 匹配
return registrationBean;
}
}
Feign调用时传递traceId
1、声明拦截器(feign调用时从mdc获取traceId放入请求头中)
java
import feign.RequestInterceptor;
import feign.RequestTemplate;
import org.slf4j.MDC;
public class FeIgnMCDInterceptor implements RequestInterceptor {
public FeIgnMCDInterceptor() {
}
public void apply(RequestTemplate template) {
String traceId = MDC.get("traceId");
if (traceId != null) {
template.header("X-Trace-Id", new String[]{traceId});
}
}
}
2、启用拦截器
java
// 任意位置注册为springbean即可
@Bean
public FeIgnMCDInterceptor feIgnMCDInterceptor() {
return new FeIgnMCDInterceptor();
}
日志配置文件中打印traceId
XML
<!-- 日志输出格式 -->
<property name="log.pattern" value="%d{yyyy-MM-dd HH:mm:ss.SSS} [${application_name}] [%X{traceId}] [%thread] %-5level %logger - [%method,%line] - %msg%n" />