在微服务框架下,需要通过traceId来定位到整个链路中每个细节的运行情况,这里不引用外部组件,自己来进行实现。当然还保证在多线程环境下的一致性。
1)接口入口侧如果有traceId,则获取;如果没有则生成;
2)定义生成traceId的规则;
3)traceId可以默认打印到log中,不需要自己显示定义;
4)通过feign传输到后端服务中
3.1)TraceId生成算法
参考:https://help.aliyun.com/document_detail/151840.html
- public static String genTraceId() {
-
- try {
- StringBuilder sb = new StringBuilder();
- InetAddress addr = InetAddress.getLocalHost();
- if (null == addr) {
- return TRACE_ID_VALUE_DEFAULT;
- }
- String addrStr = addr.getHostAddress();
- if (null == addrStr) {
- return TRACE_ID_VALUE_DEFAULT;
- }
- String[] addrArr = addrStr.split("\\.");
- if (addrArr.length != 4) {
- return TRACE_ID_VALUE_DEFAULT;
- }
-
- sb.append(StringUtils.leftPad(Integer.toHexString(Integer.valueOf(addrArr[0])) , 2, "0"))
- .append(StringUtils.leftPad(Integer.toHexString(Integer.valueOf(addrArr[1])) , 2, "0"))
- .append(StringUtils.leftPad(Integer.toHexString(Integer.valueOf(addrArr[2])) , 2, "0"))
- .append(StringUtils.leftPad(Integer.toHexString(Integer.valueOf(addrArr[3])) , 2, "0"))
- .append(System.currentTimeMillis())
- .append(RandomUtil.randomNumbers(4))
- .append(ProcessHandle.current().pid());
-
- return sb.toString();
- } catch (Exception e) {
- return TRACE_ID_VALUE_DEFAULT;
- }
- }
3.2)服务入口日志拦截
- @EnableAspectJAutoProxy
- @Component
- @Aspect
- @Slf4j
- public class InterfaceLogAspect {
-
- @Around("execution(* com.springboot.k8s.demo.interfaces.*.*(..))")
- public Object interfaceAround(ProceedingJoinPoint joinPoint) {
- String className = joinPoint.getTarget().getClass().getSimpleName();
- Object[] args = joinPoint.getArgs();
- MethodSignature signature = (MethodSignature) joinPoint.getSignature();
- Parameter[] argNames = signature.getMethod().getParameters();
- StringBuilder sb = new StringBuilder(className + "." + joinPoint.getSignature().getName() + " -- ");
-
- //获取RequestAttributes
- RequestAttributes requestAttributes = RequestContextHolder.getRequestAttributes();
- //从获取RequestAttributes中获取HttpServletRequest的信息
- HttpServletRequest request = (HttpServletRequest) requestAttributes.resolveReference(RequestAttributes.REFERENCE_REQUEST);
- TraceIdUtil.initTraceId(request);
-
- StopWatch clock = new StopWatch();
- clock.start();
- Object retVal = null;
- try {
- Map
paramMap = new HashMap<>(); - for (int i = 0; i < argNames.length; i++) {
- paramMap.put(argNames[i].getName(), args[i]);
- }
- LoggerUtils.auditLogInfo(LogLabelEnum.REQUEST_IN.getLogLabel(), paramMap);
- retVal = joinPoint.proceed(joinPoint.getArgs());
- } catch (Throwable e) {
- //..
- } finally {
- //..
- }
- return retVal;
- }
- }
3.3)FeignClient服务之间传递TraceId:
- @Service
- public class MyRequestInterceptor implements RequestInterceptor {
- @Override
- public void apply(RequestTemplate template) {
- template.header(TraceIdUtil.TRACE_ID_KEY, TraceIdUtil.getTraceId());
- }
- }
3.4)logback.xml
- <appender name="consoleLog" class="ch.qos.logback.core.ConsoleAppender">
- <layout class="ch.qos.logback.classic.PatternLayout">
- <pattern>[%-5level][%date{yyyy-MM-dd HH:mm:ss:SSS}][%logger:%line] --%mdc{client} %msg||traceId=%X{Trace-Id}%npattern>
-
- layout>
- appender>
备注:"%X{Trace-Id}"即将MDC中的以Trace-Id为key的值同步到日志中,也就是TraceIdUtil.TRACE_ID_KEY。
完整的TraceIdUtill为:
- public class TraceIdUtil {
-
- public static final String TRACE_ID_KEY = "Trace-Id";
-
- public static final String TRACE_ID_VALUE_DEFAULT = "000000";
-
- public static void setTraceId(String traceId) {
- //如果参数为空,则设置默认traceId
- //将traceId放到MDC中
- MDC.put(TRACE_ID_KEY, traceId);
- }
-
- public static String getTraceId() {
- String traceId = MDC.get(TRACE_ID_KEY);
-
- return StringUtils.isNotBlank(traceId) ? traceId : TRACE_ID_VALUE_DEFAULT;
- }
-
- /**
- * generate traceId: https://help.aliyun.com/document_detail/151840.html
- */
- public static String genTraceId() {
-
- try {
- StringBuilder sb = new StringBuilder();
- InetAddress addr = InetAddress.getLocalHost();
- if (null == addr) {
- return TRACE_ID_VALUE_DEFAULT;
- }
- String addrStr = addr.getHostAddress();
- if (null == addrStr) {
- return TRACE_ID_VALUE_DEFAULT;
- }
- String[] addrArr = addrStr.split("\\.");
- if (addrArr.length != 4) {
- return TRACE_ID_VALUE_DEFAULT;
- }
-
- sb.append(StringUtils.leftPad(Integer.toHexString(Integer.valueOf(addrArr[0])) , 2, "0"))
- .append(StringUtils.leftPad(Integer.toHexString(Integer.valueOf(addrArr[1])) , 2, "0"))
- .append(StringUtils.leftPad(Integer.toHexString(Integer.valueOf(addrArr[2])) , 2, "0"))
- .append(StringUtils.leftPad(Integer.toHexString(Integer.valueOf(addrArr[3])) , 2, "0"))
- .append(System.currentTimeMillis())
- .append(RandomUtil.randomNumbers(4))
- .append(ProcessHandle.current().pid());
-
- return sb.toString();
- } catch (Exception e) {
- return TRACE_ID_VALUE_DEFAULT;
- }
- }
-
- public static void initTraceId(HttpServletRequest request) {
- String traceId = "";
- if (request != null) {
- //get traceId from request
- traceId = request.getHeader(TraceIdUtil.TRACE_ID_KEY);
- }
- //generate new traceId
- if (StringUtils.isBlank(traceId) || TRACE_ID_VALUE_DEFAULT.equals(traceId)){
- traceId = TraceIdUtil.genTraceId();
- }
-
- TraceIdUtil.setTraceId(traceId);
- }
-
- public static void main(String[] args) {
- System.out.println(TraceIdUtil.genTraceId());
- }
- }
4.1)线程配置
- @Configuration
- public class ThreadPoolConfig {
-
- public static final String ASYNC_EXECUTOR_NAME = "threadPoolTaskExecutor";
-
- @Bean(name=ASYNC_EXECUTOR_NAME)
- public ThreadPoolTaskExecutor threadPoolTaskExecutor() {
- ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
- // for passing in request scope context
- executor.setTaskDecorator(new ContextCopyingDecorator());
- executor.setCorePoolSize(10);
- executor.setMaxPoolSize(20);
- executor.setQueueCapacity(100);
- executor.setWaitForTasksToCompleteOnShutdown(true);
- executor.setThreadNamePrefix("SeelAsyncThread-");
- executor.setRejectedExecutionHandler(new ThreadPoolExecutor.AbortPolicy());
- executor.initialize();
- return executor;
- }
- }
4.2)定义TaskDecorator
- public class ContextCopyingDecorator implements TaskDecorator {
-
- @Override
- public Runnable decorate(Runnable runnable) {
- RequestAttributes context = RequestContextHolder.currentRequestAttributes();
- Map
contextMap = MDC.getCopyOfContextMap(); - return () -> {
- try {
- RequestContextHolder.setRequestAttributes(context);
- MDC.setContextMap(contextMap);
- runnable.run();
- } finally {
- RequestContextHolder.resetRequestAttributes();
- }
- };
- }
- }
Author:忆之独秀
Email:leaguenew@qq.com
转载注明出处: