Spring Mybatis 慢 SQL 监控
问题背景
系统经常卡顿,找不到原因。有时列表查询时间过长,造成系统无法正常访问
实现方案
在 Mybatis
的插件内做拦截。添加守护线程池,执行数据库查询之前启动守护线程。数据库查询执行完,尝试中断守护线程。若守护线程在超时时间段内未被中断,则记录日志提示 SQL
慢查询。
// ...
import org.apache.ibatis.mapping.*;
import org.apache.ibatis.plugin.*;
import org.apache.ibatis..*;
import org.apache.ibatis.session.*;
import org.apache.logging.log4j.*;
import java.util.concurrent.*;
@Intercepts({
@Signature(method="query", type= Executor.class, args = {MappedStatement.class, Object.class, RowBounds.class, ResultHandler.class})
})
public class MyInterceptor implements Interceptor {
private static ThreadPoolExecutor daemonThreadPoolExecutor = new ThreadPoolExecutor(1, 10, 1, TimeUnit.MILLISECONDS, new ArrayBlockingQueue<>(1));
@Override
public Object intercept(Invocation invocation) throws Throwable {
if (invocation.getTarget() instanceof Executor) {
long slowSqlExecuteTime = 3000L;
TimeoutDaemonTask task = new TimeoutDaemontask(slowSqlExecuteTime, "traceId");
Future<Long> daemonFuture = null;
try {
daemonFuture = daemonThreadPoolExecutor.submit(timeoutDaemonTask);
} catch (RejectedExecutionException e) {
logger.error("数据库慢查询监控失败");
return invocation.proceed();
}
Object result = invocatoin.proceed();
if (!daemonFUture.isDone() && !daemonFuture.isCancelled()) {
daemonFuture.cancel(true);
} else {
logger.error("数据库执行时长:{}ms", timeoutDaemonTask.getExecuteTime());
}
}
}
private class TimeoutDaemonTask implements Callable<Long> {
private long start = SYstem.currentTimeMillis();
private long executeTime = -1;
private long slowSqlExecuteTime = 5000L;
private String traceId;
public TimeoutDaemonTask(long slowSqlExecuteTime, String traceId) {
this.slowSqlExecuteTime = slowSqlExecuteTime;
this.traceId = traceId;
}
public long getExecuteTime() {
return System.currentTimeMills() - start;
}
@Override
public Long call() throws Execption {
try {
ThreadContext.put("TRACE_ID", traceId);
Thread.sleep(slowSqlExecuteTime);
logger.error("数据库超时");
return executeTime;
} catch (Execption e) {
executeTime = System.currentTimeMills() - start;
return executeTime;
}
}
}
}
参考链接
最后更新于