分布式链路追踪-SkyWalking

分布式链路追踪-SkyWalking

为什么需要链路追踪

在这里插入图片描述

在这个微服务系统中,用户通过浏览器的 H5页面访问系统,这个用 户请求会先抵达微服务网关组件,然后网关再把请求分发给各个微 服务。所以你会发现,用户请求从发起到结束要经历 很多个微服务 的处理,这里面还涉及到消息组件的集成。

在这里插入图片描述

存在的问题:

服务之间的依赖与被依赖的关系如何能够清晰的看到?

出现异常时如何能够快速定位到异常服务?

出现性能瓶颈时如何能够迅速定位哪个服务影响的?

链路

可以将链路理解为物理电路图

​ 链路和电路图都有起点和终点。

​ 链路和电路图都通过可视化得技术手段,来模拟真实组件得运行轨迹。

​ 链路和电路图都非常复杂,并且随着系统复杂程度得增加,其可视化复杂度也会成几何倍数增加。

在这里插入图片描述

解决:

为了能够在分布式架构中快速定位问题,分布式链路追踪应运 而生。将一次分布式请求还原成调用链路,进行日志记录,性 能监控并将一次分布式请求的调用情况集中展示。比如各个服 务节点上的耗时、请求具体到达哪台机器上、每个服务节点的 请求状态等等。

常见链路追踪技术有那些

市面上有很多链路追踪的项目,其中也不乏一些优秀的,如下:

**Sleuth:**SpringCloud 提供的分布式系统中链路追踪解决方 案。很可惜的是阿里系并没有链路追踪相关的开源项目,我们可 以采用Spring Cloud Sleuth+Zipkin来做链路追踪的解决方案。

**zipkin:**由Twitter公司开源,开放源代码分布式的跟踪系统, 用于收集服务的定时数据,以解决微服务架构中的延迟问题,包 括:数据的收集、存储、查找和展现。该产品结合 spring-cloud-sleuth 使用较为简单, 集成很方便, 但是功能较简单。

**pinpoint:**韩国人开源的基于字节码注入的调用链分析,以及 应用监控分析工具。特点是支持多种插件,UI功能强大,接入端 无代码侵入

**Skywalking:**SkyWalking是本土开源的基于字节码注入的调用 链分析,以及应用监控分析工具。特点是支持多种插件,UI功能 较强,接入端无代码侵入。目前已加入Apache孵化器。

认识SkyWalking

在这里插入图片描述

什么是SkyWalking

SkyWalking是开源的可观测平台,主要用于收集,分析,聚合和可 视化服务和云原生基础设施的数据。Skywalking提供了一种简单得 方式来维护分布式系统得视图关系。

在这里插入图片描述

SkyWalking

SkyWalking是开源的一款分布式追踪,分析,告警的工具,现已属 于Apache旗下开源项目, SkyWalking为服务提供了自动探针代理, 将数据通过gRPC或者HTTP传输给后端平台,后端平台将数据存储 在Storage中,并且分析数据将结果展示在UI中。

在这里插入图片描述

优点:

多种监控手段多语言自动探针,Java,.NET Core 和 Node.JS

轻量高效,不需要大数据

模块化,UI、存储、集群管理多种机制可选

支持告警

社区活跃

缺点:

较为新兴,成熟度不够高

SkyWalking核心概念

在这里插入图片描述

上部分 Agent :

负责从应用中,收集链路信息,发送给 SkyWalking OAP 服务器。目前支持 SkyWalking、Zikpin、Jaeger 等提供的 Tracing 数据信息。而我们目前采用的是, SkyWalking Agent 收集 SkyWalking Tracing 数据,传递给服务器。

下部分 SkyWalking OAP :

负责接收 Agent 发送的 Tracing 数据信息,然后进行分析 (Analysis Core) ,存储到外部存储器( Storage ),最终提供查询( Query )功能。

左部分 Storage :

Tracing 数据存储。目前支持 ES、MySQL、Sharding Sphere、TiDB、 H2 多种存储器。而我们目前采用的是 ES ,主要考虑是 SkyWalking 开发团队自己的生产环 境采用 ES 为主。

右部分 SkyWalking UI :

负责提供控台,查看链路等等。

什么是探针Java Agent

在这里插入图片描述

探针产生的背景

在开发过程中,开发人员经常会使用IDEA的Debug功能(包含本地 和远程)调试应用,在JVM进程期间获取应用运行的JVM信息,变量 信息等。这些个技术通过Java Agent来实现的,那么Java Agent到 底是啥,为啥这么吊?

哪里有Java Agent:

idea得Debug功能

热部署 JRebel

各种线上诊断工具

代码覆盖率工具

性能分析

什么是探针

Java Agent 又叫做 Java 探针,是在 JDK1.5 引入的一种可以动态修改 Java 字节码的技术。Java 类编译之后形成字节码被 JVM 执行, 在 JVM 在执行这些字节码之前获取这些字节码信息,并且通过字节 码转换器对这些字节码进行修改,来完成一些额外的功能。

Java探针工具技术原理

在这里插入图片描述

流程:

​ 在JVM加载class二进制文件的时候,利用ASM动态的修改加载的class文件,在监控的方法前 后添加计时器功能,用于计算监控方法耗时;

​ 将监控的相关方法 和 耗时及内部调用情况,按照顺序放入处理器;

​ 处理器利用栈先进后出的特点对方法调用先后顺序做处理,当一个请求处理结束后,将耗时 方法轨迹和入参map输出到文件中;

​ 然后区分出耗时的业务,转化为xml格式进行解析和分析。

Java探针日志监控实现

环境搭建

在这里插入图片描述

引入依赖
 <dependencies>
        <!--  springboot 依赖     -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>

        <!-- 测试依赖 -->
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
        </dependency>

编写HelloController
@RestController
public class HelloController {
   

    @GetMapping("/hello")
    public String hello() {
   
        return "hello java agent";
    }


}

打包SpringBoot项目

在这里插入图片描述

探针实现

如何使用Java Agent

JDK1.5引入了java.lang.instrument包,开发者可以很方便的实现字 节码增强。其核心功能由java.lang.instrument.Instrumentation接 口提供。

Instrumentation 有两种使用方式:

​ 在应用运行之前,通过premain()方法来实现,在应用启动时侵入并代理应用。

​ 在应用运行之后,通过调用Attach AP和agentmain()方法来实现

注意:

javassist是一个库,实现ClassFileTransformer接口中的 transform()方法。ClassFileTransformer 这个接口的目的就是 在class被装载到JVM之前将class字节码转换掉,从而达到动态 注入代码的目的。

新建Maven项目javaagentdemo

在这里插入图片描述

引入依赖
  <dependencies>
    <dependency>
      <groupId>org.javassist</groupId>
      <artifactId>javassist</artifactId>
      <version>3.22.0-GA</version>
    </dependency>
  </dependencies>

  <build>
    <finalName>agent</finalName>
    <plugins>
      <!--META-INF 下 MANIFEST.MF 文件 内容Manifest-Version: 1.0Premain-Class: com.jenson.TestAgent下面Maven插件可以自动实现-->
      <plugin>
        <groupId>org.apache.maven.plugins</groupId>
        <artifactId>maven-shade-plugin</artifactId>
        <version>3.0.0</version>
        <executions>
          <execution>
            <phase>package</phase>
            <goals>
              <goal>shade</goal>
            </goals>
            <configuration>
              <transformers>
                <transformer implementation="org.apache.maven.plugins.shade.resource.ManifestResourceTransformer">
                  <manifestEntries>
                    <Premain-Class>com.org.PreMainJavaAgent</Premain-Class>
                  </manifestEntries>
                </transformer>
              </transformers>
            </configuration>
          </execution>
        </executions>
      </plugin>
    </plugins>
  </build>
Maven插件引入失败

在IDEA中使用maven-shade-plugin插件时会提示"Plugin ‘mavenshade-plugin:’ not found"

解决方法:

File -> Setting -> Build, Execution, Deployment -> Build Tools -> Maven -> 勾选Use plugin

registry选项 File -> Invalidate Caches -> Invalidate and Restart

编写探针类TestAgent
public class PreMainJavaAgent {
   

    /**
     * 在main方法运行前,与main方法运行于同一JVM中
     *
     * @param agentArgs :agentArgs是premain函数得到的程序参数,随同"-javaagent"一同传入,
     *                  与main函数不同的是,该参数是一个字符串而不是一个字符串数组,
     *                  如果程序参数有多个,程序将自行解析这个字符串.
     * @param instrumentation :一个java.lang.instrument.Instrumentation实例,由JVM自动传入,
     *                        java.lang.instrument.Instrumentation是instrument包中的一个接口,
     *                        也是核心部分,集中了其中几乎所有的功能方法,例如类定义的转换和操作.
     */
    public static void premain(String agentArgs, Instrumentation instrumentation) {
   
        System.out.println("------------------ premain  -----------------------");
        instrumentation.addTransformer(new TestTransformer());
    }

编写TestTransformer
public class TestTransformer  implements ClassFileTransformer {
   

    //增强类
    private final String CLASSNAME="com.org.controller.HelloController";

    //增强方法
    private final String METHODNAME="hello";


    //这个接口的目的就是在class被装载到jvm之前将class字节码文件转换掉,从而达到动态注入代码的目的。
    @Override
    public byte[] transform(ClassLoader loader, String className, Class<?> classBeingRedefined, ProtectionDomain protectionDomain, byte[] classfileBuffer) throws IllegalClassFormatException {
   

        //输出模式:com/org/controller/HelloController
//        System.out.println("className = " + className);

        //将className 的格式转换成 idea中文件路径形式
        String finalClassName = className.replace("/", "."
  • 9
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值