标签:import png rar 过滤 roc vertica 并发 wait down
之前在.net项目和java项目里有过不同的最佳实践。见下面链接。
▄︻┻┳═一巧用CurrentThread.Name来唯一标记一次请求的所有日志
▄︻┻┳═一巧用CurrentThread.Name来唯一标记一次请求的所有日志(续)
▄︻┻┳═一巧用CurrentThread.Name来唯一标记一次请求的所有日志(完结篇)
▄︻┻┳═一asp.net拦截器
▄︻┻┳═一巧用CurrentThread.Name来唯一标记一次请求的所有日志(java-logback篇)
本文呢,还是java项目,这次用AOP来实现。
package com.aop; import lombok.extern.slf4j.Slf4j; import org.aspectj.lang.JoinPoint; import org.aspectj.lang.ProceedingJoinPoint; import org.aspectj.lang.annotation.After; import org.aspectj.lang.annotation.Around; import org.aspectj.lang.annotation.Aspect; import org.aspectj.lang.annotation.Pointcut; import org.springframework.stereotype.Component; import java.util.Random; /** * 重置工作线程名为唯一字符串, * 这样在生产排障时,可以快速过滤一次请求的所有日志 */ @Slf4j @Component @Aspect public class WorkThreadNameAspect { @Pointcut("execution(public * com.clz.*.*(..))") public void pointCut() { } ThreadLocal<String> threadLocal = new ThreadLocal<>(); // @Before("pointCut()") // public void before(JoinPoint joinPoint) { public void setThreadName(JoinPoint joinPoint) { // if (Thread.currentThread().getName().contains("-")) { String threadNameFlag = getMethodSignature(joinPoint); String before = Thread.currentThread().getName(); String s = threadLocal.get(); if (threadLocal.get() == null) { String threadName = threadNameFlag + System.currentTimeMillis() + "_" + new Random().nextInt(1000); threadLocal.set(threadName); Thread.currentThread().setName(threadName); } log.debug("threadName={}→→→{}, threadLocal.get()={}→→→{}", before, Thread.currentThread().getName(), s, threadLocal.get()); // } } String getMethodSignature(JoinPoint joinPoint) { return joinPoint.getSignature().getDeclaringType().getSimpleName() + "_" + joinPoint.getSignature().getName(); } @After("pointCut()") public void after(JoinPoint joinPoint) { String threadNameFlag = getMethodSignature(joinPoint); if (threadLocal.get() != null && threadLocal.get().contains(threadNameFlag)) { log.debug("remove name {}", Thread.currentThread().getName()); threadLocal.remove(); } } @Around("pointCut()") public Object around(ProceedingJoinPoint joinPoint) throws Throwable { setThreadName(joinPoint); long start = System.currentTimeMillis(); try { return joinPoint.proceed(joinPoint.getArgs()); } finally { log.info("{} duration=执行耗时={}ms", getMethodSignature(joinPoint), System.currentTimeMillis() - start); } } }
注意,aspectj里各个advice的执行顺序,Around advice是先于Before advice的,所以设置线程名要在@Around注解的方法里来执行。下图是advice的执行顺序。
好了。如下多线程模拟并发来测试,从运行结果可以看出,想定位某一次请求的日志,就方便多了。
package com.clz; import lombok.extern.slf4j.Slf4j; import org.junit.jupiter.api.Test; import org.junit.runner.RunWith;import org.springframework.boot.test.context.SpringBootTest; import org.springframework.test.context.junit4.SpringRunner; import java.util.concurrent.LinkedBlockingDeque; import java.util.concurrent.ThreadPoolExecutor; import java.util.concurrent.TimeUnit; @Slf4j @SpringBootTest @RunWith(SpringRunner.class) class AOPTest { @Autowired private Class1 class1; @Test public void testWorkThreadName() throws InterruptedException { class1.test(); Thread.currentThread().setName("mmmmmmmm"); log.info("异步多线程测试"); ThreadPoolExecutor poolExecutor = new ThreadPoolExecutor(5, 5, 10, TimeUnit.MILLISECONDS, new LinkedBlockingDeque<>(5)); Thread.sleep(5); for (int i = 0; i < 2; i++) { poolExecutor.execute(() -> { class1.test(); // csdfsdafdsfdsfdsf.test(); }); } poolExecutor.shutdown(); poolExecutor.awaitTermination(2, TimeUnit.SECONDS); } }
利用AOP设置工作线程的名字,来快速过滤出一次请求的所有日志
标签:import png rar 过滤 roc vertica 并发 wait down
原文地址:https://www.cnblogs.com/buguge/p/13531945.html