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)


相关推荐

  • psutil的Process python获取进程信息「建议收藏」

    psutil的Process python获取进程信息「建议收藏」系统进程信息psutil.Process()1.创建指定进程号的对象s=psutil.Process(1701)2.进程PID:pids.pid3.进程名称:name()s.name()4.进程当前状态:status()s.status()5.进程是否还在运行:is_running()返回此进程是否正在运行。它还检查PID是否已被另一个进程重用…

  • 两万字博文教你python爬虫requests库【详解篇】[通俗易懂]

    两万字博文教你python爬虫requests库【详解篇】[通俗易懂] ????上一篇博文一篇万字博文带你入坑爬虫这条不归路(你还在犹豫什么&抓紧上车)【❤️熬夜整理&建议收藏❤️】被众多爬虫爱好者/想要学习爬虫的小伙伴们阅读之后,很多小伙伴私信我说——大佬搞爬虫都是用的socket套接字嘛????? ????(苦笑)“那肯定不是啊!python为我们封装了那么多伟大而又简单实用的爬虫库,”不过我想说的是,“学啥技术都是从底层抓起,万丈高楼平地起,它也是基于地基稳!所以在入坑文中简单地介绍使用了下底层爬虫库——socket!”???? ????而本文

  • c/c++面试题大汇总_北京易联达C语言面试咋样

    c/c++面试题大汇总_北京易联达C语言面试咋样c++的知识点

  • php测试工具_php单元测试

    php测试工具_php单元测试guzzle.png本文将介绍Guzzle,Guzzle在单元测试中的使用。来自Guzzle中文文档的解释:Guzzle是一个PHP的HTTP客户端,用来轻而易举地发送请求,并集成到我们的WEB服务上。接口简单:构建查询语句、POST请求、分流上传下载大文件、使用HTTPcookies、上传JSON数据等等。发送同步或异步的请求均使用相同的接口。使用PSR-7接口来请求、响应、分流,允许你使用其…

  • 梦断代码阅读笔记02

    梦断代码阅读笔记02

  • linux 挂载磁盘命令

    linux 挂载磁盘命令把一个磁盘/dev/sda挂载到某个目录下makdir /mnt/long //创建一个空的挂载节点mount -text4 /dev/sda /mnt/long

发表回复

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

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