Java Agent字节码增强技术实现链路追踪

  • Post author:
  • Post category:java


说明:使用bytebuddy框架来实现 RestTemplate链路追踪,并且将日志id追加到头部,借鉴 skywalking 中增强技术;直接上代码。

maven依赖


<properties>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        <maven.compiler.source>1.8</maven.compiler.source>
        <maven.compiler.target>1.8</maven.compiler.target>
        <byte.buddy.version>1.9.6</byte.buddy.version>
        <lombok.version>1.18.22</lombok.version>
        <log4.version>1.2.17</log4.version>
        <log4.api.version>1.7.21</log4.api.version>
        <spring.web.version>5.2.8.RELEASE</spring.web.version>
        <dubbo.version>2.7.0</dubbo.version>
        <javax.version>4.0.1</javax.version>
    </properties>

<dependency>
            <groupId>net.bytebuddy</groupId>
            <artifactId>byte-buddy</artifactId>
            <version>${byte.buddy.version}</version>
        </dependency>

        <dependency>
            <groupId>net.bytebuddy</groupId>
            <artifactId>byte-buddy-agent</artifactId>
            <version>${byte.buddy.version}</version>
        </dependency>

        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-web</artifactId>
            <version>${spring.web.version}</version>
            <scope>provided</scope>
        </dependency>

<dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-web</artifactId>
            <version>${spring.web.version}</version>
            <scope>provided</scope>
        </dependency>

        <dependency>
            <groupId>org.apache.dubbo</groupId>
            <artifactId>dubbo</artifactId>
            <version>${dubbo.version}</version>
            <scope>provided</scope>
        </dependency>
        
<dependency>
            <groupId>javax.servlet</groupId>
            <artifactId>javax.servlet-api</artifactId>
            <version>${javax.version}</version>
            <scope>provided</scope>
        </dependency>



1. 入口类

public class TraceAgent
{

    public static void premain(String args, Instrumentation instrumentation) {
    	//将插件从文件中读取出来
        PluginFinder pluginFinder = new PluginFinder(new PluginBootstrap().loadPlugins());
        //创建一个代理增强对象
        new AgentBuilder.Default()
        //通过自定义实现的类去拦截指定的对象
            .type(pluginFinder.buildMatch())  //拦截指定的类
            .transform(new Transformer(pluginFinder))
            .installOn(instrumentation);
    }

    public static class Transformer implements AgentBuilder.Transformer {
       //插件持有器
        private final PluginFinder pluginFinder;

        public Transformer(PluginFinder pluginFinder) {
            this.pluginFinder = pluginFinder;
        }

        @Override
        public DynamicType.Builder<?> transform(DynamicType.Builder<?> builder, TypeDescription typeDescription, ClassLoader classLoader,
                                                JavaModule javaModule) {
                                                //获取到插件,构建一个动态插件器
            List<ClassEnhancePluginDefine> classEnhancePluginDefines = pluginFinder.find(typeDescription);
            if (classEnhancePluginDefines.size() > 0) {
            //判断当前插件是否符合当前的拦截对象
                DynamicType.Builder<?> newBuilder = builder;
                //调用插件的define方法去获取到动态类型构造器,就是去返回需要匹配方法的增强方法
                for (ClassEnhancePluginDefine define : classEnhancePluginDefines) {
                    DynamicType.Builder<?> possibleNewBuilder = define.define(builder, classLoader);
                    if (possibleNewBuilder != null) {
                        newBuilder = possibleNewBuilder;
                    }
                }
                return newBuilder;
            }
            return builder;
        }
    }

}



2. 插件读取器

public class PluginBootstrap {

    /** PLUGINS */
    private static final String PLUGINS = "agent-plugin.def";

