排查项目中的循环调用

项目优化系列

循环调用排查【for循环数据库调用,dubbo调用】

在企业级开发中,由于项目会经过很多开发,开发的规范参差不齐,导致出现很多for循环调用数据库,for循环调用dubbo接口,导致明明能够只需要一次调用就能解决的问题,往往反而需要多次调用,从来带来了各种系统资源紧张。

解决思路一:人肉排查
缺点:效率低下,覆盖不全面容易遗漏。

解决思路二:通过 调用链路+traceId 持久化调用信息 依次排查出在同一时间内相同traceId多次调用发现问题
dubbo实现
使用filter扩展实现,在META-INF目录下配置过滤器

recursiveCallFilter=com.xxx.xxx.xxx.config.RecursiveCallFilter
@Activate(group = {"consumer"})
public class RecursiveCallFilter implements Filter {

    private static final Logger logger = LoggerFactory.getLogger(RecursiveCallFilter.class);

    @Override
    public Result invoke(Invoker invoker, Invocation invocation) throws RpcException {
        StackTraceElement[] stack = Thread.currentThread().getStackTrace();
        if (stack.length > 0) {
            StringBuffer sb = new StringBuffer();
            for (int i = 0; i < stack.length; i++) {
            	//使用项目包名前缀去除非业务调用
                if(stack[i].getClassName().startsWith("com.xxx.xxx.xxx")){
                    sb.append(stack[i].getClassName()+"*"+stack[i].getMethodName()+"@");
                }
            }
            logger.info("RecursiveCallFilter.invoke.trace_id:{},stack:{}", TraceIdUtil.getCurrentTraceId(),sb.toString());
        }
        //自行实现持久化方式
        return invoker.invoke(invocation);
    }
}

数据库实现

@Component
@Slf4j
@Intercepts({@Signature(type = StatementHandler.class, method = "prepare", args = {Connection.class, Integer.class})})
public class RecursiveCallInterceptor implements Interceptor {
    private static final Logger logger = LoggerFactory.getLogger(RecursiveCallInterceptor.class);

    @Override
    public Object intercept(Invocation invocation) throws Throwable {

        StackTraceElement[] stack = Thread.currentThread().getStackTrace();
        if (stack.length > 0) {
            StringBuffer sb = new StringBuffer();
            for (int i = 0; i < stack.length; i++) {
                if (stack[i].getClassName().startsWith("com.xx.xx.xx")) {
                    sb.append(stack[i].getClassName() + "*" + stack[i].getMethodName() + "@");
                }
            }
            logger.info("RecursiveCallInterceptor.invoke.trace_id:{},stack:{}", TraceIdUtil.getCurrentTraceId(),
                sb.toString());
        }
        return invocation.proceed();
    }

    @Override
    public Object plugin(Object target) {
        return Plugin.wrap(target, this);
    }

    @Override
    public void setProperties(Properties properties) {

    }
}

你可能感兴趣的:(问题优化,java,数据库)