[实习]Skywalking

SkyWalking

1.是什么

skywalking是一个包含监控,追踪,并拥有故障诊断能力的分布式系统。它主要的作用是全链路监控,收集数据,分析处理数据,然后可视化呈现。这么说有点抽象,接下来画图来说

这是skywalking的架构。它通过Service(client agent)收集数据,然后传输给receiver cluster,然后接下来在内部部分需要原始数据或者需要进行整合的下发给aggregator,其他需要做es的发给es(Elasticsearch 是一个分布式、高扩展、高实时的搜索与数据分析引擎。它能很方便的使大量数据具有搜索、分析和探索的能力。充分利用Elasticsearch的水平伸缩性,能使数据在生产环境变得更有价值。Elasticsearch 的实现原理主要分为以下几个步骤,首先用户将数据提交到Elasticsearch 数据库中,再通过分词控制器去将对应的语句分词,将其权重和分词结果一并存入数据,当用户搜索数据时候,再根据权重将结果排名,打分,再将返回结果呈现给用户。)下面会介绍数据类型,一般分为三种,感到疑惑可以翻到第3点看一下
在这里插入图片描述
到这里只要懂它是什么,做了什么即可,下面会进一步介绍,深化理解。

2. 架构解析

2.1 数据收集

Skywalking 数据收集功能采用核心模块加插件的方式实现。核心模块实现了JVM数据收集、数据采样、数据发送等功能;而不同的插件用来实现各种中间件、RPC等组件的数据收集。
在这里插入图片描述
当核心模块使用插件采集到链路数据后,会将数据加入到本地缓存队列之中,使用生产-消费者模式进行异步发送数据。**这里其实就和我之前写的kafka和talos差不多了。**具体思路就是Core这边的核心模块收集数据,然后plugin loader作消息队列中间件把信息存入右边仓库内。
在这里插入图片描述
Agent介绍(还不是很明白)
那么具体的链路数据到底是怎么收集的呢? 不知道大家有没有听说过javaagent。它为我们提供了一种在运行期修改java字节码的能力。具体就是,在编译期,java编译器会将我们的源代码编译成java字节码,也就是.class文件。在运行期,JVM载入类文件时,会根据javaagent中的定义,动态修改类文件,从而达到字节码注入的目的。 Skywalking 使用javaagent的方式,在需要收集链路信息的地方,拦截对应的字节码,进行AOP修改,当某个调用链路运行至已经被SkyWalking代理过的方法时,SkyWalking会通过代理逻辑进行这些信息的收集、传递和上报。
在这里插入图片描述

3. 数据类型

数据类型主要分成三种:1.原始数据(链路数据,JVM数据),2.指标数据Metrics(P99,P95, QPS),3.采样数据(Slow service, slow method, slow SQL)。
原始数据,就是节点信息、链路数据、JVM数据等从数据采集端直接上传上来的数据;第二部分是P99、QPS这种通过链路数据进行统计后的指标数据;第三种是类似慢服务、慢方法、慢sql之类的根据链路信息计算出来的TopN采样数据由于每种数据类型的计算方法不同,所以他们的计算流程也稍有不同。我的任务主要聚焦于指标数据。

在这里插入图片描述
数据处理端主要分为两层来处理所有的数据,第一层,我们成为L1,接收从数据收集端发送来的原始数据,一方面将原始数据打入ES存储,一方面将原始数据放入内部的消息队列中。第二层,也就是L2层,从消息队列中取出原始数据,进行聚合、计算,生成指标数据与采样数据,再存入ES中

4. 数据处理端(服务端)的模块化设计

