OAL 如何通过动态生成的 Class 类,保存数据

前置工作

OAL 如何将动态生成的 SourceDispatcher 添加到 DispatcherManager

	// org.apache.skywalking.oap.server.core.oal.rt.OALEngineLoaderService#load
public void load(OALDefine define) throws ModuleStartException {
if (oalDefineSet.contains(define)) {
// each oal define will only be activated once
return;
}
try {
OALEngine engine = loadOALEngine(define);
// 设置Stream注解监听器,用来处理org.apache.skywalking.oap.server.core.analysis.Stream注解
StreamAnnotationListener streamAnnotationListener = new StreamAnnotationListener(moduleManager);
engine.setStreamListener(streamAnnotationListener); // org.apache.skywalking.oap.server.core.source.SourceReceiverImpl#getDispatcherDetectorListener
// 获取的就是org.apache.skywalking.oap.server.core.analysis.DispatcherManager对象
engine.setDispatcherListener(moduleManager.find(CoreModule.NAME)
.provider()
.getService(SourceReceiver.class)
.getDispatcherDetectorListener()); // 调用的就是 org.apache.skywalking.oal.rt.OALRuntime#start
engine.start(OALEngineLoaderService.class.getClassLoader()); // 通知所有的监听器
engine.notifyAllListeners(); oalDefineSet.add(define);
} catch (ReflectiveOperationException | OALCompileException e) {
throw new ModuleStartException(e.getMessage(), e);
}
}

org.apache.skywalking.oap.server.core.oal.rt.OALEngineLoaderService#load 方法做了如下操作:

  1. 设置 Stream 注解监听器,用来获取指标类的基本信息,并进行相应处理
@Stream(
name = "instance_jvm_class_loaded_class_count",
scopeId = 11000,
builder = InstanceJvmClassLoadedClassCountMetricsBuilder.class,
processor = MetricsStreamProcessor.class
)
public class InstanceJvmClassLoadedClassCountMetrics extends LongAvgMetrics implements WithMetadata {
// 省略
}
  1. 通过模块管理器,先获取到 SourceReceiver 对象,借由此对象获取到 DispatcherManager 对象
public class SourceReceiverImpl implements SourceReceiver {
@Getter
private final DispatcherManager dispatcherManager; @Override
public DispatcherDetectorListener getDispatcherDetectorListener() {
return getDispatcherManager();
}
}
  1. 启动 OAL 引擎
  2. 通知所有的监听器

org.apache.skywalking.oal.rt.OALRuntime#notifyAllListeners

    @Override
public void notifyAllListeners() throws ModuleStartException {
for (Class metricsClass : metricsClasses) {
try {
// 将动态生成的Metrics添加到MetricsStreamProcessor
streamAnnotationListener.notify(metricsClass);
} catch (StorageException e) {
throw new ModuleStartException(e.getMessage(), e);
}
}
for (Class dispatcherClass : dispatcherClasses) {
try {
// 添加动态生成的SourceDispatch至DispatcherManager
dispatcherDetectorListener.addIfAsSourceDispatcher(dispatcherClass);
} catch (Exception e) {
throw new ModuleStartException(e.getMessage(), e);
}
}
}

org.apache.skywalking.oap.server.core.analysis.DispatcherManager#addIfAsSourceDispatcher

    @Override
public void addIfAsSourceDispatcher(Class aClass) throws IllegalAccessException, InstantiationException {
if (!aClass.isInterface() && !Modifier.isAbstract(
aClass.getModifiers()) && SourceDispatcher.class.isAssignableFrom(aClass)) {
Type[] genericInterfaces = aClass.getGenericInterfaces();
for (Type genericInterface : genericInterfaces) {
ParameterizedType anInterface = (ParameterizedType) genericInterface;
if (anInterface.getRawType().getTypeName().equals(SourceDispatcher.class.getName())) {
Type[] arguments = anInterface.getActualTypeArguments(); if (arguments.length != 1) {
throw new UnexpectedException("unexpected type argument number, class " + aClass.getName());
}
Type argument = arguments[0]; Object source = ((Class) argument).newInstance(); if (!Source.class.isAssignableFrom(source.getClass())) {
throw new UnexpectedException(
"unexpected type argument of class " + aClass.getName() + ", should be `org.apache.skywalking.oap.server.core.source.Source`. ");
} Source dispatcherSource = (Source) source;
SourceDispatcher dispatcher = (SourceDispatcher) aClass.newInstance(); int scopeId = dispatcherSource.scope(); // 使用scope做SourceDispatcher Map的key
List<SourceDispatcher> dispatchers = this.dispatcherMap.get(scopeId);
if (dispatchers == null) {
dispatchers = new ArrayList<>();
this.dispatcherMap.put(scopeId, dispatchers);
}
// 添加
dispatchers.add(dispatcher); LOGGER.info("Dispatcher {} is added into DefaultScopeDefine {}.", dispatcher.getClass()
.getName(), scopeId);
}
}
}
}

