Skywalking系列学习之agent收集trace数据

本文详细探讨了SkyWalking如何通过Java代理和ByteBuddy进行类增强,以收集trace数据。在方法前后添加拦截处理,创建EntrySpan和ExitSpan来跟踪服务调用。EntrySpan用于服务提供者,而ExitSpan在HTTP请求时被创建。在方法执行前后,SkyWalking管理TracingContext,存储trace信息,并通过ConsumerThread处理并传输给Server端。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

前言

  在上篇文章《SkyWalking系列学习之环境搭建以及分析如何类增强》中已经知道业务系统通过-javaagent引入代理,通过ByteBuddy对指定的类做增强处理。下面介绍Skywalking-Java怎样收集trace数据

实例方法增强入口InstMethodsInter#intercept

  1. 在入口打上条件断点,准确分析Skywalking-Java怎样收集trace数据
    在这里插入图片描述
  2. 分析InstMethodsInter#intercept整体结构发现,就是在原有方法前后做了拦截处理(重点)
    在这里插入图片描述

InstMethodsInter前置处理

	public void beforeMethod(EnhancedInstance objInst, Method method, Object[] allArguments, Class<?>[] argumentsTypes,
                             MethodInterceptResult result) throws Throwable {
         // 构建操作名,例如发送get请求 --> GET:/demo/hello                    
    	String operationName = this.buildOperationName(method, httpServletRequest.getMethod(),
                                                                   (EnhanceRequireObjectCache) objInst.getSkyWalkingDynamicField());
        // 创建EntrySpan                                                          
        AbstractSpan span = ContextManager.createEntrySpan(operationName, contextCarrier);        
        //为EntrySpan打url的tag
        Tags.URL.set(span, httpServletRequest.getRequestURL().toString());
        //为EntrySpan打http.method的tag
        Tags.HTTP.METHOD.set(span, httpServletRequest.getMethod());
                                                  
    }                         
  1. 在执行业务方法前,
    1.1 创建TracingContext,并初始化segment属性
    1.2 创建EntrySpan,放入activeSpanStack有序队列中。
  2. 业务方法内执行http远程请求前,创建ExitSpan,放入activeSpanStack有序队列中。执行完后从activeSpanStack取出
  3. 整个业务方法执行完后,将trace信息存入buffer中

创建EntrySpan

  1. EntrySpan是入口Span,用于服务提供者(Service Provider) ,例如Tomcat
    在这里插入图片描述
  2. Agent 会在Tomcat 定义的方法切面,创建 EntrySpan对象,也会在SpringMVC定义的方法切面,创建EntrySpan对象
    2.1 Agent只会在第一个方法切面,生成 EntrySpan 对象,第二个方法切面,栈深度+ 1(通过这样的方式,保持一个 TraceSegment 有且仅有一个 EntrySpan 对象)
    在这里插入图片描述

创建ExitSpan

  1. 在业务方法中发起http请求,执行httpClient.execute(httpGet)时会被HttpClientExecuteInterceptor拦截
    public void beforeMethod(EnhancedInstance objInst, Method method, Object[] allArguments, Class<?>[] argumentsTypes,
                             MethodInterceptResult result) throws Throwable {
            // operationName = /v1.0/menu/viewCount                 
            String operationName = requestURI;
            // 创建ExitSpan
            AbstractSpan span = ContextManager.createExitSpan(operationName, contextCarrier, remotePeer);
        
     }
    
  2. 创建ExitSpan,设置parentSpanId为activeSpanStack的最后一个span,并将ExitSpan放入activeSpanStack队列最后
    在这里插入图片描述

InstMethodsInter后置处理

  1. 通过ContextManager#stopSpan停止链路追踪,最终在创建EntrySpan地方完全终止(例如tomcat)
    1.1 如果stackDepth-1为0表示已经完成,将该span添加到TraceSegment中,并从队列StackBasedTracingSpan里弹出
    // TracingContext
     public boolean stopSpan(AbstractSpan span) {
        AbstractSpan lastSpan = peek();
        if (lastSpan == span) {
            if (lastSpan instanceof AbstractTracingSpan) {
                AbstractTracingSpan toFinishSpan = (AbstractTracingSpan) lastSpan;
               // 判断EntrySpan的stackDepth-1后是否为0,是则将该span添加到TraceSegment中
                if (toFinishSpan.finish(segment)) {
                   // 从队列里弹出 --> StackBasedTracingSpan#finish
                    pop();
                }
            } else {
                pop();
            }
        } else {
            throw new IllegalStateException("Stopping the unexpected span = " + span);
        }
    	// 如果结束则trace线程记录在buffer中
        finish();
        return activeSpanStack.isEmpty();
    }
    
  2. TraceSegmentServiceClient记录traceSegment,并存储在buffer中
    在这里插入图片描述