数据收集其实在客户端,由用户收集反馈
Skywalking将每个独立的功能都抽象成一个模块,设计统一的上层接口;所有的模块都ModuleManager中管理;模块间的调用都通过ModuleManager来获得其他模块的实现;而同样的模块可以有多种实现方式,比如配置模块,我们可以使用Apollo、Zookeeper等中间件来实现;存储模块则可以使用ES、Mysql等数据库来实现模块的各个实现之间没有耦合关系,全部通过模块定义中规定的上层接口来调用采用模块化的设计后,我们就可以跟我业务的使用场景,来定制化各个组件的实现方式,并且可以简单的开发属于我们自己的插件,比如开发Talos数据摄取方式等。
模块化设计的优点是:定义清晰,可以有多种实现,无耦合,自由插拔,便于拓展
在这里插入图片描述
模块端主要由4种模块结构构成,他们的关系如下图
在这里插入图片描述
以下代码都是抽象出来的,想要理解更多请自行参考源码

3.1 ModuleManager

这个类负责管理module。作为模块的管理器,其本身实现很简单,只有一个成员变量,三个共有方法成员变量loadedModules使用HashMap来存储所有初始化过得模块实现。由此可知,每个manager实现有且只有一个函数init用来初始化所有的模块
那么要使用哪些模块呢?这个是通过传递一个配置参数applicationConfiguration来实现的在初始化中主要分为两部分逻辑,首先是每个模块的预处理部分,预处理后,会根据模块间的依赖,生成拓扑图来进行初始化剩下两个函数分别是has与find,分别用来判断模块实现是否存在与获得模块实现

注意这里用的是provider的prepare,而不是调用define的prepare。是因为这里的预处理是要初始化模块的服务,而define只是个定义。且在provider中如果需要会调用define.prepare的,所以不用担心。

public class ModuleManager implements ModuleDefineHolder {
	//存放所有初始化过的模块,用于管理
    private final Map<String, ModuleDefine> loadedModules = new HashMap<>();

	//初始化
    public void init(ApplicationConfiguration applicationConfiguration) {
        ...

		//预处理
        for (ModuleProvider provider: providers) {
            provider.prepare();
        }

		//按照模块依赖初始化
        BootstrapFlow bootstrapFlow = new BootstrapFlow(loadedModules);
        bootstrapFlow.start(this);
        bootstrapFlow.notifyAfterCompleted();
    }

    public boolean has(String moduleName) {...}

    public ModuleProviderHolder find(String moduleName) {...}
}

3.2 ModuleDefine

我们再来看下模块定义类,它有切只有一个模块实现成员变量loadedProvider,这也再一次证实了一个模块同一时间只能有一个实现;此外模块定义类中还有一个特别重要的方法,就是services(),这个模块向外提供哪些接口服务,都是通过services来进行定义的比如说存储模块,就需要对外提供各个数据表的增删改查的服务;集群模块,就需要对外提供集群节点列表的服务

public abstract class ModuleDefine implements ModuleProviderHolder {

    private ModuleProvider loadedProvider = null; //模块实现

    private final String name; //模块名称

    public ModuleDefine(String name) {    this.name = name;    }
  
    public abstract Class[] services(); //对外提供的服务

	//初始化
    void prepare(ModuleManager moduleManager, ModuleConfiguration configuration
        , ServiceLoader<ModuleProvider> moduleProviderLoader) {
        ...
    }
}

3.3 ModuleProvider

服务实现模块中,拥有一个services成员变量,它就是用来存放在模块定义中规定的服务的实现还有一个接口是requiredModules,他用来规定模块的依赖列表

public abstract class ModuleProvider implements ModuleServiceHolder {
    private ModuleManager manager;
    private ModuleDefine moduleDefine;
    //服务实现列表
    private final Map<Class<? extends Service>, Service> services = new HashMap<>();

    public abstract String name();

    public abstract void prepare();

    public abstract void start();

    public abstract void notifyAfterCompleted();

    public abstract String[] requiredModules(); //模块依赖列表

    public final void registerServiceImplementation(Class<? extends Service> serviceType, Service service) {...}

    void requiredCheck(Class<? extends Service>[] requiredServices) {    ...    }
    ...
}

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值