OAL 如何将动态生成的 Metrics 添加到 MetricsStreamProcessor

与“ OAL  如何将动态生成的 SourceDispatcher  添加到 DispatcherManager ”流程基本一致,都是在 org.apache.skywalking.oal.rt.OALRuntime#notifyAllListeners 方法中处理的

    @Override
public void notifyAllListeners() throws ModuleStartException {
for (Class metricsClass : metricsClasses) {
try {
// 将动态生成的Metrics添加到MetricsStreamProcessor
streamAnnotationListener.notify(metricsClass);
} catch (StorageException e) {
throw new ModuleStartException(e.getMessage(), e);
}
}
for (Class dispatcherClass : dispatcherClasses) {
try {
// 添加动态生成的SourceDispatch至DispatcherManager
dispatcherDetectorListener.addIfAsSourceDispatcher(dispatcherClass);
} catch (Exception e) {
throw new ModuleStartException(e.getMessage(), e);
}
}
}

org.apache.skywalking.oap.server.core.analysis.StreamAnnotationListener#notify

    @Override
public void notify(Class aClass) throws StorageException {
if (aClass.isAnnotationPresent(Stream.class)) {
Stream stream = (Stream) aClass.getAnnotation(Stream.class); if (stream.processor().equals(RecordStreamProcessor.class)) {
RecordStreamProcessor.getInstance().create(moduleDefineHolder, stream, aClass);
} else if (stream.processor().equals(MetricsStreamProcessor.class)) {
// 因为所有的Metrics类上的@Stream注解的processor = MetricsStreamProcessor.class,所以只会走该分支
MetricsStreamProcessor.getInstance().create(moduleDefineHolder, stream, aClass);
} else if (stream.processor().equals(TopNStreamProcessor.class)) {
TopNStreamProcessor.getInstance().create(moduleDefineHolder, stream, aClass);
} else if (stream.processor().equals(NoneStreamProcessor.class)) {
NoneStreamProcessor.getInstance().create(moduleDefineHolder, stream, aClass);
} else if (stream.processor().equals(ManagementStreamProcessor.class)) {
ManagementStreamProcessor.getInstance().create(moduleDefineHolder, stream, aClass);
} else {
throw new UnexpectedException("Unknown stream processor.");
}
} else {
throw new UnexpectedException(
"Stream annotation listener could only parse the class present stream annotation.");
}
}