  	//主要是将文件中的插件读取出来,然后通过名称构造出来
    public List<ClassEnhancePluginDefine> loadPlugins() {
        ClassPathResource classPathResource = new ClassPathResource(PLUGINS);
        List<ClassEnhancePluginDefine> enhancePluginDefines = new ArrayList<>();
        try {
            if (!classPathResource.exists()) {
                return enhancePluginDefines;
            }
            
            InputStreamReader streamReader = new InputStreamReader(classPathResource.getInputStream());
            BufferedReader reader = new BufferedReader(streamReader);
            String tempString;
            while ((tempString = reader.readLine()) != null) {
                if (tempString.trim().length() == 0 || tempString.startsWith("#")) {
                    continue;
                }
                if (StringUtils.isEmpty(tempString)) {
                    continue;
                }

                String[] pluginDefine = tempString.split("=");
                if (pluginDefine.length != 2) {
                    continue;
                }
                log.debug("读取到插件类:{}", pluginDefine[1]);
                ClassEnhancePluginDefine classEnhancePluginDefine = (ClassEnhancePluginDefine) Class.forName(pluginDefine[1],
                                                                                                             true,
                                                                                                             this.getClass().getClassLoader())
                    .newInstance();
                enhancePluginDefines.add(classEnhancePluginDefine);
            }
        } catch (Exception e) {
            log.error("读取插件配置异常:", e);
        }
        return enhancePluginDefines;
    }
}



3. agent-plugin.def文件定义

spring-resttemplate=com.xxx.agent.interceptor.resttemplate.sync.RestTemplateInstrumentation
dubbo=com.xxx.agent.interceptor.doubbo.DubboInstrumentation
httpServlet=com.xxx.agent.interceptor.httpservlet.HttpServletInstrumentation



4. 插件持有器

public class PluginFinder {
    private final Map<String, LinkedList<ClassEnhancePluginDefine>> nameMatchDefine = new HashMap<>();


    //将读取出来的插件传入到 PluginFinder  持有器中
    public PluginFinder(List<ClassEnhancePluginDefine> classEnhancePluginDefines) {
        //遍历插件的名称,并且添加到名字匹配器当中
        classEnhancePluginDefines.forEach(classEnhancePluginDefine -> {
            //调用插件的实现方法,将需要增强的对象设置到map当中,value就是多个插件List
            String enhanceClass = classEnhancePluginDefine.enhanceClass();
            LinkedList<ClassEnhancePluginDefine> enhancePluginDefines = nameMatchDefine.computeIfAbsent(enhanceClass,
                                                                                                        k -> new LinkedList<>());
            enhancePluginDefines.add(classEnhancePluginDefine);
        });
    }
	//通过传入的 typeDescription 对象来判断是否是指定要增强的类,并且返回插件
    public List<ClassEnhancePluginDefine> find(TypeDescription typeDescription) {
        List<ClassEnhancePluginDefine> matchedPlugins = new LinkedList<ClassEnhancePluginDefine>();
        String typeName = typeDescription.getTypeName();
        if (nameMatchDefine.containsKey(typeName)) {
            matchedPlugins.addAll(nameMatchDefine.get(typeName));
        }
        return matchedPlugins;
    }

    //构建一个匹配器
    public ElementMatcher<? super TypeDescription> buildMatch() {
        ElementMatcher.Junction elementMatcher = new AbstractJunction<NamedElement>() {
            @Override
            //判断class名称是否是自己需要增强,在初始化的时候就把插件需要增强的类设置进去了
            public boolean matches(NamedElement namedElement) {
                return nameMatchDefine.containsKey(namedElement.getActualName());
            }
        };
        //判断需要创建的对象是不是一个接口
        elementMatcher = elementMatcher.and(not(isInterface()));
        for (String matchClass : nameMatchDefine.keySet()) {
            elementMatcher = elementMatcher.or(nameStartsWithIgnoreCase(matchClass));
        }
        //然后返回属性匹配器
        return new ProtectiveShieldMatcher<>(elementMatcher);
    }

}
public class ProtectiveShieldMatcher<T> extends ElementMatcher.Junction.AbstractBase<T> {

    /** Element matcher */
    private final ElementMatcher<? super T> elementMatcher;

    /**
     * Protective shield matcher
     *
     * @param elementMatcher element matcher
     * @since 1.0.0
     */
    public ProtectiveShieldMatcher(ElementMatcher<? super T> elementMatcher) {
        this.elementMatcher = elementMatcher;
    }

    /**
     * Matches
     *
     * @param target target
     * @return the boolean
     * @since 1.0.0
     */
    @Override
    public boolean matches(T target) {
        try {
            return this.elementMatcher.matches(target);
        } catch (Throwable t) {
            log.warn("匹配增强类失败:{}", t.getMessage());
            return false;
        }
    }
}
public abstract class AbstractJunction<S> implements ElementMatcher.Junction<S> {

