...
 
Commits (4)
    https://gitcode.net/abu935009066/easy-admin/-/commit/e5dcf197a884a6293ae4be2f1379ab893e3fba20 增强异步线程池情况下trace功能 2023-04-17T09:40:43+08:00 laker 935009066@qq.com https://gitcode.net/abu935009066/easy-admin/-/commit/39576ffa79cc4c4984f698e95c667ed518f0eaec 增强异步线程池情况下trace功能 2023-04-17T10:38:12+08:00 laker 935009066@qq.com https://gitcode.net/abu935009066/easy-admin/-/commit/698b1e4131f5cc4cb8740ea886a5324349b720ba 增强异步线程池情况下trace功能 2023-04-17T11:05:45+08:00 laker 935009066@qq.com https://gitcode.net/abu935009066/easy-admin/-/commit/4b0eb21ef062999b77b9f1ba0f22e3764fcb24d4 优化代码注释 2023-04-18T13:51:59+08:00 laker 935009066@qq.com
......@@ -117,13 +117,17 @@ public class DruidConfig {
return registrationBean;
}
// 参见 DruidFilterConfiguration
/**
* 参见 DruidFilterConfiguration
*/
@Bean
public StatFilter statFilter() {
return new StatFilter();
}
// 参见 DruidSpringAopConfiguration
/**
* 参见 DruidSpringAopConfiguration
*/
@Bean
public Advice advice() {
return new DruidStatInterceptor();
......
......@@ -11,8 +11,9 @@ import springfox.documentation.spring.web.plugins.Docket;
import springfox.documentation.swagger2.annotations.EnableSwagger2WebMvc;
/**
* ip:port/doc.html
* @author longli
* 接口文档描述,访问地址:http://ip:port/doc.html
*
* @author laker
*/
@Configuration
@EnableSwagger2WebMvc
......
......@@ -20,6 +20,10 @@ import java.time.LocalDateTime;
import java.time.LocalTime;
import java.time.format.DateTimeFormatter;
/**
* 自定义扩展jackson序列化和反序列化
* @author laker
*/
@Component
public class JacksonCustomizer implements Jackson2ObjectMapperBuilderCustomizer {
......
......@@ -3,14 +3,15 @@ package com.laker.admin.framework.ext.thread;
import cn.hutool.core.util.IdUtil;
import com.laker.admin.framework.EasyAdminConstants;
import com.laker.admin.framework.aop.trace.SpanType;
import com.laker.admin.framework.aop.trace.Trace;
import com.laker.admin.framework.aop.trace.TraceContext;
import lombok.extern.slf4j.Slf4j;
import org.slf4j.MDC;
import java.util.Map;
import java.util.concurrent.Callable;
import java.util.concurrent.Future;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.RunnableFuture;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.TimeoutException;
/**
* 自定义扩展线程池用于捕获执行中异常,防止异常被吞 + 解决MDC参数问题。
......@@ -27,25 +28,25 @@ public class EasyAdminMDCThreadPoolExecutor extends EasyAdminThreadPoolExecutor
* @param prefix 线程名前缀,e.g:MCP-POOL
*/
public EasyAdminMDCThreadPoolExecutor(int poolSize, int queueSize, String prefix) {
super(poolSize, poolSize, prefix);
super(poolSize, queueSize, prefix);
// 非核心线程如果处于闲置状态超过该值,就会被销毁。如果设置allowCoreThreadTimeOut(true),则会也作用于核心线程。
this.allowCoreThreadTimeOut(true);
}
/**
* submit Runnable callable 都会走这里,所以我们只需要改写这里即可。
*
* @param command
*/
@Override
public void execute(Runnable command) {
super.execute(wrap(command, MDC.getCopyOfContextMap()));
}
// @Override
// public Future<?> submit(Runnable task) {
// return super.submit(wrap(task, MDC.getCopyOfContextMap()));
// }
if (command instanceof RunnableFuture) {
// submit future
super.execute(new EasyAdminFuture((RunnableFuture) command, MDC.getCopyOfContextMap()));
} else {
super.execute(wrapExecuteRunnable(command, MDC.getCopyOfContextMap()));
}
@Override
public Future<?> submit(Callable task) {
return super.submit(wrap(task, MDC.getCopyOfContextMap()));
}
......@@ -56,79 +57,84 @@ public class EasyAdminMDCThreadPoolExecutor extends EasyAdminThreadPoolExecutor
* @param threadContext
* @return
*/
private Runnable wrap(final Runnable runnable, final Map<String, String> threadContext) {
// 父线程 trace对象
// Trace trace = TraceContext.getTrace();
private static Runnable wrapExecuteRunnable(final Runnable runnable, final Map<String, String> threadContext) {
return () -> {
if (threadContext == null) {
MDC.clear();
} else {
MDC.setContextMap(threadContext);
}
// // 增加trace对象 父子线程传递 start
// if (trace == null) {
// TraceContext.clear();
// } else {
// TraceContext.setTrace(trace);
// }
// // 增加trace对象 父子线程传递 end
setTraceIdIfAbsent();
try {
TraceContext.addSpan("subThread.run", SpanType.Thread);
TraceContext.addSpan("subThread.executeRunnable", SpanType.Thread);
runnable.run();
} finally {
TraceContext.stopSpan(1);
MDC.clear();
// // 增加trace对象 父子线程传递 这里跟mdc一样任务执行完需要清除。
// TraceContext.clear();
}
};
}
/**
* 封装任务,加入TraceId,有返回值
*
* @param callable
* @param threadContext
* @param <T>
* @return
*/
private <T> Callable<T> wrap(final Callable<T> callable, final Map<String, String> threadContext) {
Trace trace = TraceContext.getTrace();
return new Callable<T>() {
@Override
public T call() throws Exception {
if (threadContext == null) {
MDC.clear();
} else {
MDC.setContextMap(threadContext);
}
// 增加trace对象 父子线程传递 start
if (trace == null) {
TraceContext.clear();
} else {
TraceContext.setTrace(trace);
}
// 增加trace对象 父子线程传递 end
setTraceIdIfAbsent();
try {
return callable.call();
} finally {
MDC.clear();
// 增加trace对象 父子线程传递 这里跟mdc一样任务执行完需要清除。
TraceContext.clear();
}
private static class EasyAdminFuture<T> implements RunnableFuture<T> {
private RunnableFuture<T> future;
private Map<String, String> threadContext;
public EasyAdminFuture(RunnableFuture<T> future, Map<String, String> threadContext) {
this.future = future;
this.threadContext = threadContext;
}
@Override
public boolean cancel(boolean mayInterruptIfRunning) {
return this.future.cancel(mayInterruptIfRunning);
}
@Override
public boolean isCancelled() {
return this.future.isCancelled();
}
@Override
public boolean isDone() {
return this.future.isDone();
}
@Override
public T get() throws InterruptedException, ExecutionException {
return this.future.get();
}
@Override
public T get(long timeout, TimeUnit unit) throws InterruptedException, ExecutionException, TimeoutException {
return this.future.get(timeout, unit);
}
@Override
public void run() {
if (threadContext == null) {
MDC.clear();
} else {
MDC.setContextMap(threadContext);
}
};
setTraceIdIfAbsent();
try {
TraceContext.addSpan("subThread.submitRunnableFuture", SpanType.Thread);
future.run();
} finally {
TraceContext.stopSpan(1);
MDC.clear();
}
}
}
/**
* 如果traceId不存在,则设置一个随机的traceId
* 这种场景主要用于后台定时任务类,没有前端生成traceID的情况。
*/
private void setTraceIdIfAbsent() {
private static void setTraceIdIfAbsent() {
if (MDC.get(EasyAdminConstants.TRACE_ID) == null) {
MDC.put(EasyAdminConstants.TRACE_ID, IdUtil.simpleUUID());
}
......
......@@ -107,7 +107,7 @@ public class EasyAdminThreadPoolExecutor extends ThreadPoolExecutor {
}
}
if (t != null) {
log.error("", t);
log.error("线程池中的任务执行异常!!!", t);
}
log.debug("afterExecute-任务:{},异常:{}", r, t);
}
......
......@@ -55,7 +55,7 @@ public class LakerDataSourceTransactionManager extends DataSourceTransactionMana
long cost = System.currentTimeMillis() - transaction1.begin;
dateThreadLocal.remove();
if (cost > costTime) {
log.info("事务耗时监控!transaction:{},time:{}ms", transaction1.name, cost);
log.debug("事务耗时监控!transaction:{},time:{}ms", transaction1.name, cost);
}
}
super.doCleanupAfterCompletion(transaction);
......
......@@ -72,6 +72,16 @@ public class ExtLeaveController extends BaseFlowController {
});
pool.execute(() -> {
TraceCodeBlock.trace("6666666666666666",value -> {
try {
TimeUnit.MILLISECONDS.sleep(400);
} catch (InterruptedException e) {
e.printStackTrace();
}
});
});
pool.submit(() -> {
TraceCodeBlock.trace("1231233",value -> {
try {
......