基于 Skywalking 根因分析设计与实现

微服务架构在独立部署、快速交付和灵活扩展上表现出极大的优势,但也会带来新的问题。服务间的调用关系变得异常复杂。当微服务架构出现系统性风险时,排查风险和故障诊断相比于传统的项目会更加困难。根因分析就是跟据服务和端点调用指标快速定位微服务应用问题的一种方法。

要解决的问题

目前针对单台实例,我们已经有了灵犀诊断通过分析应用的堆、栈信息来快速分析实例问题,但随着微服务应用越来越多,服务间调用越来越复杂,如何快速定位到实例或者服务维度为题成为一个亟需解决的问题。

概念

image-20220830162456964

根据上图可以了解到一个应用除了本地调用之外、还会有远程调用(DB、Redis、HTTP、MQ等),而HTTP、DUBBO远程调用又会关联到服务端应用,基于这样的关系,一个完整的微服务调用链路就可以串联起来,我们就可以根据这些关系去做根因分析。

为了解决实现根因分析,我们需要掌握以下一些概念:

入口端点

一个业务服务处理事务入口成为入口端点

  • HTTP/Dubbo
  • MQ 消费处理入口(包含Kafka,RocketMQ,RabbitMQ)
  • 调度 Job 入口(调度系统,Spring Task,ScheduledThreadPoolExecutor等等)

出口端点

每个入口端点都包含本地操作(Local)以及远程操作,远程操作对应的即为出口端点

  • HTTP / Dubbo 调用出口
  • MQ 消息发送出口(包含Kafka,RocketMQ,RabbitMQ)
  • 数据库读写调用出口(包含MySQL, MongoDB,Redis,Elasticsearch,HBase等等)

指标

  • 应用所有入口端点的【耗时】和【成功率】
  • 每个入口端点之后的每种操作的【耗时】和【成功率】

指标收集

指标类型

基于skywalking上报的segment数据,我们可以很轻易的获取到上述入口端点、出口端点、Local的指标数据

简单抽象成如下几种类型:

指标名 labels
入口 rca_entry_duration、rca_entry_error_rate service:服务、entry:入口端点
Dubbo rca_exit_dubbo_duration、rca_exit_dubbo_error_rate entry: 入口端点、exit:出口端点
HTTP rca_exit_http_duration、rca_exit_http_error_rate entry: 入口端点、address:远程地址
MySQL rca_exit_mysql_duration、rca_exit_mysql_error_rate entry: 入口端点、address:远程地址
MongoDB rca_exit_mongodb_duration、rca_exit_mongodb_error_rate entry: 入口端点、address:远程地址
Hbase rca_exit_hbase_duration、rca_exit_hbase_error_rate entry: 入口端点、address:远程地址
Elasticsearch rca_exit_es_duration、rca_exit_es_error_rate entry: 入口端点、address:远程地址
RocketMQ rca_exit_rocketmq_duration、rca_exit_rocketmq_error_rate entry: 入口端点、address:远程地址
RabbitMQ rca_exit_rabbitmq_duration、rca_exit_rabbitmq_error_rate entry: 入口端点、address:远程地址
Kafka rca_exit_kafka_duration、rca_exit_kafka_error_rate entry: 入口端点、address:远程地址

端点格式调整

1
com.qihoo.xxxFacade.xxxMethod --> demo-app.xxxFacade.xxxMethod
  • 通过端点即可知道是哪个服务,减少指标label

  • 与CAT数据格式保持一致,方便后续与CAT打通

指标收集架构图

由于要对skywalking数据二次处理,同时又要保证skywalking能正常运行、因此采用流量复制方案,一份流量打到skywalking-oap、一份到skywalking-bridge(自建bridge)。

image-20220830163208808

  1. 客户端skywalking-agent通过grpc上报segment数据到skywalking-gateway(Nginx)
  2. Nginx拦截segment流量转发到skywalking-bridge,其他流量依旧到skywalking-oap
  3. skywalking-bridge通过kafka转发segment数据到skywalking-oap,以保证skywalking正常运行
  4. skywalking-bridge通过kafka转发segment数据到flink进行流式处理,flink会把解析segment数据为span并按分钟进行聚合处理生成指标数据
  5. flink处理生成的指标数据通过kafka转发到skywalking-bridge
  6. skywalking-bridge把指标数据保存到VictoraMetric时序数据库中
  7. lingxi-diagnotor从VictoraMetric中获取数据进行根因分析

根因分析

方案

我们如何知道一个服务有问题,通常情况下需要看监控大盘,观看上面的指标是否有抖动,耗时是否增加、成功率是否上升等。

什么叫抖动?某个服务耗时 500ms,某个 RPC 环节耗时 250ms,那么这个 RPC 环节一定是有问题的吗?不一定,必须要跟它正常情况进行一个对比才能知道它的这个耗时是否正常。所以需要一个正常水准,然后基于正常水准的对比才能确定某个环节是否抖动了。

所以我们方案的前提就是:

需要有准确的异常开始时间,异常开始前一段时间范围要正常,基于前一段时间抖动程度来判定识别后一半时间范围的抖动是否为异常抖动

然而不通应用不同端点耗时、成功率都有所不同,1ms->3ms上升200%,100ms->200ms上升100%,两组数据哪个有问题呢,可能后者问题更大。那么环比正常数据什么样的阈值才是有问题的,我们不可能针对每个应用每个端点去设置阈值,需要一个能够评判的标准,标准差应运而生。

  • 方差是在概率论和统计方差衡量随机变量或一组数据时离散程度的度量。是每个样本值与全体样本值的平均数之差的平方值的平均数。
  • **标准差(Standard Deviation) **是离均差平方的算术平均数(即:方差)的算术平方根,用σ表示。标准差也被称为标准偏差,或者实验标准差,在概率统计中最常使用作为统计分布程度上的测量依据。

方差和标准差都是对一组(一维)数据进行统计的,反映的是一维数组的离散程度。

标准差和均值的量纲(单位)是一致的,在描述一个波动范围是标准差比方差更方便。比如一个班男生的平均身高是170cm,标准差是10cm,那么方差就是10cm^2。可以进行的比较简便的描述是本班男生身高分布是170±10cm,方差就无法做到这点。

实现逻辑

image-20220830163352915

  1. 计算入口端点前一个小时(可配置)正常数据的标准差A1,要分析时间范围的目标数据标准差A2
  2. 当A2是A1的3倍还多时(可配置),则认为端点抖动,可能有异常,下钻分析Local、Dubbo、Mysql、Redis指标
    • 耗时:当目标数据最大值<正常数据平均值+A1,则过滤掉(去除向下波动数据)
    • 失败率:当目标数据最小值<正常数据平局值+A1,则过滤掉(去除向下波动数据)
  3. 计算下钻指标前一个小时(可配置)正常数g准的标准差B1,和要分析时间范围的目标数据标准差B2
  4. 当B2是B1的3倍还多时(可配置),则认为指标波动,可能有异常
  5. 当指标为Dubbo是,记录客户端端点,继续递归分析

流程图

image-20220830163244919

后续工作

  • 考虑接入CAT,丰富指标,增加准确性

  • 考虑接入GC、CPU、Memory等指标,当分析出Local问题时能够精确给出因为什么原因导致

  • Metrics和调用链查询联动

参考

  1. https://my.oschina.net/pingpangkuangmo/blog/4334872
  2. https://zhuanlan.zhihu.com/p/407298025

基于 Skywalking 根因分析设计与实现
https://zhengshuoo.github.io/posts/011-root-cause-analyze
作者
zhengshuo
发布于
2022年8月28日
许可协议