    /**
     * And
     *
     * @param <U>            parameter
     * @param elementMatcher element matcher
     * @return the junction
     * @since 1.0.0
     */
    @Override
    public <U extends S> Junction<U> and(ElementMatcher<? super U> elementMatcher) {
        return new Conjunction<>(this, elementMatcher);
    }

    /**
     * Or
     *
     * @param <U>            parameter
     * @param elementMatcher element matcher
     * @return the junction
     * @since 1.0.0
     */
    @Override
    public <U extends S> Junction<U> or(ElementMatcher<? super U> elementMatcher) {
        return new Disjunction<>(this, elementMatcher);
    }
}



5. 插件定义的顶级接口类

public interface ClassEnhancePluginDefine {

    /**
     * 需要增强的类
     *
     * @return the string
     * @since 1.0.0
     */
    String enhanceClass();

    /**
     * 获取到定义方法
     *
     * @return the dynamic type . builder
     * @since 1.0.0
     */
    DynamicType.Builder<?> define(DynamicType.Builder<?> newBuilder,
                                  ClassLoader classLoader);

    /**
     * 获取到需要增强的具体方法
     *
     * @return the list
     * @since 1.0.0
     */
    InstanceMethodsInterceptPoint[] enhanceInstance();

}



6. 抽象插件类

public abstract class AbstractClassEnhancePluginDefine implements ClassEnhancePluginDefine {

    @Override
    public DynamicType.Builder<?> define(DynamicType.Builder<?> newBuilder, ClassLoader classLoader) {
        //获取到需要拦截的方法
        InstanceMethodsInterceptPoint[] instanceMethodsInterceptPoints = this.enhanceInstance();
        if (instanceMethodsInterceptPoints.length <= 0) {
            return newBuilder;
        }
        //遍历需要拦截点位
        for (InstanceMethodsInterceptPoint instanceMethodsInterceptPoint : instanceMethodsInterceptPoints) {
            //需要使用的拦截器
            Class<?> interceptor = instanceMethodsInterceptPoint.getMethodsInterceptor();
            //获取到需要拦截的方法匹配器
            ElementMatcher.Junction<MethodDescription> junction
                = not(isStatic()).and(instanceMethodsInterceptPoint.getMethodsMatcher());
            //将需要拦截的方法以及执行的拦截器挂载到builder上
            newBuilder = newBuilder
                .method(junction)
                .intercept(MethodDelegation
                               .withDefaultConfiguration()
                               .to(new InstMethodsInter(interceptor)));
        }
        return newBuilder;
    }
}



7. 增强方法的顶级接口

public interface InstanceMethodsInterceptPoint {

    /**
     * 方法匹配器
     *
     * @return the methods matcher
     * @since 1.0.0
     */
    ElementMatcher<MethodDescription> getMethodsMatcher();

    /**
     * 方法拦截器
     *
     * @return the methods interceptor
     * @since 1.0.0
     */
    Class<?> getMethodsInterceptor();

    /**
     * 是否覆盖参数,暂未实现
     *
     * @return the boolean
     * @since 1.0.0
     */
    boolean isOverrideArgs();
}



8. 环绕方法的拦截器

public interface InstanceMethodsAroundInterceptor {

    /**
     * Before method
     *
     * @param objInst        obj inst
     * @param method         method
     * @param allArguments   all arguments
     * @param argumentsTypes arguments types
     * @throws Throwable throwable
     * @since 1.0.0
     */
    void beforeMethod(Object objInst, Method method, Object[] allArguments, Class<?>[] argumentsTypes) throws Throwable;

    /**
     * After method
     *
     * @param objInst        obj inst
     * @param method         method
     * @param allArguments   all arguments
     * @param argumentsTypes arguments types
     * @param result         result
     * @return the object
     * @throws Throwable throwable
     * @since 1.0.0
     */
    Object afterMethod(Object objInst, Method method, Object[] allArguments, Class<?>[] argumentsTypes, Object result) throws Throwable;

