skywalking 请求链路采样设置和原理

目标

skywalking 默认情况会采集大量 trace 数据,这样可以比较全的追踪所有请求调用链路的请求,但同时对 ES 存储资源要求非常高,需要我们投入很大的存储节点才可以。那么有没有一种采样的请求上报的机制呢?答案是有的,通过设置采样数据的比例,我们就可以在资源成本和采集条目之前取得一个平衡。

现状

日常排查问题的现实情况往往是,我们只需要能采集到出现问题的请求链路即可,而不需要能够采集所有请求的链路数据,在加了采样条目设置后,有一部分 trace 数据会被丢掉,当然如果正好丢掉了我们出问题的 trace 请求,那么就需要我们稳定复现请求,从而控制概率采集到该问题数据。

skywalking 里面配置采样条目

在 skwalking 的 agent 目录下的 agent.conf 文件有采样参数的设置 sample_n_per_3_secs,默认情况下该值 是 0 或者 -1 的情况下是关闭采样功能,如果大于 0,则代表agent 3 秒内采集多少条数据上报 oap

agent.sample_n_per_3_secs=${SW_AGENT_SAMPLE:40}

注意:该值的修改需要每次进行 agent 打包后生效

采样功能的原理分析

SamplingService 类里面的 handleSamplingRateChanged 方案,会启动一个线程,每隔 3 秒定时重置采样值的计数器:

void handleSamplingRateChanged() {
    if (getSamplingRate() > 0) {
        if (!on) {
            on = true;
            this.resetSamplingFactor();
            ScheduledExecutorService service = Executors.newSingleThreadScheduledExecutor(
                new DefaultNamedThreadFactory("SamplingService"));
            scheduledFuture = service.scheduleAtFixedRate(new RunnableWithExceptionProtection(
                this::resetSamplingFactor, t -> LOGGER.error("unexpected exception.", t)), 0, 3, TimeUnit.SECONDS);
            LOGGER.debug(
                "Agent sampling mechanism started. Sample {} traces in 3 seconds.",
                getSamplingRate()
            );
        }
    } else {
        if (on) {
            if (scheduledFuture != null) {
                scheduledFuture.cancel(true);
            }
            on = false;
        }
    }
}

计数器采用 java 并发包下面的原子类计数,从而确保多线程环境下该值的并发更新问题:

    private void resetSamplingFactor() {
        samplingFactorHolder = new AtomicInteger(0);
    }

然后提供了一个方法,用于判断是否到达采样阈值:

    public boolean trySampling(String operationName) {
        if (on) {
            int factor = samplingFactorHolder.get();
            if (factor < getSamplingRate()) {
                return samplingFactorHolder.compareAndSet(factor, factor + 1);
            } else {
                return false;
            }
        }
        return true;
    }

在这个方法里面可以看到,如果原子类 AtomicInteger 实例的 get 方法的值小于阈值,然后就进行一次 CAS 更新操作,当 CAS 成功时代表该 trace context 数据允许上报 oap,否则就代表达到了采样阈值,该 trace context 数据丢弃。

上报还是不上报的逻辑在 ContextManagerExtendService 类的 createTraceContext 方法中可以找到:

 public AbstractTracerContext createTraceContext(String operationName, boolean forceSampling) {
        AbstractTracerContext context;
        /*
         * Don't trace anything if the backend is not available.
         */
        if (!Config.Agent.KEEP_TRACING && GRPCChannelStatus.DISCONNECT.equals(status)) {
            return new IgnoredTracerContext();
        }

        int suffixIdx = operationName.lastIndexOf(".");
        if (suffixIdx > -1 && Arrays.stream(ignoreSuffixArray).anyMatch(a -> a.equals(operationName.substring(suffixIdx)))) {
            context = new IgnoredTracerContext();
        } else {
            SamplingService samplingService = ServiceManager.INSTANCE.findService(SamplingService.class);
            //如果该条打上了强制采样标签 或 满足满足采样条件就可以直接上报 oap
            if (forceSampling || samplingService.trySampling(operationName)) {
                context = new TracingContext(operationName);
            } else {
                //否则就忽略该次 trace context, 不做任何处理
                context = new IgnoredTracerContext();
            }
        }

        return context;
    }
总结

通过合理的 skywalking 的采样机制的设置,可以大大减轻服务端 ES 的存储压力,以及减少 agent 端消耗应用的的 cpu 和内存的资源,也包括减少上报 oap 网络带宽的占用等,从而达到在资源成本和采集请求覆盖面得到一个平衡

参考

Table of Agent Configuration Properties | Apache SkyWalking

SkyWalking 是一个开源的应用程序性能监控(APM)工具,专门用于分布式系统的监控故障排查。链路监控是 SkyWalking 的核心功能之一,通过它可以追踪分析分布式系统中的请求路径。链路监控的粒度设置对于监控的详细程度性能影响至关重要。 ### SkyWalking 链路监控粒度设置 1. **采样率设置**: 采样率决定了在所有请求中,有多少请求会被监控。采样率过高会导致性能开销过大,过低则可能错过重要信息。可以通过配置文件或管理界面设置采样率。 ```yaml # application.yml skywalking: agent: sampling: rate: 1000 # 每1000个请求采样1个 ``` 2. **追踪深度设置**: 追踪深度指的是在一个请求链中,追踪的深度层级。深度越高,监控的细节越多,但性能开销也越大。可以通过配置文件设置追踪深度。 ```yaml # application.yml skywalking: agent: trace: max_depth: 20 # 最大追踪深度为20 ``` 3. **忽略特定请求**: 有些请求可能不需要监控,可以通过配置忽略这些请求,减少不必要的性能开销。 ```yaml # application.yml skywalking: agent: ignore_suffix: - .jpg - .css - .js ``` 4. **自定义链路追踪**: 在某些情况下,可能需要自定义链路追踪逻辑,以便更精细地控制监控行为。可以通过编写自定义插件或使用 SkyWalking 提供的 API 来实现。 ```java // 示例代码:自定义链路追踪 import org.apache.skywalking.apm.toolkit.trace.Trace; import org.apache.skywalking.apm.toolkit.trace.TraceContext; public class MyService { @Trace public void myMethod() { // 方法实现 String traceId = TraceContext.traceId(); // 使用 traceId 进行日志记录或其他操作 } } ``` ### 总结 SkyWalking 提供了多种方式来设置链路监控的粒度,包括采样率、追踪深度、忽略特定请求自定义链路追踪等。通过合理配置这些参数,可以在保证性能的前提下,获取到足够详细的监控数据。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值