traceid實現
需要依賴
<dependency><groupId>com.alibaba</groupId><artifactId>transmittable-thread-local</artifactId><version>2.14.5</version></dependency>
public class TraceIdContext {private static final String TRACE_ID = "traceId";private static final TransmittableThreadLocal<String> context = new TransmittableThreadLocal<>();// 使用雪花算法生成分布式唯一IDprivate static final Snowflake snowflake = IdUtil.getSnowflake(1, 1);public static void setTraceId(String traceId) {context.set(traceId);MDC.put(TRACE_ID, traceId);}/*** 生成新的雪花ID并設置為TraceId*/public static String generateAndSetTraceId() {String traceId = snowflake.nextIdStr();setTraceId(traceId);return traceId;}public static String generateTraceId() {return snowflake.nextIdStr();}public static String getTraceId() {return context.get();}public static void clear() {context.remove();MDC.remove(TRACE_ID);}
}
TraceIdFilter實現
@Slf4j
public class TraceIdFilter extends OncePerRequestFilter {private static final String TRACE_ID_HEADER = "X-Trace-Id";@Overrideprotected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain)throws ServletException, IOException {try {String traceId = request.getHeader(TRACE_ID_HEADER);if (StrUtil.isEmpty(traceId)) {traceId = TraceIdContext.generateAndSetTraceId();} else {TraceIdContext.setTraceId(traceId);}// 設置到響應頭response.addHeader(TRACE_ID_HEADER, traceId);filterChain.doFilter(request, response);} finally {TraceIdContext.clear();}}
}
注冊TraceFilterConfig
@Configuration
public class TraceFilterConfig {@Beanpublic FilterRegistrationBean<TraceIdFilter> traceIdFilter() {FilterRegistrationBean<TraceIdFilter> registration = new FilterRegistrationBean<>();registration.setFilter(new TraceIdFilter());registration.addUrlPatterns("/*");registration.setOrder(WebFilterOrderEnum.TRACE_FILTER);return registration;}
}
自定義的 Spring Security 配置適配器實現需添加TraceIdFilter, 在登錄后
// 添加 Token FilterhttpSecurity.addFilterBefore(new TraceIdFilter(), UsernamePasswordAuthenticationFilter.class);
在日志中也可以打印每個請求traceid, 其中 [%X{traceId}]) 就是上文 MDC.put(TRACE_ID, traceId)設置的
<property name="PATTERN_DEFAULT" value="%d{${LOG_DATEFORMAT_PATTERN:-yyyy-MM-dd HH:mm:ss.SSS}} | %highlight(${LOG_LEVEL_PATTERN:-%5p} ${PID:- }) | %boldYellow(%thread [%tid] [%X{traceId}]) %boldGreen(%-40.40logger{39}) | %m%n${LOG_EXCEPTION_CONVERSION_WORD:-%wEx}"/>
網頁效果
所有請求都會帶上traceid, 后期使用skywalking替換也很簡答