ConsumerThread线程处理TraceSegment

  1. ConsumerThread线程拉去buffer数据,让TraceSegmentServiceClient消费处理
     private boolean consume(List<T> consumeList) {
          for (DataSource dataSource : dataSources) {
          		// 从buffer中读取数据存放在consumeList中
               dataSource.obtain(consumeList);
           }
    
           if (!consumeList.isEmpty()) {
               try {
               		// 消费者消费数据
                   consumer.consume(consumeList);
               } catch (Throwable t) {
                   consumer.onError(consumeList, t);
               } finally {
                   consumeList.clear();
               }
               return true;
           }
           consumer.nothingToConsume();
           return false;
    }
    
  2. 将TraceSegment转换为SegmentObject,通过grpc传输给Server端
    在这里插入图片描述

束语

  本篇文章通过业务方法内发起http调用示例来debug SkyWalking的链路是如何形成以及怎样传递Server端。后续会分析Server端如何处理SegmentObject

### SkyWalking Agent 使用指南与配置 #### 关于 SkyWalking Java Agent 的基本概念 Apache SkyWalking 是一款开源的应用性能监控 (APM) 工具,支持分布式系统的追踪、指标收集以及服务拓扑展示等功能。其核心组件之一是 **Java Agent**,它通过字节码增强技术实现对应用的无侵入式监控[^1]。 --- #### 下载 SkyWalking Agent 要使用 SkyWalking Java Agent,需先从官方渠道下载对应的版本。以下是获取方式: - 访问 Apache SkyWalking 官方网站或 GitHub 发布页面,找到最新发布的二进制包。 - 下载链接通常位于 [Releases 页面](https://github.com/apache/skywalking/releases),选择适合的操作系统架构并解压即可获得 `skywalking-agent` 文件夹[^4]。 --- #### 配置 SkyWalking Agent SkyWalking Agent 的主要配置文件为 `agent.config` 或者 YAML 格式的 `application.yml`,具体取决于安装路径和使用的版本。以下是一些常见的配置项说明: 1. **OAP Server 地址** 设置 OAP(Observability Analysis Platform)服务器地址以便数据上报: ```properties collector.backend_service=${SW_BACKEND_SERVICE:localhost:11800} ``` 2. **采样率** 控制 Trace 数据的采集频率,减少网络流量开销: ```properties trace.sample_rate=1.0 ``` 3. **插件启用** 开启特定协议的支持(如 HTTP、Dubbo 等),默认情况下部分插件可能未激活: ```yaml plugins: - name: httpclient enabled: true ``` 上述配置可以通过编辑 `${SKYWALKING_AGENT_HOME}/config/application.yml` 实现。 --- #### 启动参数设置 为了使 SkyWalking Java Agent 生效,在启动目标 JVM 应用程序时需要加入 `-javaagent` 参数。例如: ```bash -javaagent:/path/to/skywalking/agent/skywalking-agent.jar ``` 此命令会加载指定目录下的 SkyWalking Agent 并按照预设规则拦截业务逻辑中的方法调用链路信息。 --- #### 自定义 Plugin 开发流程简介 如果现有 Plugins 不满足需求,则可以尝试扩展功能。这一步骤涉及源代码编译环境搭建及相关依赖管理工具 Maven 的熟练运用。操作概览如下所示: 1. 克隆仓库到本地机器; 2. 执行构建脚本完成初始化工作流; 3. 修改对应模块内的类描述符匹配表达式以适配新的框架特性[^3]。 注意:自定义开发前建议仔细阅读官方文档中关于 Instrumentation API 的讲解材料。 --- #### Kong 插件专项指导 针对网关场景下如何集成 SkyWalking 监控体系,《引用[2]》提供了详细的 Kong Agent 安装教程。简单来说就是克隆 GitCode 上托管的镜像库副本之后参照 README.md 中列举出来的步骤逐一执行下去直至成功部署完毕为止[^2]。 ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值