Java Agent字节码增强技术实现链路追踪[通俗易懂]

Java Agent字节码增强技术实现链路追踪[通俗易懂]javaagent

大家好,又见面了,我是你们的朋友全栈君。如果您正在找激活码,请点击查看最新教程,关注关注公众号 “全栈程序员社区” 获取激活教程,可能之前旧版本教程已经失效.最新Idea2022.1教程亲测有效,一键激活。

Jetbrains全家桶1年46,售后保障稳定

说明:使用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>

Jetbrains全家桶1年46,售后保障稳定

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的源码进行修改,各位看官根据具体的业务可以进行实现;如果有什么错误的地方,还请各位大佬指教

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。

发布者:全栈程序员-用户IM,转载请注明出处:https://javaforall.cn/213943.html原文链接:https://javaforall.cn

【正版授权,激活自己账号】: Jetbrains全家桶Ide使用,1年售后保障,每天仅需1毛

【官方授权 正版激活】: 官方授权 正版激活 支持Jetbrains家族下所有IDE 使用个人JB账号...

(0)


相关推荐

  • 浅议大数据时代下消防工作、生活和思维的变革「建议收藏」

    浅议大数据时代下消防工作、生活和思维的变革「建议收藏」最近在微信圈流行的段子:一个客户拨打了披萨店的电话,还没说要什么披萨,仅仅告知了他的会员卡号,店员从系统中就知道了他所有个人信息。包括地址、电话、身高体重、医疗记录、过敏史、家里几口人、家里人的健康状态、房贷、个人信用,最后还包括他现在骑着摩托车拨打电话的GPS定位。并针对他目前这些信息定向推销店内减肥的、低糖的、够他家庭6人份的披萨,还指出他最好用现金…

  • 决策树模型的用途_决策树模型怎么建立

    决策树模型的用途_决策树模型怎么建立概念定义在特征空间与类空间上的条件概率分布,即给定特征条件下类的条件概率分布;也可以认为是if-then规则的集合优点模型具有可读性,分类速度快。模型首先,介绍一下决策树模型:由结点和有向边组成,结点又可分为内部结点和叶结点。内部结点表示一个特征或属性,叶结点表示一个类。决策树与条件概率分布决策树所表示的条件概率分布由各个单元给定条件下的类的条件概率分布组成。若X表…

    2022年10月21日
  • 十以内的加法游戏_10以内加减法游戏

    十以内的加法游戏_10以内加减法游戏现在市面上有非常多的益智类小游戏,其中就有很多是关于速算问题的,我们可以通过scratch编程来实现一个更加具有画面感的速算类小游戏,来帮助有计算问题的小朋友通过游戏来进行更好的心算速算练习。现在的这一款10以内的加法速算游戏,比较适合刚接触计算年龄比较小的孩子。1:首先我们需要添加几个有趣的角色。2,添加背景并设置好需要的变量。3,利用“询问”指令来实现出题的效果,并通过判断”回答”是…

  • BS架构与CS架构的区别(详细讲解)

    BS架构与CS架构的区别(详细讲解)1.CS=Client-Server=客戶端-服務器。例子:QQ,迅雷,快播,暴風影音,各種網絡遊戲等等。只要有和服務器通訊的都算。2.BS=Browser-Server=浏览器-服務器。例子:所有的网站都是bs。C/S系统结构   B/S系统结构 1、客户端要求C/S客户端的计算机电脑配置要求较高。B/S客户端的计算…

  • vs2012ultimate密钥_visual studio 2012产品密钥

    vs2012ultimate密钥_visual studio 2012产品密钥VisualStudioExpress2012forWindowsDesktopKEY:MMVJ9-FKY74-W449Y-RB79G-8GJGJMicrosoftVisualStudioExpress2012forWebKEY:VX3VY-8GCVT-KJQCY-RQ99X-MCF2RVisualStudioExpress

    2022年10月14日
  • Thread的join方法[通俗易懂]

    Thread的join方法[通俗易懂]Thread中的join方法主要的作用是让jion的线程加入当前线程,等加入的线程执行完之后才会执行当前线程。接下来看个例子:publicclassTestJoin{publicstaticvoidmain(String[]args)throwsInterruptedException{Threadt1=newThread(()->{try{Thr

发表回复

您的电子邮箱地址不会被公开。

关注全栈程序员社区公众号