org.apache.skywalking.oap.server.core.analysis.worker.MetricsStreamProcessor#create 中,通过一系列的处理,最后将 Worker (处理器)放入 map 中,等待后续被使用

    /**
* Create the workers and work flow for every metrics.
*
* @param moduleDefineHolder pointer of the module define.
* @param stream definition of the metrics class.
* @param metricsClass data type of the streaming calculation.
*/
public void create(ModuleDefineHolder moduleDefineHolder, Stream stream, Class<? extends Metrics> metricsClass) throws StorageException {
this.create(moduleDefineHolder, StreamDefinition.from(stream), metricsClass);
} @SuppressWarnings("unchecked")
public void create(ModuleDefineHolder moduleDefineHolder,
StreamDefinition stream,
Class<? extends Metrics> metricsClass) throws StorageException {
if (DisableRegister.INSTANCE.include(stream.getName())) {
return;
} StorageDAO storageDAO = moduleDefineHolder.find(StorageModule.NAME).provider().getService(StorageDAO.class);
IMetricsDAO metricsDAO;
try {
// 获取@Stream注解上的builder类,并创建Metrics存储DAO对象
metricsDAO = storageDAO.newMetricsDao(stream.getBuilder().newInstance());
} catch (InstantiationException | IllegalAccessException e) {
throw new UnexpectedException("Create " + stream.getBuilder().getSimpleName() + " metrics DAO failure.", e);
} ModelCreator modelSetter = moduleDefineHolder.find(CoreModule.NAME).provider().getService(ModelCreator.class);
DownSamplingConfigService configService = moduleDefineHolder.find(CoreModule.NAME)
.provider()
.getService(DownSamplingConfigService.class); MetricsPersistentWorker hourPersistentWorker = null;
MetricsPersistentWorker dayPersistentWorker = null; MetricsTransWorker transWorker = null; final MetricsExtension metricsExtension = metricsClass.getAnnotation(MetricsExtension.class);
/**
* All metrics default are `supportDownSampling` and `insertAndUpdate`, unless it has explicit definition.
*/
boolean supportDownSampling = true;
boolean supportUpdate = true;
if (metricsExtension != null) {
supportDownSampling = metricsExtension.supportDownSampling();
supportUpdate = metricsExtension.supportUpdate();
}
if (supportDownSampling) {
if (configService.shouldToHour()) {
Model model = modelSetter.add(
metricsClass, stream.getScopeId(), new Storage(stream.getName(), DownSampling.Hour), false);
hourPersistentWorker = downSamplingWorker(moduleDefineHolder, metricsDAO, model, supportUpdate);
}
if (configService.shouldToDay()) {
Model model = modelSetter.add(
metricsClass, stream.getScopeId(), new Storage(stream.getName(), DownSampling.Day), false);
dayPersistentWorker = downSamplingWorker(moduleDefineHolder, metricsDAO, model, supportUpdate);
} transWorker = new MetricsTransWorker(
moduleDefineHolder, hourPersistentWorker, dayPersistentWorker);
} Model model = modelSetter.add(
metricsClass, stream.getScopeId(), new Storage(stream.getName(), DownSampling.Minute), false);
MetricsPersistentWorker minutePersistentWorker = minutePersistentWorker(
moduleDefineHolder, metricsDAO, model, transWorker, supportUpdate); String remoteReceiverWorkerName = stream.getName() + "_rec";
IWorkerInstanceSetter workerInstanceSetter = moduleDefineHolder.find(CoreModule.NAME)
.provider()
.getService(IWorkerInstanceSetter.class);
workerInstanceSetter.put(remoteReceiverWorkerName, minutePersistentWorker, metricsClass); MetricsRemoteWorker remoteWorker = new MetricsRemoteWorker(moduleDefineHolder, remoteReceiverWorkerName);
MetricsAggregateWorker aggregateWorker = new MetricsAggregateWorker(
moduleDefineHolder, remoteWorker, stream.getName()); // private Map<Class<? extends Metrics>, MetricsAggregateWorker> entryWorkers = new HashMap<>();
// 将指标类的Class与MetricsAggregateWorker放入map中
// 当需要处理指标数据时,从map中获取即可
entryWorkers.put(metricsClass, aggregateWorker);
}

SourceReceiver 处理 Source 相关流程

在“从一个案例开始分析 OAL 原理”一节,聊到了 oap server 将从 agent 收到的指标信息,发送至 SourceReceive

对应的坐标是:org.apache.skywalking.oap.server.analyzer.provider.jvm.JVMSourceDispatcher#sendToClassMetricProcess

    private void sendToClassMetricProcess(String service,
String serviceId,
String serviceInstance,
String serviceInstanceId,
long timeBucket,
Class clazz) {
// 拼装Source对象
ServiceInstanceJVMClass serviceInstanceJVMClass = new ServiceInstanceJVMClass();
serviceInstanceJVMClass.setId(serviceInstanceId);
serviceInstanceJVMClass.setName(serviceInstance);
serviceInstanceJVMClass.setServiceId(serviceId);
serviceInstanceJVMClass.setServiceName(service);
serviceInstanceJVMClass.setLoadedClassCount(clazz.getLoadedClassCount());
serviceInstanceJVMClass.setUnloadedClassCount(clazz.getUnloadedClassCount());
serviceInstanceJVMClass.setTotalLoadedClassCount(clazz.getTotalLoadedClassCount());
serviceInstanceJVMClass.setTimeBucket(timeBucket);
// 将Source对象发送至SourceReceive进行处理
sourceReceiver.receive(serviceInstanceJVMClass);
}

SourceReceiver 的默认实现类 org.apache.skywalking.oap.server.core.source.SourceReceiverImpl ,将收集到的指标通过 org.apache.skywalking.oap.server.core.analysis.DispatcherManager#forward 进行分发

package org.apache.skywalking.oap.server.core.source;

