源码角度了解Skywalking之Trace信息的采样
源码角度了解Skywalking之Trace信息的采样
一条请求链路产生那么多trace信息,skywalking是每条trace都进行采集吗?显然不是,这就涉及到skywalking的采样了,我们看一下SKywalking是怎么对Trace信息进行采样的
采样
采样涉及到的类是SamplingService,在上篇文章中我们分析ContextManager的createEntrySpan()方法创建EntrySpan的过程中,调用了SamplingService的forceSampled()方法进行采样,具体就是samplingFactorHolder属性进行加1操作,记录采样次数。
SamplingService同样是BootService的实现类,它负责如何对 TraceSegment进行采样。每个 TraceSegment 都已被跟踪,但考虑到序列化反序列化的 CPU 成本和网络带宽问题,如果采样开启,代理不会将它们全部发送到收集器。
采样是在Config的Agent的SAMPLE_N_PER_3_SECS参数值,它表示在 3 秒内采样数,默认情况下,负数或零表示关闭。
定时重置采样次数
SamplingService的boot()方法:
public void boot() throws Throwable {
if (scheduledFuture != null) {
scheduledFuture.cancel(true);
}
if (Config.Agent.SAMPLE_N_PER_3_SECS > 0) {
on = true;
this.resetSamplingFactor();
ScheduledExecutorService service = Executors
.newSingleThreadScheduledExecutor(new DefaultNamedThreadFactory("SamplingService"));
scheduledFuture = service.scheduleAtFixedRate(new RunnableWithExceptionProtection(new Runnable() {
@Override
public void run() {
resetSamplingFactor();
}
}, new RunnableWithExceptionProtection.CallbackWhenException() {
@Override public void handle(Throwable t) {
logger.error("unexpected exception.", t);
}
}), 0, 3, TimeUnit.SECONDS);
logger.debug("Agent sampling mechanism started. Sample {} traces in 3 seconds.", Config.Agent.SAMPLE_N_PER_3_SECS);
}
}
- 如果boot()方法被调用了两次,就取消旧的那一个,这种情况主要在测试用例中出现
- 先重置采样次数,判断如果配置的SAMPLE_N_PER_3_SECS参数大于0,表示开启了采样,把on设置为true,创建定时线程池,每3s重置采样次数,创建RunnableWithExceptionProtection实例线程,线程调用resetSamplingFactor()方法重置采用次数
ContextManager在创建Span的过程中需要获取TraceContext对象,调用了ContextManagerExtendService的createTraceContext()方法来创建TraceContext,如果是强制采样或者调用trySampling()进行判断可以进行采样,就创建TracingContext对象,否则调用IgnoredTracerContext对象
是否可以采样
看一下SamplingService的trySampling()方法:
public boolean trySampling() {
if (on) {
int factor = samplingFactorHolder.get();
if (factor < Config.Agent.SAMPLE_N_PER_3_SECS) {
boolean success = samplingFactorHolder.compareAndSet(factor, factor + 1);
return success;
} else {
return false;
}
}
return true;
}
SamplingService的trySampling()方法主要是如果采样机制开启,判断是否可以成功获取默认采样因子,具体这里samplingFactorHolder属性值与Config.Agent.SAMPLE_N_PER_3_SECS配置类中设置的值进行比较如果,如果比它小就可以进行采样,返回true
强制采样
SamplingService的forceSampled()方法进行强制采样
public void forceSampled() {
if (on) {
samplingFactorHolder.incrementAndGet();
}
}
逻辑比较简答,就是如果开启采样了,对采样次数进行加1操作。
总结
这篇文章主要分析了Skywalking是怎么trace信息的采样,不能每个trace信息我们都进行采集,因为会增加网络带宽,给服务造成压力,因此我们可以通过Config.Agent.SAMPLE_N_PER_3_SECS参数来配置3s内采样的次数,SamplingService是实现采样的类,它提供forceSampled()方法强制采样,提供trySampling()方法判断是否可以采用,最重要的是它的boot()方法,维护了一个定时线程池,每3s对采用次数清零,方便下次采样。
- 点赞
- 收藏
- 关注作者
评论(0)