【SkyWalking从入门到精通】第12篇:SkyWalking Agent高级配置:调教你的基因改造针
上一篇【第11篇】JavaAgent安装与配置:给应用植入可观测性的基因
下一篇【第13篇】Server部署详解:解读指挥中心的控制面板
上一篇我们把基因改造针(JavaAgent)成功植入了应用体内。但注射完成只是第一步——就像买了一辆跑车,只会点火启动可不够,你得学会调教引擎、调整悬挂、切换驾驶模式。
今天,我们就来深入Agent的高级配置:插件机制、采样率、异步追踪、上下文传播……这些参数决定了你的Agent是"见啥追踪啥"的莽夫,还是"精准高效"的忍者。
1. 插件机制详解
1.1 三种插件类型
SkyWalking Agent的插件分为三个阵营,就像基因改造液的三层药效:
┌──────────────────────────────────────────────────────────────────┐
│ Agent插件三层架构 │
│ │
│ ┌──────────────────────────────────────────────────────────┐ │
│ │ bootstrap-plugins/ (底层突变层) │ │
│ │ 拦截JDK内部类(如Thread/HttpURLConnection) │ │
│ │ 在JVM bootstrap classloader加载时生效 │ │
│ │ ── apm-jdk-thread-plugin.jar │ │
│ │ ── apm-jdk-http-plugin.jar │ │
│ └──────────────────────────────────────────────────────────┘ │
│ │ │
│ ┌──────────────────────────────────────────────────────────┐ │
│ │ plugins/ (基础能力层) │ │
│ │ 默认激活,覆盖主流框架 │ │
│ │ ── Spring/Tomcat/MySQL/Redis/Dubbo/Kafka... │ │
│ │ 约30+插件,开箱即用 │ │
│ └──────────────────────────────────────────────────────────┘ │
│ │ │
│ ┌──────────────────────────────────────────────────────────┐ │
│ │ optional-plugins/ (高级能力层) │ │
│ │ 按需激活,特殊框架或高级功能 │ │
│ │ ── Oracle/Jedis/Gateway/自定义增强... │ │
│ │ 约30+插件,手动启用 │ │
│ └──────────────────────────────────────────────────────────┘ │
└──────────────────────────────────────────────────────────────────┘
这三层插件各有不同的加载时机和适用范围:
bootstrap-plugins:这是最底层的插件,拦截的是JDK内部类。为什么单独分出来?因为JDK的核心类(如java.lang.Thread)是由Bootstrap ClassLoader加载的,普通插件无法触及这个层次。这些插件在Agent初始化的最早阶段就被加载,相当于给JVM的底层基因做了手术。
plugins:默认激活的插件,覆盖了大多数主流框架。只要你的应用用了Spring、Tomcat、MySQL这些常见技术栈,这些插件就会自动追踪。就像基因改造的基础套餐——你不需要主动选择,它就在那里。
optional-plugins:可选插件,需要手动激活。这些插件覆盖的是更特殊或更新兴的框架(如Oracle数据库、Spring Cloud Gateway),或者是一些有争议的功能(如自定义增强)。就像基因改造的高级套餐——需要你主动选择,按需激活。
1.2 插件激活与禁用
激活可选插件
激活optional-plugins非常简单——把jar包从optional-plugins/目录移到plugins/目录即可:
# 激活Spring Cloud Gateway插件
mv optional-plugins/apm-spring-cloud-gateway-2.x-plugin.jar plugins/
# 激活Oracle数据库插件
mv optional-plugins/apm-oracle-10.x-plugin.jar plugins/
# 激活自定义增强插件
mv optional-plugins/apm-customize-enhance-plugin.jar plugins/
# 激活多个插件(批量移动)
mv optional-plugins/apm-kafka-plugin.jar plugins/
mv optional-plugins/apm-jedis-2.x-4.x-plugin.jar plugins/
禁用默认插件
有时候你可能想禁用某个默认插件——比如你的应用不用MySQL,不需要追踪数据库调用;或者某个插件和你的代码有冲突。方法同样简单——把jar包从plugins/移到optional-plugins/:
# 禁用MySQL追踪插件
mv plugins/apm-mysql-5.x-plugin-8.x-plugin.jar optional-plugins/
# 禁用Tomcat追踪插件
mv plugins/apm-tomcat-7.x-8.x-9.x-plugin.jar optional-plugins/
插件冲突排查
当多个插件对同一个类进行增强时,可能会产生冲突。排查方法:
# 查看Agent日志中的插件加载信息
grep "plugin found" skywalking-agent/logs/skywalking-api.log
# 查看哪些类被哪些插件增强
grep "Enhance class" skywalking-agent/logs/skywalking-api.log
1.3 自定义增强插件
optional-plugins目录中有一个特殊的插件——apm-customize-enhance-plugin.jar,它允许你不用写Java代码就能追踪自定义方法。
激活后,在config/目录下创建customize-enhance.xml:
<?xml version="1.0" encoding="UTF-8"?>
<enhances>
<!-- 追踪指定类的指定方法 -->
<enhance class="com.mycompany.service.UserService" method="getUserById">
<operationName>UserService.getUserById</operationName>
</enhance>
<!-- 追踪带参数匹配的方法 -->
<enhance class="com.mycompany.service.OrderService" method="createOrder">
<operationName>OrderService.createOrder</operationName>
<include subClass="true"/> <!-- 包含子类 -->
</enhance>
<!-- 追踪所有匹配类名的public方法 -->
<enhance class="com.mycompany.controller.*Controller" method="*">
<operationName>Controller.${methodName}</operationName>
</enhance>
</enhances>
这个功能就像基因改造液的"自定义配方"——不需要开发新插件,只需要一个XML文件就能追踪任何方法。
2. 采样率配置
2.1 为什么需要采样
在生产环境中,如果每个请求都被完整追踪,会给OAP Server带来巨大的存储和计算压力。就像一个城市里的每一个行人都被DNA追踪——数据量太大了,系统会崩溃。
采样率就是控制"追踪多少比例的请求"的参数:
┌──────────────────────────────────────────────────────────┐
│ 采样率对数据量的影响 │
│ │
│ 100%采样 → 所有请求被追踪 → 数据量巨大 → 存储压力高 │
│ │
│ ┌───┬───┬───┬───┬───┬───┬───┬───┬───┬───┐ │
│ │ ✓ │ ✓ │ ✓ │ ✓ │ ✓ │ ✓ │ ✓ │ ✓ │ ✓ │ ✓ │ 全量 │
│ └───┴───┴───┴───┴───┴───┴───┴───┴───┴───┘ │
│ │
│ 10%采样 → 每10个请求追踪1个 → 数据量可控 → 存储友好 │
│ │
│ ┌───┬───┬───┬───┬───┬───┬───┬───┬───┬───┐ │
│ │ ✓ │ │ │ │ │ │ │ │ │ │ 采样 │
│ └───┴───┴───┴───┴───┴───┴───┴───┴───┴───┘ │
│ │
│ 关键:慢请求和错误请求会被强制追踪(不受采样率影响) │
└──────────────────────────────────────────────────────────┘
2.2 sampler配置参数
# agent.config
# 采样策略:基于3秒时间窗口内的采样数量
# 默认值为-1,表示不采样(全量追踪)
# 正整数N表示每3秒追踪N个请求
agent.sample_n_per_3_secs=${SW_AGENT_SAMPLE:N_PER_3_SECS:-1}
注意:这里的采样率不是百分比!它是一个每3秒的采样数量:
| 配置值 | 效果 |
|---|---|
| -1 | 全量追踪(默认) |
| 3 | 每3秒追踪3个请求 |
| 10 | 每3秒追踪10个请求 |
| 100 | 每3秒追踪100个请求 |
计算等效百分比需要知道你的请求QPS:
# 如果QPS=100,sample_n_per_3_secs=10
# 等效采样率 = 10 / (100 * 3) ≈ 3.3%
# 如果QPS=50,sample_n_per_3_secs=5
# 等效采样率 = 5 / (50 * 3) ≈ 3.3%
# 通用公式:
# 等效采样率 ≈ sample_n_per_3_secs / (QPS * 3)
2.3 采样率的注意事项
一个关键设计:采样率不影响慢请求和错误请求的追踪。无论采样率设置多低,SkyWalking都会强制追踪:
- 响应时间超过阈值的请求
- 出现异常/错误的请求
这就像基因改造液的智能模式——普通人按比例抽查,但可疑人物一律详细追踪。
# 慢请求阈值(毫秒),超过此值的请求强制追踪
trace.slow_threshold=${SW_TRACE_SLOW_THRESHOLD:-1}
# -1表示不强制追踪慢请求
# 正整数表示超过此毫秒数的请求强制追踪
2.4 不同场景的采样率建议
┌──────────────────────────────────────────────────────┐
│ 不同场景的采样率推荐 │
│ │
│ 开发/测试环境:-1(全量追踪) │
│ └───────────────────── 没有性能压力,数据全量分析 │
│ │
│ 低流量生产(QPS<50):-1或3 │
│ └───────────────────── 流量低,全量或轻微采样 │
│ │
│ 中流量生产(QPS 50-500):3-10 │
│ └───────────────────── 适度采样,保证核心数据 │
│ │
│ 高流量生产(QPS>500):10-50 │
│ └───────────────────── 重点采样,错误和慢请求不漏 │
│ │
│ 超高流量(QPS>5000):50-100 │
│ └───────────────────── 粗粒度采样,只追踪代表性请求 │
└──────────────────────────────────────────────────────┘
3. Agent日志配置
3.1 日志级别与含义
Agent有自己的日志系统(基于Log4j2),日志级别从低到高:
# agent.config
logging.level=${SW_LOGGING_LEVEL:INFO}
| 级别 | 输出内容 | 适用场景 |
|---|---|---|
| DEBUG | 所有调试信息,包括字节码增强细节 | 插件开发/排查问题 |
| INFO | 关键事件(启动/连接/采样) | 日常生产 |
| WARN | 潜在问题(连接超时/采样溢出) | 生产环境 |
| ERROR | 严重错误(Agent崩溃/数据丢失) | 所有环境 |
生产环境建议设为WARN或INFO。DEBUG级别会产生大量日志,仅在排查问题时临时启用。
3.2 日志文件管理
# agent.config
# 日志输出目录(空=Agent根目录/logs/)
logging.dir=${SW_LOGGING_DIR:}
# 日志文件名
logging.file_name=${SW_LOGGING_FILE_NAME:skywalking-api.log}
# 单个日志文件最大大小(字节),默认300MB
logging.max_file_size=${SW_LOGGING_MAX_FILE_SIZE:300000000}
# 最大日志文件数量,默认3个(轮转)
logging.max_file_num=${SW_LOGGING_MAX_FILE_NUM:3}
日志文件会自动轮转——当当前文件达到max_file_size时,会创建新文件,最多保留max_file_num个文件:
logs/
├── skywalking-api.log # 当前日志(正在写入)
├── skywalking-api.log.1 # 第一轮转文件
└── skywalking-api.log.2 # 第二轮转文件
│
│ 超过3个文件 → 最老的文件自动删除
│ skywalking-api.log → 满了 → 重命名为.1
│ 新的skywalking-api.log → 继续写入
3.3 将Agent日志输出到应用日志
有时你希望Agent日志和应用日志混在一起,方便统一查看。可以通过修改config/log4j2.xml实现:
<!-- 修改log4j2.xml,将Console appender设为异步 -->
<Configuration status="WARN">
<Appenders>
<Console name="Console" target="SYSTEM_OUT">
<PatternLayout pattern="%d %p %c - %m%n"/>
</Console>
<RollingFile name="RollingFile"
fileName="${sys:skywalking.log.dir}/${sys:skywalking.log.file.name}"
filePattern="${sys:skywalking.log.dir}/${sys:skywalking.log.file.name}.%i">
<PatternLayout pattern="%d %p %c - %m%n"/>
<SizeBasedTriggeringPolicy size="${sys:skywalking.log.max_file_size}"/>
<DefaultRolloverStrategy max="${sys:skywalking.log.max_file_num}"/>
</RollingFile>
</Appenders>
<Loggers>
<Root level="${sys:skywalking.log.level}">
<AppenderRef ref="Console"/> <!-- 输出到控制台 -->
<AppenderRef ref="RollingFile"/> <!-- 输出到文件 -->
</Root>
</Loggers>
</Configuration>
4. 高级特性
4.1 Ignore Suffix——忽略特定后缀的请求
有些URL后缀是静态资源请求,追踪它们毫无意义:
# agent.config
# 忽略追踪的URL后缀(逗号分隔)
trace.ignore_path=${SW_TRACE_IGNORE_PATH:.css,.js,.html,.jpg,.png,.gif,.ico,.svg,.woff,.woff2,.ttf,.eot}
这就像基因改造液忽略了所有"路人甲"——只追踪有意义的动作,忽略走马观花的闲逛。
配置后,这些请求不会产生任何Trace数据:
# 不追踪的请求示例:
GET /static/css/style.css → 忽略
GET /images/logo.png → 忽略
GET /scripts/app.js → 忽略
# 正常追踪的请求示例:
GET /api/users/123 → 追踪 ✓
POST /api/orders → 追踪 ✓
GET /health → 追踪 ✓(除非也加入忽略列表)
4.2 Correlation Context——跨进程上下文传播
有时候你需要在Trace中传播自定义的业务数据(如用户ID、订单号),SkyWalking提供了Correlation Context机制:
// 在代码中设置自定义上下文
import org.apache.skywalking.apm.toolkit.trace.TraceContext;
// 设置跨进程传播的上下文数据(最多3个键值对)
TraceContext.putCorrelation("userId", "user-12345");
TraceContext.putCorrelation("orderId", "order-67890");
// 在下游服务中获取
String userId = TraceContext.getCorrelation("userId");
String orderId = TraceContext.getCorrelation("orderId");
配置参数:
# agent.config
# Correlation Context最大数据量(最多传播几个键值对)
correlation.max=${SW_CORRELATION_MAX:3}
# 单个值的最大长度(字符数)
correlation.value_max_length=${SW_CORRELATION_VALUE_MAX_LENGTH:128}
这就像基因改造后超级英雄之间的加密通讯——通过Trace链路传播的业务信息,只有同一条追踪链上的服务才能读取。
4.3 异步追踪
在微服务中,异步处理非常常见——CompletableFuture、@Async、Reactive编程。追踪异步调用是APM领域最棘手的问题之一,就像追踪一个会瞬移的超级英雄——他消失了又出现在另一个地方,你怎么把前后联系起来?
SkyWalking的解决方案是异步Span:
import org.apache.skywalking.apm.toolkit.trace.ActiveSpan;
import org.apache.skywalking.apm.toolkit.trace.TraceContext;
// 方式一:使用@Trace注解标记异步方法
@Trace
@Async
public void asyncProcessOrder(Order order) {
// 这个异步方法会被自动追踪
ActiveSpan.setTag("orderId", order.getId());
}
// 方式二:手动创建异步Span
public void processAsync() {
// 获取当前Trace的SegmentRef
Runnable task = TraceContext.capture(); // 捕获当前上下文
CompletableFuture.runAsync(() -> {
TraceContext.continue(task); // 在异步线程中恢复上下文
try {
// 异步处理逻辑...
doSomething();
} finally {
TraceContext.stop(); // 结束异步Span
}
});
}
异步追踪的原理图:
┌──────────────────────────────────────────────────────────────────┐
│ 异步追踪上下文传播原理 │
│ │
│ 主线程: ┌─────SpanA─────┐ │
│ │ │ capture() → 保存上下文快照 │
│ │ ┌──────────┼─────────────────────┐ │
│ └────┘ │ │ │
│ │ 异步线程 │ │
│ │ continue() → 恢复 │ │
│ │ ┌───SpanB──────┐ │ │
│ │ │ 异步处理 │ │ │
│ │ │ stop()→结束 │ │ │
│ │ └──────────────┘ │ │
│ └─────────────────────┘ │
│ │
│ SpanA和SpanB属于同一个Trace,通过上下文快照关联 │
└──────────────────────────────────────────────────────────────────┘
4.4 Trace Limit——Span数量限制
一个Trace可能包含很多Span,但无限增长会导致数据膨胀:
# agent.config
# 单个Trace的最大Span数量
trace.limit=${SW_TRACE_LIMIT:500}
# 超过限制后,新Span会被丢弃(但Trace不会截断)
# 默认500,对于大多数场景足够
如果你的业务链路特别深(比如一个请求要调用20+个下游服务),可能需要调大这个值。
4.5 Force Trace——强制追踪条件
你可以配置在特定条件下强制追踪,不受采样率影响:
# agent.config
# 慢请求阈值(毫秒),超过此值的请求强制追踪
# -1 = 不强制追踪慢请求
trace.slow_threshold=${SW_TRACE_SLOW_THRESHOLD:-1}
不同服务可以设置不同的阈值——对核心业务设置严格的阈值,对非核心业务放宽:
# 核心支付服务:200ms就算慢
export SW_TRACE_SLOW_THRESHOLD=200
# 用户服务:500ms才算慢
export SW_TRACE_SLOW_THRESHOLD=500
5. 插件开发简介
如果内置插件和自定义增强插件都不够,你可以开发自己的Agent插件。SkyWalking提供了完整的插件开发框架:
┌──────────────────────────────────────────────────────────────────┐
│ Agent插件开发核心概念 │
│ │
│ 1. ClassMatch:定义要拦截哪些类 │
│ ── NameMatch:精确匹配类名 │
│ ── PrefixMatch:前缀匹配 │
│ ── RegexMatch:正则匹配 │
│ ── AnnotationMatch:注解匹配 │
│ │
│ 2. InstanceMethodIntercept:拦截实例方法 │
│ ── beforeMethod:方法执行前 │
│ ── afterMethod:方法执行后 │
│ ── handleMethodException:方法异常时 │
│ │
│ 3. StaticMethodIntercept:拦截静态方法 │
│ ── 同上三个拦截点 │
│ │
│ 4. EnhanceTemplate:将ClassMatch和Intercept组合 │
│ ── 定义拦截规则和拦截逻辑 │
│ │
│ 完整开发流程在后续文章(053+)中详解 │
└──────────────────────────────────────────────────────────────────┘
6. 配置速查表
把所有高级配置参数整理在一起,方便快速查阅:
# ==================== 采样配置 ====================
agent.sample_n_per_3_secs=${SW_AGENT_SAMPLE:N_PER_3_SECS:-1}
trace.slow_threshold=${SW_TRACE_SLOW_THRESHOLD:-1}
trace.limit=${SW_TRACE_LIMIT:500}
# ==================== 忽略配置 ====================
trace.ignore_path=${SW_TRACE_IGNORE_PATH:.css,.js,.html,.jpg,.png}
trace.operation_name_length_limit=${SW_TRACE_OPERATION_NAME_LENGTH_LIMIT:500}
# ==================== 上下文配置 ====================
correlation.max=${SW_CORRELATION_MAX:3}
correlation.value_max_length=${SW_CORRELATION_VALUE_MAX_LENGTH:128}
# ==================== 日志配置 ====================
logging.level=${SW_LOGGING_LEVEL:INFO}
logging.dir=${SW_LOGGING_DIR:}
logging.file_name=${SW_LOGGING_FILE_NAME:skywalking-api.log}
logging.max_file_size=${SW_LOGGING_MAX_FILE_SIZE:300000000}
logging.max_file_num=${SW_LOGGING_MAX_FILE_NUM:3}
# ==================== 网络配置 ====================
collector.grpc.max_message_size=${SW_COLLECTOR_GRPC_MAX_MESSAGE_SIZE:10485760}
collector.grpc.timeout=${SW_COLLECTOR_GRPC_TIMEOUT:30}
7. 小结
Agent的高级配置就像调教基因改造针的精度:
- 插件三层架构:bootstrap(底层突变)、plugins(基础能力)、optional-plugins(高级能力)
- 采样率:不是百分比,是每3秒追踪N个请求;慢请求和错误不受采样限制
- 日志管理:WARN级别适合生产,自动轮转管理
- 高级特性:ignore suffix过滤噪音、correlation context传播业务数据、异步追踪串联瞬移英雄
- 自定义增强:XML配置即可追踪任意方法,无需开发插件
下一篇文章,我们将从Agent端转向OAP Server端——解读后端的部署与配置。基因改造针已经调教完毕,接下来要看看指挥中心的运作方式。
上一篇【第11篇】JavaAgent安装与配置:给应用植入可观测性的基因
下一篇【第13篇】Server部署详解:解读指挥中心的控制面板
更多推荐




所有评论(0)