    /**
     * Handle method exception
     *
     * @param objInst        obj inst
     * @param method         method
     * @param allArguments   all arguments
     * @param argumentsTypes arguments types
     * @param t              t
     * @since 1.0.0
     */
    void handleMethodException(Object objInst, Method method, Object[] allArguments,
                               Class<?>[] argumentsTypes, Throwable t);
}



9. 方法执行的包装方法

public class InstMethodsInter {

    /** Interceptor */
    private InstanceMethodsAroundInterceptor interceptor;

    /**
     * Inst methods inter
     *
     * @param interceptorName interceptor name
     * @since 1.0.0
     */
    public InstMethodsInter(@NonNull Class<?> interceptorName) {
        try {
            this.interceptor = (InstanceMethodsAroundInterceptor) interceptorName.newInstance();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    /**
     * Intercept
     *
     * @param obj          obj
     * @param allArguments all arguments
     * @param method       method
     * @param callable     callable
     * @return the object
     * @since 1.0.0
     */
    @RuntimeType
    public Object intercept(@This Object obj,
                            @AllArguments Object[] allArguments,
                            @Origin Method method,
                            @SuperCall Callable<?> callable) {
        Object result = null;
        try {
            interceptor.beforeMethod(obj, method, allArguments, method.getParameterTypes());
        } catch (Throwable throwable) {
            log.error("前置增强方法执行异常:", throwable);
        }
        try {
        	//真正方法的执行
            result = callable.call();
        } catch (Throwable t) {
            interceptor.handleMethodException(obj, method, allArguments, method.getParameterTypes(), t);
        } finally {
            try {
                result = interceptor.afterMethod(obj, method, allArguments, method.getParameterTypes(), result);
            } catch (Throwable t) {
                log.error("后置增强方法执行异常:", t);
            }
        }
        return result;
    }

}



10. 实现的插件类



RestTemplate 增强类

public class RestTemplateInstrumentation extends AbstractClassEnhancePluginDefine {

    /** 需要增强的类*/
    private static final String ENHANCE_CLASS = "org.springframework.web.client.RestTemplate";

    /** 需要增强的方法*/
    private static final String DO_EXECUTE_METHOD_NAME = "doExecute";

    /** 对应增强方法执行的类*/
    private static final Class<?> DO_EXECUTE_INTERCEPTOR = RestExecuteInterceptor.class;

    /** 需要增强的方法*/
    private static final String HANDLE_REQUEST_METHOD_NAME = "handleResponse";

    /** 对应增强方法执行的类*/
    private static final Class<?> HAND_REQUEST_INTERCEPTOR = RestResponseInterceptor.class;

    /** 需要增强的方法 */
    private static final String CREATE_REQUEST_METHOD_NAME = "createRequest";

    /** 对应增强方法执行的类*/
    private static final Class<?> CREATE_REQUEST_INTERCEPTOR = RestRequestInterceptor.class;

    /**
     * Enhance class
     *
     * @return the string
     * @since 1.0.0
     */
    @Override
    public String enhanceClass() {
        return ENHANCE_CLASS;
    }

    /**
     * Enhance instance
     *
     * @return the instance methods intercept point [ ]
     * @since 1.0.0
     */
    @Override
    public InstanceMethodsInterceptPoint[] enhanceInstance() {
        return new InstanceMethodsInterceptPoint[] {
            new InstanceMethodsInterceptPoint() {
                @Override
                public ElementMatcher<MethodDescription> getMethodsMatcher() {
                    return named(CREATE_REQUEST_METHOD_NAME);
                }

                @Override
                public Class<?> getMethodsInterceptor() {
                    return CREATE_REQUEST_INTERCEPTOR;
                }

                @Override
                public boolean isOverrideArgs() {
                    return false;
                }
            },
            new InstanceMethodsInterceptPoint() {
                @Override
                public ElementMatcher<MethodDescription> getMethodsMatcher() {
                    return named(DO_EXECUTE_METHOD_NAME);
                }

                @Override
                public Class<?> getMethodsInterceptor() {
                    return DO_EXECUTE_INTERCEPTOR;
                }

                @Override
                public boolean isOverrideArgs() {
                    return false;
                }
            },
            new InstanceMethodsInterceptPoint() {
                @Override
                public ElementMatcher<MethodDescription> getMethodsMatcher() {
                    return named(HANDLE_REQUEST_METHOD_NAME);
                }

                @Override
                public Class<?> getMethodsInterceptor() {
                    return HAND_REQUEST_INTERCEPTOR;
                }

                @Override
                public boolean isOverrideArgs() {
                    return false;
                }
            }
        };
    }
}


1. excute() 方法
public class RestExecuteInterceptor implements InstanceMethodsAroundInterceptor {

    @Override
    public void beforeMethod(Object objInst, Method method, Object[] allArguments, Class<?>[] argumentsTypes) throws Throwable {

    }

    @Override
    public Object afterMethod(Object objInst, Method method, Object[] allArguments, Class<?>[] argumentsTypes, Object result) throws Throwable {
        return result;
    }

    @Override
    public void handleMethodException(Object objInst, Method method, Object[] allArguments, Class<?>[] argumentsTypes, Throwable t) {
        //调用异常之后打印调用链路
        RuntimeContextManager.printTraceLog();
    }
}


2. createRequest() 方法
public class RestRequestInterceptor implements InstanceMethodsAroundInterceptor {

    @Override
    public void beforeMethod(Object objInst, Method method, Object[] allArguments, Class<?>[] argumentsTypes) throws Throwable {

    }

    @Override
    public Object afterMethod(Object objInst, Method method, Object[] allArguments, Class<?>[] argumentsTypes, Object result) throws Throwable {
        ClientHttpRequest clientHttpRequest = (ClientHttpRequest) result;
        if (clientHttpRequest instanceof AbstractClientHttpRequest) {
            AbstractClientHttpRequest httpRequest = (AbstractClientHttpRequest) clientHttpRequest;
            //将traceId追加到header头当中
            RuntimeContextManager.CarrierItem item = RuntimeContextManager.get();
            while (item.hasNext()) {
                item = item.next();
                httpRequest.getHeaders().add(ConstName.HEAD_KEY, item.getHeadValue());
            }
        }
        return result;
    }

    @Override
    public void handleMethodException(Object objInst, Method method, Object[] allArguments, Class<?>[] argumentsTypes, Throwable t) {
        RuntimeContextManager.printTraceLog();
    }
}



3. handleResponse() 方法
public class RestResponseInterceptor implements InstanceMethodsAroundInterceptor {

    /**
     * Before method
     *
     * @param objInst        obj inst
     * @param method         method
     * @param allArguments   all arguments
     * @param argumentsTypes arguments types
     * @throws Throwable throwable
     * @since 1.0.0
     */
    @Override
    public void beforeMethod(Object objInst, Method method, Object[] allArguments, Class<?>[] argumentsTypes) throws Throwable {

    }

    /**
     * After method
     *
     * @param objInst        obj inst
     * @param method         method
     * @param allArguments   all arguments
     * @param argumentsTypes arguments types
     * @param result         result
     * @return the object
     * @throws Throwable throwable
     * @since 1.0.0
     */
    @Override
    public Object afterMethod(Object objInst, Method method, Object[] allArguments, Class<?>[] argumentsTypes, Object result) throws Throwable {
        ClientHttpResponse clientHttpResponse = (ClientHttpResponse) allArguments[1];
        List<String> traceList = clientHttpResponse.getHeaders().get(ConstName.HEAD_KEY);
        if (!CollectionUtils.isEmpty(traceList)) {
            RuntimeContextManager.remove();
            //将trace放到 manager当中存储
            traceList.forEach(trace -> {
                RuntimeContextManager.add(RuntimeContextManager.CarrierItem.item(trace, trace));
            });
        }
        return result;
    }

    /**
     * Handle method exception
     *
     * @param objInst        obj inst
     * @param method         method
     * @param allArguments   all arguments
     * @param argumentsTypes arguments types
     * @param t              t
     * @since 1.0.0
     */
    @Override
    public void handleMethodException(Object objInst, Method method, Object[] allArguments, Class<?>[] argumentsTypes, Throwable t) {
        RuntimeContextManager.printTraceLog();
    }
}



servlet 增强类

public class HttpServletInstrumentation extends AbstractClassEnhancePluginDefine {

    private static final String ENHANCE_CLASS = "org.springframework.web.servlet.DispatcherServlet";

    private static final String DO_FILTER_METHOD = "service";

    private static final Class<HttpServletInterceptor> DO_FILTER_INTERCEPTOR = HttpServletInterceptor.class;


    /**
     * Enhance class
     *
     * @return the string
     * @since 1.0.0
     */
    @Override
    public String enhanceClass() {
        return ENHANCE_CLASS;
    }

    /**
     * Enhance instance
     *
     * @return the instance methods intercept point [ ]
     * @since 1.0.0
     */
    @Override
    public InstanceMethodsInterceptPoint[] enhanceInstance() {
        return new InstanceMethodsInterceptPoint[] {
            new InstanceMethodsInterceptPoint() {
                @Override
                public ElementMatcher<MethodDescription> getMethodsMatcher() {
                    //拦截对应的方法,并且是public方法
                    return named(DO_FILTER_METHOD).and(isPublic());
                }

                @Override
                public Class<?> getMethodsInterceptor() {
                    return DO_FILTER_INTERCEPTOR;
                }

                @Override
                public boolean isOverrideArgs() {
                    return false;
                }
            }
        };
    }
}


1. service() 方法
public class HttpServletInterceptor implements InstanceMethodsAroundInterceptor {

    /**
     * Before method
     *
     * @param objInst        obj inst
     * @param method         method
     * @param allArguments   all arguments
     * @param argumentsTypes arguments types
     * @throws Throwable throwable
     * @since 1.0.0
     */
    @Override
    public void beforeMethod(Object objInst, Method method, Object[] allArguments, Class<?>[] argumentsTypes) throws Throwable {
        HttpServletRequest httpRequest = (HttpServletRequest) allArguments[0];
        Enumeration<String> headers = httpRequest.getHeaders(ConstName.HEAD_KEY);
        //将请求头的数据读取出来后清除掉头部数据
        if (headers.hasMoreElements()) {
            String nextElement = headers.nextElement();
            RuntimeContextManager.CarrierItem carrierItem
                = RuntimeContextManager.CarrierItem.item(nextElement, nextElement);
            RuntimeContextManager.add(carrierItem);
        }
        RuntimeContextManager.CarrierItem next = RuntimeContextManager.CarrierItem.item(System.getProperty(ConstName.CONFIG_APP_NAME),
                                                                                        System.getProperty(ConstName.CONFIG_APP_NAME));
        RuntimeContextManager.add(next);
        httpRequest.removeAttribute(ConstName.HEAD_KEY);
    }

    /**
     * After method
     *
     * @param objInst        obj inst
     * @param method         method
     * @param allArguments   all arguments
     * @param argumentsTypes arguments types
     * @param result         result
     * @return the object
     * @throws Throwable throwable
     * @since 1.0.0
     */
    @Override
    public Object afterMethod(Object objInst, Method method, Object[] allArguments, Class<?>[] argumentsTypes, Object result) throws Throwable {
        HttpServletResponse httpServletResponse = (HttpServletResponse) allArguments[1];
        RuntimeContextManager.addResponseHeaders(httpServletResponse);
        RuntimeContextManager.printTraceLog();
        RuntimeContextManager.remove();
        return result;
    }

    /**
     * Handle method exception
     *
     * @param objInst        obj inst
     * @param method         method
     * @param allArguments   all arguments
     * @param argumentsTypes arguments types
     * @param t              t
     * @since 1.0.0
     */
    @Override
    public void handleMethodException(Object objInst, Method method, Object[] allArguments, Class<?>[] argumentsTypes, Throwable t) {
        RuntimeContextManager.printTraceLog();
        RuntimeContextManager.remove();
    }

}



dubbo 增强类

public class DubboInstrumentation extends AbstractClassEnhancePluginDefine {

    private static final String ENHANCE_CLASS = "org.apache.dubbo.monitor.support.MonitorFilter";

    private static final Class<DubboInterceptor> INTERCEPT_CLASS = DubboInterceptor.class;

    /** DO_EXECUTE_METHOD_NAME */
    private static final String INVOKE_METHOD_NAME = "invoke";

    @Override
    public String enhanceClass() {
        return ENHANCE_CLASS;
    }

    @Override
    public InstanceMethodsInterceptPoint[] enhanceInstance() {
        return new InstanceMethodsInterceptPoint[] {
            new InstanceMethodsInterceptPoint() {
                @Override
                public ElementMatcher<MethodDescription> getMethodsMatcher() {
                    return named(INVOKE_METHOD_NAME);
                }

                @Override
                public Class<DubboInterceptor> getMethodsInterceptor() {
                    return INTERCEPT_CLASS;
                }

                @Override
                public boolean isOverrideArgs() {
                    return false;
                }
            }
        };
    }
}


1. invoke() 方法
public class DubboInterceptor implements InstanceMethodsAroundInterceptor {

    /**
     * Before method
     *
     * @param objInst        obj inst
     * @param method         method
     * @param allArguments   all arguments
     * @param argumentsTypes arguments types
     * @throws Throwable throwable
     * @since y.y.y
     */
    @Override
    public void beforeMethod(Object objInst, Method method, Object[] allArguments, Class<?>[] argumentsTypes) throws Throwable {
        Invoker invoker = (Invoker) allArguments[0];
        Invocation invocation = (Invocation) allArguments[1];
        RpcContext rpcContext = RpcContext.getContext();
        boolean isConsumer = rpcContext.isConsumerSide();
        URL requestURL = invoker.getUrl();
        if (isConsumer) {
            //添加一次当前服务的名称
            RuntimeContextManager.add(RuntimeContextManager.CarrierItem.item(System.getProperty(ConstName.CONFIG_APP_NAME),
                                                                             System.getProperty(ConstName.CONFIG_APP_NAME)));
            //判断如果是消费者,将数据写入请求头
            String traceStr = RuntimeContextManager.getTraceStr();
            rpcContext.getAttachments().put(ConstName.HEAD_KEY, traceStr);
        } else {
            //如果是提供者
            String traceStr = rpcContext.getAttachments().get(ConstName.HEAD_KEY);
            RuntimeContextManager.addTraceForStr(traceStr);
        }
    }

    /**
     * After method
     *
     * @param objInst        obj inst
     * @param method         method
     * @param allArguments   all arguments
     * @param argumentsTypes arguments types
     * @param result         result
     * @return the object
     * @throws Throwable throwable
     * @since y.y.y
     */
    @Override
    public Object afterMethod(Object objInst, Method method, Object[] allArguments, Class<?>[] argumentsTypes, Object result) throws Throwable {
        return null;
    }

    /**
     * Handle method exception
     *
     * @param objInst        obj inst
     * @param method         method
     * @param allArguments   all arguments
     * @param argumentsTypes arguments types
     * @param t              t
     * @since y.y.y
     */
    @Override
    public void handleMethodException(Object objInst, Method method, Object[] allArguments, Class<?>[] argumentsTypes, Throwable t) {

    }

    /**
     * Generate operation name
     *
     * @param requestURL request url
     * @param invocation invocation
     * @return the string
     * @since y.y.y
     */
    private String generateOperationName(URL requestURL, Invocation invocation) {
        StringBuilder operationName = new StringBuilder();
        String groupStr = requestURL.getParameter(Constants.GROUP_KEY);
        groupStr = StringUtils.isEmpty(groupStr) ? "" : groupStr + "/";
        operationName.append(groupStr);
        operationName.append(requestURL.getPath());
        operationName.append("." + invocation.getMethodName() + "(");
        for (Class<?> classes : invocation.getParameterTypes()) {
            operationName.append(classes.getSimpleName() + ",");
        }
        if (invocation.getParameterTypes().length > 0) {
            operationName.delete(operationName.length() - 1, operationName.length());
        }
        operationName.append(")");
        return operationName.toString();
    }

    /**
     * Generate request url
     *
     * @param url        url
     * @param invocation invocation
     * @return the string
     * @since y.y.y
     */
    private String generateRequestURL(URL url, Invocation invocation) {
        StringBuilder requestURL = new StringBuilder();
        requestURL.append(url.getProtocol() + "://");
        requestURL.append(url.getHost());
        requestURL.append(":" + url.getPort() + "/");
        requestURL.append(generateOperationName(url, invocation));
        return requestURL.toString();
    }
}



11. 上下文持有器

public class RuntimeContextManager {

    private final static ThreadLocal<CarrierItem> RUNTIME_CARRIER = new ThreadLocal<>();

    public static CarrierItem get() {
        CarrierItem carrierItem = RUNTIME_CARRIER.get();
        if (carrierItem == null) {
            carrierItem = new CarrierItem(Thread.currentThread().getName(), System.currentTimeMillis()+"", null);
            RUNTIME_CARRIER.set(carrierItem);
        }
        return carrierItem;
    }

    public static void remove() {
        RUNTIME_CARRIER.remove();
    }

    public static void add(CarrierItem next) {
        CarrierItem item = get();
        while (item.hasNext()) {
            item = item.next();
        }
        //如果尾部的服务名跟添加时的一样,就不需要再添加
        String headValue = item.getHeadValue();
        if (headValue.equalsIgnoreCase(next.headValue)) {
            return;
        }
        item.setNext(next);
    }

    public static void addRequestHeaders(ClientHttpRequest clientHttpRequest) {
        CarrierItem carrierItem = get();
        clientHttpRequest.getHeaders().remove(ConstName.HEAD_KEY);
        while (carrierItem.hasNext()) {
            carrierItem = carrierItem.next;
            clientHttpRequest.getHeaders().add(ConstName.HEAD_KEY, carrierItem.headValue);
        }
    }

    public static void addResponseHeaders(ServletResponse servletResponse) {
        CarrierItem carrierItem = get();
        if (servletResponse instanceof HttpServletResponse) {
            while (carrierItem.hasNext()) {
                carrierItem = carrierItem.next;
                ((HttpServletResponse) servletResponse).addHeader(ConstName.HEAD_KEY, carrierItem.headValue);
            }
        }
    }

    public static void printTraceLog() {
        String s = getTraceStr();
        if (s == null) {
            return;
        }
        log.info("服务调用路径:{}", s);
    }

    public static String getTraceStr() {
        CarrierItem carrierItem = get();
        List<String> items = new ArrayList<>();
        while (carrierItem.hasNext()) {
            carrierItem = carrierItem.next;
            items.add(carrierItem.headValue);
        }
        if (CollectionUtils.isEmpty(items)) {
            return null;
        }
        return items.stream().map(String::valueOf).collect(Collectors.joining(ConstName.DELIMITER));
    }

    public static void addTraceForStr(String traceStr) {
        if (StringUtils.isEmpty(traceStr)) {
            return;
        }
        String[] trace = StringUtils.split(traceStr, ConstName.DELIMITER);
        Arrays.stream(trace).forEach(str -> {
            add(CarrierItem.item(str, str));
        });
    }


    public static class CarrierItem implements Iterator<CarrierItem> {

        private String headKey;

        private String headValue;

        private CarrierItem next;

        public CarrierItem() {
        }

        public CarrierItem(String headKey, String headValue) {
            this(headKey, headValue, null);
        }

        public CarrierItem(String headKey, String headValue, CarrierItem next) {
            this.headKey = headKey;
            this.headValue = headValue;
            this.next = next;
        }

        public static CarrierItem item(String headKey, String headValue) {
            return new CarrierItem(headKey, headValue);
        }

        @Override
        public boolean hasNext() {
            return next != null;
        }

        @Override
        public CarrierItem next() {
            return next;
        }

        @Override
        public void remove() {

        }

        public String getHeadKey() {
            return headKey;
        }

        public void setHeadKey(String headKey) {
            this.headKey = headKey;
        }

        public String getHeadValue() {
            return headValue;
        }

        public void setHeadValue(String headValue) {
            this.headValue = headValue;
        }

        public CarrierItem getNext() {
            return next;
        }

        public void setNext(CarrierItem next) {
            this.next = next;
        }
    }
}

public class ConstName {

    /** CONFIG_APP_NAME */
    public static final String CONFIG_APP_NAME = "APP_NAME";

    /** HEAD_KEY */
    public static final String HEAD_KEY = "Trace";

    /** 分隔符 */
    public static final String DELIMITER = "--->";

}


由于公司封装的框架原因,导致restTemplate增强会有问题,所以一在拦截handResponse()会导致提前返回对象;但是大体框架没有问题,都是根据skywalking的源码进行修改,各位看官根据具体的业务可以进行实现;如果有什么错误的地方,还请各位大佬指教



版权声明:本文为weixin_43915643原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。