import java.io.IOException;
import lombok.Getter;
import org.apache.skywalking.oap.server.core.analysis.DispatcherDetectorListener;
import org.apache.skywalking.oap.server.core.analysis.DispatcherManager; public class SourceReceiverImpl implements SourceReceiver {
@Getter
private final DispatcherManager dispatcherManager; public SourceReceiverImpl() {
this.dispatcherManager = new DispatcherManager();
} @Override
public void receive(Source source) {
// 通过调配器管理器进行转发
dispatcherManager.forward(source);
} @Override
public DispatcherDetectorListener getDispatcherDetectorListener() {
return getDispatcherManager();
} public void scan() throws IOException, InstantiationException, IllegalAccessException {
dispatcherManager.scan();
}
}
	// org.apache.skywalking.oap.server.core.analysis.DispatcherManager#forward
public void forward(Source source) {
if (source == null) {
return;
}
// 通过source的scope找到对应的调度器
List<SourceDispatcher> dispatchers = dispatcherMap.get(source.scope()); /**
* Dispatcher is only generated by oal script analysis result.
* So these will/could be possible, the given source doesn't have the dispatcher,
* when the receiver is open, and oal script doesn't ask for analysis.
*/
if (dispatchers != null) {
source.prepare();
// 调度器进行分发,OAL动态生成的调度器,也会在这进行分发
for (SourceDispatcher dispatcher : dispatchers) {
dispatcher.dispatch(source);
}
}
}

MetricsStreamProcessor 如何处理 SourceDispatcher 发送过来的指标数据

完整代码请见“ OAL 如何动态生成 Class 类”下“案例”一节

org.apache.skywalking.oap.server.core.source.oal.rt.dispatcher.ServiceInstanceJVMClassDispatcher#doInstanceJvmClassLoadedClassCount 发送数据至 org.apache.skywalking.oap.server.core.analysis.worker.MetricsStreamProcessor

package org.apache.skywalking.oap.server.core.source.oal.rt.dispatcher;

import org.apache.skywalking.oap.server.core.analysis.SourceDispatcher;
import org.apache.skywalking.oap.server.core.analysis.worker.MetricsStreamProcessor;
import org.apache.skywalking.oap.server.core.source.ServiceInstanceJVMClass;
import org.apache.skywalking.oap.server.core.source.Source;
import org.apache.skywalking.oap.server.core.source.oal.rt.metrics.InstanceJvmClassLoadedClassCountMetrics; public class ServiceInstanceJVMClassDispatcher implements SourceDispatcher<ServiceInstanceJVMClass> {
private void doInstanceJvmClassLoadedClassCount(ServiceInstanceJVMClass var1) {
InstanceJvmClassLoadedClassCountMetrics var2 = new InstanceJvmClassLoadedClassCountMetrics();
var2.setTimeBucket(var1.getTimeBucket());
var2.setEntityId(var1.getEntityId());
var2.setServiceId(var1.getServiceId());
var2.combine(var1.getLoadedClassCount(), (long)1);
// 发送数据到指标流处理器
MetricsStreamProcessor.getInstance().in(var2);
} public void dispatch(Source var1) {
ServiceInstanceJVMClass var2 = (ServiceInstanceJVMClass)var1;
this.doInstanceJvmClassLoadedClassCount(var2);
} public ServiceInstanceJVMClassDispatcher() {
}
}

org.apache.skywalking.oap.server.core.analysis.worker.MetricsStreamProcessor#in 方法中,使用在 org.apache.skywalking.oap.server.core.analysis.worker.MetricsStreamProcessor#create 中创建的 Worker 对象,保存数据

    public void in(Metrics metrics) {
MetricsAggregateWorker worker = entryWorkers.get(metrics.getClass());
if (worker != null) {
worker.in(metrics);
}
}

PS:内部再细节一些的数据处理流程,相关的关键字有: DataCarrier 、 Worker 、 StorageModule  ,暂且不表,不是这篇文章的内容。

总结

Skywalking Metrics处理流程

参考文档

分享并记录所学所见

