-
在网关生成TraceId:在网关处,可以拦截所有的请求,在请求进入系统时生成唯一的TraceId,并将其添加到请求的Header中,例如使用
UUID.randomUUID().toString()
生成一个唯一的TraceId,并将其添加到HTTP Header中。 -
传递TraceId到各个服务:网关转发请求到各个微服务时,需要将TraceId传递下去。这可以通过在网关处将TraceId添加到HTTP Header中,然后微服务在接收到请求时提取Header中的TraceId,并设置到MDC中。
-
在各个服务中打印TraceId:使用logback,在日志输出时打印TraceId。这可以通过logback的配置来实现。
下面是一个简单的示例:
<!-- logback-spring.xml -->
<configuration>
<!-- Define the pattern for logging including TraceId -->
<property name="LOG_PATTERN" value="%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{36} [%X{TraceId}] - %msg%n"/>
<!-- Console Appender -->
<appender name="CONSOLE" class="ch.qos.logback.core.ConsoleAppender">
<encoder>
<pattern>${LOG_PATTERN}</pattern>
</encoder>
</appender>
<!-- Root Logger -->
<root level="info">
<appender-ref ref="CONSOLE"/>
</root>
</configuration>
在这个配置中,[%X{TraceId}]
用于从MDC中获取TraceId并打印到日志中。
在微服务中,接收到请求时,需要将TraceId从Header中提取出来,并设置到MDC中:
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.slf4j.MDC;
import javax.servlet.*;
import javax.servlet.http.HttpServletRequest;
import java.io.IOException;
import java.util.UUID;
public class TraceIdFilter implements Filter {
private static final Logger logger = LoggerFactory.getLogger(TraceIdFilter.class);
@Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
HttpServletRequest httpRequest = (HttpServletRequest) request;
String traceId = httpRequest.getHeader("TraceId");
if (traceId == null || traceId.isEmpty()) {
traceId = UUID.randomUUID().toString();
logger.info("Generated TraceId: {}", traceId);
}
MDC.put("TraceId", traceId);
try {
chain.doFilter(request, response);
} finally {
MDC.remove("TraceId");
}
}
}
这个Filter用于从请求中获取TraceId,如果请求中没有TraceId,则生成一个新的,并将其设置到MDC中。然后在chain.doFilter(request, response);
之后,清理MDC,确保不会影响其他请求的TraceId。
最后,在微服务的启动类中注册这个Filter:
import org.springframework.boot.web.servlet.FilterRegistrationBean;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@Configuration
public class WebConfig {
@Bean
public FilterRegistrationBean<TraceIdFilter> traceIdFilter() {
FilterRegistrationBean<TraceIdFilter> registrationBean = new FilterRegistrationBean<>();
registrationBean.setFilter(new TraceIdFilter());
registrationBean.addUrlPatterns("/*"); // Add filter to all URLs
return registrationBean;
}
}
这样,就可以在整个系统中追踪请求,而且在日志中打印出TraceId,方便追踪和调试。