文章目录
- 前言
- 调用链示图
- dubbo服务之间的的调链
- cloud 服务之间的调用链
- 网关
- servlet容器: 标签续传
- 1.定义插件
- 2.实现灰度增强拦截
- 线程池: 标签续传
- 1.拦截Runnable或Callable,接口增强实现标签续传;
- Callable 插件定义
- Runnable 插件定义
- 拦载Callabl或Runnable构造(可共用)
- 拦载run或call 方法(可共用)
- 2.拦截ThreadPoolExecutor, 但是当业务使用Callable或Runnable 时,使用的是lambda表达式时,
- ThreadPool插件定义
- ThreadPool公共拦截类
- execute方法拦截
- submit方法拦截
- spring-cloud 服务增强
- 1. 灰度标签续传
- Feign htttp 拦载插件定义
- Feign灰度标签拦截器
- RestTemplate http 拦截插件定义
- RestTemplate http 拦截灰度标签续传
- 2.ribbon灰度路由
- Rule 插件定义
- Rule 灰度路由规则拦截改写
- dubbo服务增强
- 1. 灰度标签续传
- 服务消费方ContextFilter插件定义
- 服务提供方ContextFilter插件定义
- 服务消费方ContextFilter拦截
- 服务提供方ContextFilter拦截
- 2. 灰度路由规则拦截改写
- 路由插件定义
- 灰度路由规则拦截改写
- nacos client增强
- 插件定义
- 实例uuid拦截上报
- eureka client增强
- 插件定义
- 实例uuid拦截上报
前言
上一篇介绍,agent基础框架的实现,本篇主要介绍灰度标签在各种组件、协议之间续传,以及路由规则改写;从用户客户端发送请求,到用户收到后端响应信息,整个请求链路会经过各种组件,
调用链示图
dubbo服务之间的的调链
cloud 服务之间的调用链
上面展示的组件调用链为: 用户->网关->servlet容器服务->线程池->dubbo服务或cloud服务;这仅展示某一种调用路径,实际环境可能更复杂,有经过cloud或消息队列等等,不再一一列举。
网关
网关交互相对杂复一些,单独开篇
servlet容器: 标签续传
通常web容器服务,都会实现servlet,找到适合的组件接口,
- 从http请求头获取灰度标签,并设置到threadLocal,
- 请求处理完后,清除该信息;
- 分析发现比较合适对HandlerAdapter(不是唯一)进行拦截:
1.定义插件
public class HandlerAdapterDefine extends ClassEnhancePluginDefine {
private static final String CLASS_INTERCEPTOR = "com.dbcat.gray.agent.mvc.HandlerAdapterInterceptor";
@Override
protected ClassMatch enhanceClass() {
return HierarchyMatch.byHierarchyMatch("org.springframework.web.servlet.HandlerAdapter");
}
@Override
public ConstructorInterceptPoint[] getConstructorsInterceptPoints() {
return new ConstructorInterceptPoint[0];
}
@Override
public InstanceMethodsInterceptPoint[] getInstanceMethodsInterceptPoints() {
return new InstanceMethodsInterceptPoint[] {
new InstanceMethodsInterceptPoint() {
@Override
public ElementMatcher<MethodDescription> getMethodsMatcher() {
return named("handle").and(takesArguments(3));
}
@Override
public String getMethodsInterceptor() {
return CLASS_INTERCEPTOR;
}
@Override
public boolean isOverrideArgs() {
return false;
}
}
};
}
@Override
public StaticMethodsInterceptPoint[] getStaticMethodsInterceptPoints() {
return new StaticMethodsInterceptPoint[0];
}
}
2.实现灰度增强拦截
public class HandlerAdapterInterceptor implements InInterceptor, InstanceMethodsAroundInterceptor {
@Override
public void beforeMethod(EnhancedInstance objInst, Method method, Object[] allArguments, Class<?>[] argumentsTypes, MethodInterceptResult result){
String routingEnv = getRoutingEnv(allArguments);
this.setContext(routingEnv);
CounterManager.increaseConsume(ComponentType.MVC,routingEnv);
}
@Override
public Object afterMethod(EnhancedInstance objInst, Method method, Object[] allArguments, Class<?>[] argumentsTypes, Object ret) {
//清除threadLocal里的数据
this.removeContext();
return ret;
}
private String getRoutingEnv(Object[] allArguments){
//从http 请求头或Attribute 获取灰度标签设置到threadLocal
Object request = allArguments[0];
Method getHeader = ReflectUtils.getMethod(request, "getHeader", String.class);
String env = (String)ReflectUtils.invokeMethod(getHeader, request, X_ENV);
if(env != null && !env.trim().equals("")){
return env;
}
Method getAttribute = ReflectUtils.getMethod(request, "getAttribute", String.class);
return (String)ReflectUtils.invokeMethod(getAttribute, request, X_ENV);
}
}
这里只是介绍Servlet容器,如果项目实际使用其它类型web容器,也可以用类似的方式对其增强
线程池: 标签续传
服务或消息的路由规则依赖灰度标签,如果业务代码内出现跨线程操作后,则会出现灰度标签断传,从而导致路由错误;针对该问题可以分别对以下线程相关接口或类进行标签续传增强处理:
1.拦截Runnable或Callable,接口增强实现标签续传;
Callable 插件定义
public class CallableDefine extends ClassEnhancePluginDefine {
private static final String CALLABLE_CLASS = "java.util.concurrent.Callable";
private static final String CALLABLE_CLASS_INTERCEPTOR = "com.dbcat.gray.agent.threading.ThreadingConstructorInterceptor";
private static final String CALLABLE_CALL_METHOD_INTERCEPTOR = "com.dbcat.gray.agent.threading.ThreadingMethodInterceptor";
@Override
protected ClassMatch enhanceClass() {
return new ThreadingMatch(CALLABLE_CLASS);
}
@Override
public ConstructorInterceptPoint[] getConstructorsInterceptPoints() {
return new ConstructorInterceptPoint[] {
new ConstructorInterceptPoint() {
@Override
public ElementMatcher<MethodDescription> getConstructorMatcher() {
//拦截构造,切换线程前保存灰度标签到当前Callable实现上
return any();
}
@Override
public String getConstructorInterceptor() {
return CALLABLE_CLASS_INTERCEPTOR;
}
}
};
}
@Override
public InstanceMethodsInterceptPoint[] getInstanceMethodsInterceptPoints() {
return new InstanceMethodsInterceptPoint[] {
new InstanceMethodsInterceptPoint() {
@Override
public ElementMatcher<MethodDescription> getMethodsMatcher() {
//拦截call方法
return named("call").and(takesArguments(0));
}
@Override
public String getMethodsInterceptor() {
return CALLABLE_CALL_METHOD_INTERCEPTOR;
}
@Override
public boolean isOverrideArgs() {
return false;
}
}
};
}
}
Runnable 插件定义
public class RunnableDefine extends ClassEnhancePluginDefine {
private static final String RUNNABLE_CLASS = "java.lang.Runnable";
private static final String RUNNABLE_CLASS_INTERCEPTOR = "com.dbcat.gray.agent.threading.ThreadingConstructorInterceptor";
private static final String RUNNABLE_RUN_METHOD_INTERCEPTOR = "com.dbcat.gray.agent.threading.ThreadingMethodInterceptor";
@Override
protected ClassMatch enhanceClass() {
return new ThreadingMatch(RUNNABLE_CLASS);
}
@Override
public ConstructorInterceptPoint[] getConstructorsInterceptPoints() {
return new ConstructorInterceptPoint[] {
new ConstructorInterceptPoint() {
@Override
public ElementMatcher<MethodDescription> getConstructorMatcher() {
//拦截构造,切换线程前保存灰度标签到当前Runnable实现上
return any();
}
@Override
public String getConstructorInterceptor() {
return RUNNABLE_CLASS_INTERCEPTOR;
}
}
};
}
@Override
public InstanceMethodsInterceptPoint[] getInstanceMethodsInterceptPoints() {
return new InstanceMethodsInterceptPoint[] {
new InstanceMethodsInterceptPoint() {
@Override
public ElementMatcher<MethodDescription> getMethodsMatcher() {
//拦载run方法
return named("run").and(takesArguments(0));
}
@Override
public String getMethodsInterceptor() {
return RUNNABLE_RUN_METHOD_INTERCEPTOR;
}
@Override
public boolean isOverrideArgs() {
return false;
}
}
};
}
}
拦载Callabl或Runnable构造(可共用)
public class ThreadingConstructorInterceptor implements InInterceptor, InstanceConstructorInterceptor {
@Override
public void onConstruct(final EnhancedInstance objInst, final Object[] allArguments) {
//获取当前线程ThreadLocal里的灰度标签,并保存当前Callable或 Runnable 实现上
String env = this.getContext(null);
objInst.setGrayDynamicField(env);
}
}
拦载run或call 方法(可共用)
public class ThreadingMethodInterceptor implements InInterceptor, InstanceMethodsAroundInterceptor {
@Override
public void beforeMethod(final EnhancedInstance objInst, final Method method, final Object[] allArguments,
final Class<?>[] argumentsTypes, final MethodInterceptResult result) {
String xEnv = (String) objInst.getGrayDynamicField();
this.setContext(xEnv);
}
@Override
public Object afterMethod(final EnhancedInstance objInst, final Method method, final Object[] allArguments,
final Class<?>[] argumentsTypes, final Object ret) {
this.removeContext();
return ret;
}
}
2.拦截ThreadPoolExecutor, 但是当业务使用Callable或Runnable 时,使用的是lambda表达式时,
可以通过拦截ThreadPoolExecutor,增强实现标签续传
ThreadPool插件定义
需要拦截execute和submit方法
public class ThreadPoolExecutorDefine extends ClassInstanceMethodsEnhancePluginDefine {
private static final String ENHANCE_CLASS = "java.util.concurrent.ThreadPoolExecutor";
private static final String INTERCEPT_EXECUTE_METHOD_HANDLE = "com.dbcat.gray.agent.threading.ThreadPoolExecuteMethodInterceptor";
private static final String INTERCEPT_SUBMIT_METHOD_HANDLE = "com.dbcat.gray.agent.threading.ThreadPoolSubmitMethodInterceptor";
@Override
public boolean isBootstrapInstrumentation() {
return true;
}
@Override
protected ClassMatch enhanceClass() {
return LogicalMatchOperation.or(HierarchyMatch.byHierarchyMatch(ENHANCE_CLASS), MultiClassNameMatch.byMultiClassMatch(ENHANCE_CLASS));
}
@Override
public ConstructorInterceptPoint[] getConstructorsInterceptPoints() {
return new ConstructorInterceptPoint[0];
}
@Override
public InstanceMethodsInterceptPoint[] getInstanceMethodsInterceptPoints() {
return new InstanceMethodsInterceptPoint[]{
new InstanceMethodsInterceptPoint() {
@Override
public ElementMatcher<MethodDescription> getMethodsMatcher() {
return ElementMatchers.named("execute");
}
@Override
public String getMethodsInterceptor() {
return INTERCEPT_EXECUTE_METHOD_HANDLE;
}
@Override
public boolean isOverrideArgs() {
return true;
}
},
new InstanceMethodsInterceptPoint() {
@Override
public ElementMatcher<MethodDescription> getMethodsMatcher() {
return ElementMatchers.named("submit");
}
@Override
public String getMethodsInterceptor() {
return INTERCEPT_SUBMIT_METHOD_HANDLE;
}
@Override
public boolean isOverrideArgs() {
return true;
}
}
};
}
}
ThreadPool公共拦截类
public abstract class AbstractThreadPoolInterceptor implements InstanceMethodsAroundInterceptor {
@Override
public void beforeMethod(EnhancedInstance objInst, Method method, Object[] allArguments, Class<?>[] argumentsTypes, MethodInterceptResult result) throws Throwable {
if (notToEnhance(allArguments)) {
return;
}
Object wrappedObject = wrap(allArguments[0]);
if (wrappedObject != null) {
allArguments[0] = wrappedObject;
}
}
public abstract Object wrap(Object param);
@Override
public Object afterMethod(EnhancedInstance objInst, Method method, Object[] allArguments, Class<?>[] argumentsTypes, Object ret) throws Throwable {
return ret;
}
@Override
public void handleMethodException(EnhancedInstance objInst, Method method, Object[] allArguments, Class<?>[] argumentsTypes, Throwable t) {
}
private boolean notToEnhance(Object[] allArguments) {
if (allArguments == null || allArguments.length < 1) {
return true;
}
Object argument = allArguments[0];
//如果已经被增强过,不必在增强了
return argument instanceof EnhancedInstance ;
}
}
execute方法拦截
public class ThreadPoolExecuteMethodInterceptor extends AbstractThreadPoolInterceptor {
@Override
public Object wrap(Object param) {
if (param instanceof RunnableWrapper) {
return null;
}
if (param instanceof RunnableFuture) {
return null;
}
if (!(param instanceof Runnable)) {
return null;
}
Runnable runnable = (Runnable) param;
return new RunnableWrapper(runnable);
}
}
submit方法拦截
public class ThreadPoolSubmitMethodInterceptor extends AbstractThreadPoolInterceptor {
@Override
public Object wrap(Object param) {
if (param instanceof Callable) {
Callable callable = (Callable) param;
return new CallableWrapper(callable);
}
if (param instanceof Runnable) {
Runnable runnable = (Runnable) param;
return new RunnableWrapper(runnable);
}
return null;
}
}
spring-cloud 服务增强
cloud 服务之间的通通http通信的,首先要解决灰度标签在服务之间传递,可以利用http请求头,携带灰度标签;其它次是路由问题,spring-cloud 的远程调用负载是由ribbon实现,只要据灰度标签修改ribbon的路由规则,则可以实现灰度服务路由。
1. 灰度标签续传
分析可能存在通过feign调用或LoadBalance的 RestTemplate 调用服务,所以需要这两种方式的调用进行拦截,通过http请头续传灰度标。
Feign htttp 拦载插件定义
public class FeignTargetPluginDefine extends ClassInstanceMethodsEnhancePluginDefine {
private static final String ENHANCE_CLASS = "feign.Target";
private static final String INTERCEPTOR_CLASS = "com.dbcat.gray.agent.cloud.FeignRequestContextInterceptor";
@Override
protected ClassMatch enhanceClass() {
return HierarchyMatch.byHierarchyMatch(ENHANCE_CLASS);
}
@Override
public ConstructorInterceptPoint[] getConstructorsInterceptPoints() {
return new ConstructorInterceptPoint[0];
}
@Override
public InstanceMethodsInterceptPoint[] getInstanceMethodsInterceptPoints() {
return new InstanceMethodsInterceptPoint[]{
new InstanceMethodsInterceptPoint() {
@Override
public ElementMatcher<MethodDescription> getMethodsMatcher() {
return ElementMatchers.named("apply");
}
@Override
public String getMethodsInterceptor() {
return INTERCEPTOR_CLASS;
}
}
};
}
}
Feign灰度标签拦截器
public class FeignContextInterceptor implements InstanceMethodsAroundInterceptor {
@Override
public void beforeMethod(EnhancedInstance objInst, Method method, Object[] allArguments, Class<?>[] argumentsTypes, MethodInterceptResult result) throws Throwable {
RequestTemplate template = (RequestTemplate) allArguments[0];
//续传灰度标签
String routingEnv = (String) ServerContextHolder.getData(X_ENV);
if (routingEnv != null && !routingEnv.trim().equals("")) {
template.header(X_ENV, routingEnv);
}
}
}
RestTemplate http 拦截插件定义
public class ClientHttpRequestInterceptorPluginDefine extends ClassInstanceMethodsEnhancePluginDefine {
private static final String ENHANCE_CLASS = "org.springframework.http.client.ClientHttpRequestInterceptor";
private static final String INTERCEPTOR_CLASS = "com.dbcat.gray.agent.cloud.HttpRequestContextInterceptor";
@Override
protected ClassMatch enhanceClass() {
return HierarchyMatch.byHierarchyMatch(ENHANCE_CLASS);
}
@Override
public ConstructorInterceptPoint[] getConstructorsInterceptPoints() {
return new ConstructorInterceptPoint[0];
}
@Override
public InstanceMethodsInterceptPoint[] getInstanceMethodsInterceptPoints() {
return new InstanceMethodsInterceptPoint[]{
new InstanceMethodsInterceptPoint() {
@Override
public ElementMatcher<MethodDescription> getMethodsMatcher() {
return ElementMatchers.named("intercept");
}
@Override
public String getMethodsInterceptor() {
return INTERCEPTOR_CLASS;
}
}
};
}
}
RestTemplate http 拦截灰度标签续传
public class HttpRequestContextInterceptor implements InstanceMethodsAroundInterceptor {
@Override
public void beforeMethod(EnhancedInstance objInst, Method method, Object[] allArguments, Class<?>[] argumentsTypes, MethodInterceptResult result) throws Throwable {
HttpRequest request = (HttpRequest) allArguments[0];
String routingEnv = (String) ServerContextHolder.getData(X_ENV);
if (routingEnv != null && !routingEnv.trim().equals("")) {
request.getHeaders().set(X_ENV, routingEnv);
}
}
}
2.ribbon灰度路由
Rule 插件定义
public class RulePluginDefine extends ClassInstanceMethodsEnhancePluginDefine {
private static final String ENHANCE_CLASS = "com.netflix.loadbalancer.AbstractLoadBalancerRule";
private static final String INTERCEPTOR_CLASS = "com.dbcat.gray.agent.cloud.RuleInterceptor";
@Override
protected ClassMatch enhanceClass() {
return HierarchyMatch.byHierarchyMatch(ENHANCE_CLASS);
}
@Override
public ConstructorInterceptPoint[] getConstructorsInterceptPoints() {
return new ConstructorInterceptPoint[0];
}
@Override
public InstanceMethodsInterceptPoint[] getInstanceMethodsInterceptPoints() {
return new InstanceMethodsInterceptPoint[]{
new InstanceMethodsInterceptPoint() {
@Override
public ElementMatcher<MethodDescription> getMethodsMatcher() {
return ElementMatchers.named("choose");
}
@Override
public String getMethodsInterceptor() {
return INTERCEPTOR_CLASS;
}
}
};
}
}
Rule 灰度路由规则拦截改写
public class RuleInterceptor implements InstanceMethodsAroundInterceptor {
@Override
public void beforeMethod(EnhancedInstance objInst, Method method, Object[] allArguments, Class<?>[] argumentsTypes, MethodInterceptResult result) throws Throwable {
ZoneAvoidanceRule rule = (ZoneAvoidanceRule) objInst;
ILoadBalancer loadBalancer = rule.getLoadBalancer();
List<Server> allServers = loadBalancer.getAllServers();
if (allServers.isEmpty()) {
result.defineReturnValue(null);
return;
}
//据灰度标签,选择相应的服务
String env = (String) ServerContextHolder.getData(GrayConstant.X_ENV);
ServerSelector serverSelector = CloudServerSelector.build(env, allServers);
List<Server> targetServers = serverSelector.selectServers();
Server server = doChooseServer(targetServers, rule, allArguments);
result.defineReturnValue(server);
}
private Server doChooseServer(List<Server> targetServers, ZoneAvoidanceRule rule, Object[] allArguments) {
if (targetServers.isEmpty()) {
return null;
}
Object loadBalancerKey = allArguments[0];
Optional<Server> server = rule.getPredicate().chooseRoundRobinAfterFiltering(targetServers, loadBalancerKey);
return server.isPresent() ? server.get() : null;
}
}
dubbo服务增强
分析dubbo 源码发布,灰度标签的续传,只要改写ConsumerContextFilter和ContextFilter 两个filter,它们分别是消费的filter和服务提供方的filter;ConsumerContextFilter的作用是消费方上下文件信息通过 rpc的attachment传递给服务提供方;而ContextFilter的作用则是服务提供方将消息传递的上下文从attachment中取出;对灰度路由规则的改写,仅需拦载Router接口的实现即可。
1. 灰度标签续传
服务消费方ContextFilter插件定义
public class ConsumerConextFilterPluginDefine extends ClassInstanceMethodsEnhancePluginDefine {
private static final String ENHANCE_CLASS = "org.apache.dubbo.rpc.filter.ConsumerContextFilter";
private static final String INTERCEPTOR_CLASS = "com.dbcat.gray.agent.dubbo.ConsumerContextInterceptor";
@Override
protected ClassMatch enhanceClass() {
return NameMatch.byName(ENHANCE_CLASS);
}
@Override
public ConstructorInterceptPoint[] getConstructorsInterceptPoints() {
return new ConstructorInterceptPoint[0];
}
@Override
public InstanceMethodsInterceptPoint[] getInstanceMethodsInterceptPoints() {
return new InstanceMethodsInterceptPoint[]{
new InstanceMethodsInterceptPoint() {
@Override
public ElementMatcher<MethodDescription> getMethodsMatcher() {
return ElementMatchers.named("invoke");
}
@Override
public String getMethodsInterceptor() {
return INTERCEPTOR_CLASS;
}
}
};
}
}
服务提供方ContextFilter插件定义
public class ProviderContextFilterPluginDefine extends ClassInstanceMethodsEnhancePluginDefine {
private static final String ENHANCE_CLASS = "org.apache.dubbo.rpc.filter.ContextFilter";
private static final String INTERCEPTOR_CLASS = "com.dbcat.gray.agent.dubbo.ProviderContextInterceptor";
@Override
protected ClassMatch enhanceClass() {
return NameMatch.byName(ENHANCE_CLASS);
}
@Override
public ConstructorInterceptPoint[] getConstructorsInterceptPoints() {
return new ConstructorInterceptPoint[0];
}
@Override
public InstanceMethodsInterceptPoint[] getInstanceMethodsInterceptPoints() {
return new InstanceMethodsInterceptPoint[]{
new InstanceMethodsInterceptPoint() {
@Override
public ElementMatcher<MethodDescription> getMethodsMatcher() {
return ElementMatchers.named("invoke");
}
@Override
public String getMethodsInterceptor() {
return INTERCEPTOR_CLASS;
}
}
};
}
}
服务消费方ContextFilter拦截
public class ConsumerContextInterceptor implements InstanceMethodsAroundInterceptor {
@Override
public void beforeMethod(EnhancedInstance objInst, Method method, Object[] allArguments, Class<?>[] argumentsTypes, MethodInterceptResult result) {
RpcContext context = RpcContext.getContext();
String routingEnv = (String) ServerContextHolder.getData(X_ENV);
CounterManager.increaseConsume(DUBBO, routingEnv);
if (routingEnv != null && !routingEnv.trim().equals("")) {
context.setAttachment(X_ENV, routingEnv);
}
}
}
服务提供方ContextFilter拦截
public class ProviderContextInterceptor implements InstanceMethodsAroundInterceptor {
@Override
public void beforeMethod(EnhancedInstance objInst, Method method, Object[] allArguments, Class<?>[] argumentsTypes, MethodInterceptResult result) throws Throwable {
Invocation invocation = (Invocation) allArguments[1];
String routingEnv = invocation.getAttachment(X_ENV);
CounterManager.increasePublish(DUBBO, routingEnv);
if (routingEnv != null && !routingEnv.trim().equals("")) {
ServerContextHolder.setData(X_ENV, routingEnv);
}
}
}
2. 灰度路由规则拦截改写
路由插件定义
public class AppGrayRouterPluginDefine extends ClassInstanceMethodsEnhancePluginDefine {
private static final String ENHANCE_CLASS = "org.apache.dubbo.rpc.cluster.router.condition.config.AppRouter";
private static final String INTERCEPTOR_CLASS = "com.dbcat.gray.agent.dubbo.AppGrayRouterInterceptor";
@Override
protected ClassMatch enhanceClass() {
return NameMatch.byName(ENHANCE_CLASS);
}
@Override
public ConstructorInterceptPoint[] getConstructorsInterceptPoints() {
return new ConstructorInterceptPoint[0];
}
@Override
public InstanceMethodsInterceptPoint[] getInstanceMethodsInterceptPoints() {
return new InstanceMethodsInterceptPoint[]{
new InstanceMethodsInterceptPoint() {
@Override
public ElementMatcher<MethodDescription> getMethodsMatcher() {
return ElementMatchers.named("route");
}
@Override
public String getMethodsInterceptor() {
return INTERCEPTOR_CLASS;
}
}
};
}
}
灰度路由规则拦截改写
public class AppGrayRouterInterceptor implements InstanceMethodsAroundInterceptor {
@Override
public void beforeMethod(EnhancedInstance objInst, Method method, Object[] allArguments, Class<?>[] argumentsTypes, MethodInterceptResult result) {
List<Invoker> invokers = (List<Invoker>) allArguments[0];
if (invokers.isEmpty()) {
result.defineReturnValue(Collections.emptyList());
return;
}
String env = (String) ServerContextHolder.getData(GrayConstant.X_ENV);
DubboServerSelector selector = DubboServerSelector.build(env, invokers);
List<Invoker> targetInvokers = selector.selectServers();
result.defineReturnValue(targetInvokers);
}
}
nacos client增强
为了方便 注册中心与灰度管理方及应用实例,统一识别某一个实例,应用在启动时,会动态生产一个实例id, 分别上报到注册中或和灰度发布管理管,所以,如果使用nacos作为注册中心,需在应用启动时,作为元数据上报到注册中收。
插件定义
public class NacosDiscoveryPropertiesPluginDefine extends ClassInstanceMethodsEnhancePluginDefine {
private static final String ENHANCE_CLASS = "com.alibaba.cloud.nacos.NacosDiscoveryProperties";
private static final String INTERCEPTOR_CLASS = "com.dbcat.gray.agent.cloud.NacosDiscoveryPropertiesInterceptor";
@Override
protected ClassMatch enhanceClass() {
return NameMatch.byName(ENHANCE_CLASS);
}
@Override
public ConstructorInterceptPoint[] getConstructorsInterceptPoints() {
return new ConstructorInterceptPoint[]{
new ConstructorInterceptPoint() {
@Override
public ElementMatcher<MethodDescription> getConstructorMatcher() {
return ElementMatchers.any();
}
@Override
public String getConstructorInterceptor() {
return INTERCEPTOR_CLASS;
}
}
};
}
@Override
public InstanceMethodsInterceptPoint[] getInstanceMethodsInterceptPoints() {
return new InstanceMethodsInterceptPoint[0];
}
}
实例uuid拦截上报
public class NacosDiscoveryPropertiesInterceptor implements InstanceConstructorInterceptor {
@Override
public void onConstruct(EnhancedInstance objInst, Object[] allArguments) throws Throwable {
ServerInstance instance = ServerInstance.getInstance();
NacosDiscoveryProperties properties = (NacosDiscoveryProperties) objInst;
Map<String, String> metadata = properties.getMetadata();
metadata.put(GrayConstant.INSTANCE_UUID, instance.getUuid());
metadata.put(GrayConstant.APP_NAME,instance.getAppName());
}
}
eureka client增强
原因同上
插件定义
public class InstanceInfoPluginDefine extends ClassInstanceMethodsEnhancePluginDefine {
private static final String ENHANCE_CLASS = "com.netflix.appinfo.InstanceInfo";
private static final String INTERCEPTOR_CLASS = "com.dbcat.gray.agent.cloud.InstanceInfoInterceptor";
@Override
protected ClassMatch enhanceClass() {
return NameMatch.byName(ENHANCE_CLASS);
}
@Override
public ConstructorInterceptPoint[] getConstructorsInterceptPoints() {
return new ConstructorInterceptPoint[]{
new ConstructorInterceptPoint() {
@Override
public ElementMatcher<MethodDescription> getConstructorMatcher() {
return ElementMatchers.any();
}
@Override
public String getConstructorInterceptor() {
return INTERCEPTOR_CLASS;
}
}
};
}
@Override
public InstanceMethodsInterceptPoint[] getInstanceMethodsInterceptPoints() {
return new InstanceMethodsInterceptPoint[0];
}
}
实例uuid拦截上报
public class InstanceInfoInterceptor implements InstanceConstructorInterceptor {
@Override
public void onConstruct(EnhancedInstance objInst, Object[] allArguments) throws Throwable {
ServerInstance instance = ServerInstance.getInstance();
InstanceInfo instanceInfo = (InstanceInfo) objInst;
Map<String, String> metadata = instanceInfo.getMetadata();
metadata.put(GrayConstant.INSTANCE_UUID, instance.getUuid());
metadata.put(APP_NAME,instance.getAppName());
}
}
未完,待续…
给大家安利一款mysql监控软件: 安装方便,消耗低,可视化,傻瓜式操作,可以监控慢日志详情、cpu、内存、连接数、tps 等信息
体验演示
下载地址