Skywalking-09:OAL原理——如何通过动态生成的Class类保存数据的更多相关文章

  1. 讨论一下hibernate如何动态注册一个动态生成的实体类

    如何动态生成实体类请参考这篇博文:http://www.cnblogs.com/anai/p/4269858.html 下面说说得到实体类后,如何能使用hibernate的接口来进行数据访问. 我们都 ...

  2. spring boot 动态生成接口实现类

    目录 一: 定义注解 二: 建立动态代理类 三: 注入spring容器 四: 编写拦截器 五: 新建测试类 在某些业务场景中,我们只需要业务代码中定义相应的接口或者相应的注解,并不需要实现对应的逻辑. ...

  3. 使用T4模板动态生成NPoco实体类

    这是一个妥妥的NPoco类,这是我们在工作开发中,手动去写这个实体类,属实非常心累,字段少无所谓一次两次,数量多了,字段多了,就心态裂开

  4. Skywalking-07:OAL原理——解释器实现

    OAL 解释器实现 OAL 解释器是基于 Antlr4 实现的,我们先来了解下 Antlr4 Antlr4 基本介绍 Antlr4 使用案例 参考Antlr4的使用简介这篇文章,我们实现了一个简单的案 ...

  5. js动态生成水印

    原理:通过动态生成canvas然后转为base64格式 代码Demo export const waterMark = (text) =>{ let _wm = document.createE ...

  6. Java下的框架编程(反射,泛型,元数据,CGLib,代码动态生成,AOP,动态语言嵌入)

    Java 虽然没有动态语言般暴起,但仍然天连天,水接水的生出好多框架技术---反射(reflection),泛型(generics),元数据(annotation),proxies(proxy/cgl ...

  7. net core天马行空系列:降低net core门槛,数据库操作和http访问仅需写接口,实现类由框架动态生成

    引文   hi,大家好,我是三合.不知各位有没有想过,如果能把数据库操作和http访问都统一封装成接口(interface)的形式, 然后接口对应的实现类由框架去自动生成,那么必然能大大降低工作量,因 ...

  8. Aop动态生成代理类时支持带参数构造函数

    一.背景 在某些情况下,我们需要植入AOP代码的类并没有默认构造函数.那么此时动态生成的代理类也需要相同签名的构造函数,并且内部调用原始类的构造函数.自己折腾了1晚上没搞定,现在搞定了发出来供大家一起 ...

  9. Java 动态生成复杂 Word

    Java 动态生成复杂 Word 阅读目录 1. 制作 Word 模版,将你需要动态生成的字段用${}替换.2. 将 Word文档保存为 xml .3. 引入项目. 项目中需要用 java 程序生成d ...

随机推荐

  1. 利用AOP切面打印项目中每个接口的运行情况

    1.前言 AOP切面技术,大家应该都听知道,Spring框架的主要功能之一. AOP切面的用途很广,其中一个常见的用途就是打印接口方法的运行日志和运行时间. 日志对于一个项目很是重要,不仅有助于调错, ...

  2. 详解 Interpolator动画插值器

    Interpolator 被用来修饰动画效果,定义动画的变化率.在Android源码中对应的接口类为TimeInterpolator,通过输入均匀变化的0~1之间的值,可以得到匀速.正加速.负加速.无 ...

  3. cmd关闭端口占用

    netstat -nao |findStr "8080" taskkill /pid 15406  /f

  4. ES6扩展——数值扩展

    1.0o代表八进制 0b代表二进制 ,通过Number()可转为10进制: //0o 0O octanary八进制 //0b 0B binary二进制 console.log(0o16); //14 ...

  5. 求方程 p+q+r+s+t=pqrst 的全体自然数解(约定p<=q<=r<=s<=t)

    解:方程左右的表达式分别记为u和v. 由题设有5t>=u. 0本来是不算入自然数的,现在的趋势是把0也算作自然数. 若p=0,则v=0,为使得u=0成立,q.r.s.t都必需为0. 这样就得到方 ...

  6. 基于CentOS7.x Linux操作系统,从0开始构建一套Docker虚拟化平台,使用二进制Tar包方式,部署的步骤和方法如下:

    #配置centos7的yum源#建议阿里源#链接:https://yq.aliyun.com/articles/525282?type=2#从Docker官网下载软件包: ls -l docker-1 ...

  7. UDP实现在线聊天功能

    发送端 //发送 public class UDPChat01 { public static void main(String[] args) throws Exception { //开启端口 D ...

  8. 记一次 .NET 某机械臂智能机器人控制系统MRS CPU爆高分析

    一:背景 1. 讲故事 这是6月中旬一位朋友加wx求助dump的故事,他的程序 cpu爆高UI卡死,问如何解决,截图如下: 在拿到这个dump后,我发现这是一个关于机械臂的MRS程序,哈哈,在机械臂这 ...

  9. CGLib 简析

    背景 JDK 动态代理存在的一些问题: 调用效率低 JDK 通过反射实现动态代理调用,这意味着低下的调用效率: 每次调用 Method.invoke() 都会检查方法的可见性.校验参数是否匹配,过程涉 ...

  10. adb 常用命令大全(4)- 应用管理

    查看应用列表 语法格式 adb shell pm list packages [-f] [-d] [-e] [-s] [-3] [-i] [-u] [--user USER_ID] [FILTER] ...