APM和SkyWalking小记

APM

APM,Application Performance Management,应用性能管理系统。是对企业的应用系统进行实时监控,实现对应用性能管理和故障定位的系统化解决方案。开源产品:美团的 CAT、Twitter 的 Zipkin,韩国开源的 Pinpoint 和国人开源的 SkyWalking 等。大多数会自研,如阿里的鹰眼,Google 的 Dapper 等。

  • CAT:基于 Java 语言开发,目前支持 Java、C/C++、Nodejs、Python、Go 等语言的客户端,监控数据会全量统计。主要用户:美团点评、携程、拼多多等。CAT 需要开发人员手动在应用程序中埋点,对代码侵入性比较强;
  • Zipkin:基于 Java 语言开发。侵入性相对于 CAT 要低一点,需要对 web.xml 等相关配置文件进行修改,但依然对系统有一定的侵入性。Zipkin 可以轻松与 Spring Cloud 进行集成,也是 Spring Cloud 推荐的 APM 系统。
  • PinPoint:运用了字节码增强技术,只需要在启动时添加启动参数即可实现 APM 功能,对代码无侵入。目前支持 Java 和 PHP 语言,底层采用 HBase 来存储数据,探针收集的数据粒度非常细,但性能损耗较大,因其出现的时间较长,完成度较高,文档丰富,因此应用的公司较多。
  • SkyWalking:国人开源,数据存储支持 MySQL、ElasticSearch 等。与 PinPoint 相同,Java 探针采用字节码增强技术实现,对业务代码无侵入。探针采集数据粒度相较于 Pinpoint 较粗,但性能表现优秀。SkyWalking 支持很多框架,比如 Dubbo、gRPC、SOFARPC 等。

SkyWalking 的优势:

  • 1.支持 Java、.Net、Nodejs 等多款语言的探针,还提供多种开源框架的插件,例如 Dubbo、gRPC、SOFARPC 等;
  • 2.基于 OpenTracing 规范,专门为微服务架构以及云原生架构而设计的,2019 年从 Apache 基金会孵化器毕业成为定级项目;
  • 3.SkyWalking 没有企业束缚,社区活跃,增长势头强劲;
  • 4.使用面广,比如腾讯、阿里云、华为、滴滴、电信等;
  • 5.是国人开源的(2012 年到 2015 年,吴晟因参与中国联通的首个全国集中系统,饱受分布式系统错误定位的困扰,决定着手建立 SkyWalking 这个项目。2017 年年底,SkyWalking 作为中国的个人项目社区加入 Apache 孵化器),中文文档齐全;
  • 6.有很多开发者持续不断地向社区提供插件,https://skywalking.apache.org/docs/

SkyWalking 典型案例

  • https://github.com/apache/skywalking-website/blob/master/data/homepage.yml

  • 拉勾网:

    • SkyWalking 正在观测超过 100 个服务,500 多个 JVM 实例
    • SkyWalking 每天收集和分析 40 多亿个跟踪数据,用来分析性能,其中包括 30 万个端点和依赖关系的指标
    • 在整个群集中监控>50k 流量/秒
  • 永辉超市
    • SkyWalking 每天分析至少 100 多亿(3B)的跟踪数据
    • 其次,SkyWalking 用较小的部署,每天分析 2 亿多个跟踪数据
  • 百度
    • SkyWalking 每天从 1400 多个 pod 中,从 120 多个服务收集 1T 以上的跟踪数据
    • 随着更多服务的增加,规模会持续增大
  • 贝壳找房(ke.com)
    • 很早就使用了 SkyWalking,有两名成员已经成为 PMC
    • Deployments 每天收集 160 多亿个跟踪数据
  • 阿里云效
    • SkyWalking 每天收集和分析数十亿个 span
    • SkyWalking 使阿里云的 45 项服务和~300 个实例保持稳定
  • 阿里巴巴天猫
    • SkyWalking 个性化定制版,每天监控数十亿跟踪数据
    • 与此同时,他们基于 SkyWalking 的 Agent 技术栈,利用其跟踪和上下文传播能力,正在构建一个全链路压测平台

SkyWalking Web 功能

对于 Web 侧来说,我们主要需要的是 SkyWalking 的全链路和 OAP 功能。

  • 1.Ajax 全链路追踪。符合 OpenTracing 的请求全链路追踪。
  • 2.上报 Performance 性能信息。包含 DNS、DOMReady 等 permance 信息及 FMP 等业务统计时间。
    • redirectTime: 重定向时间
    • dnsTime: DNS 解析时间
    • ttfbTime: 首个资源响应时间
    • tcpTime: TCP 连接时间
    • transTime: HTTP 应答时间
    • domAnalysisTime: DOM 解析时间
    • fptTime: 白屏时间
    • domReadyTime: DOM 完成时间
    • loadPageTime: 页面加载时间
    • resTime: 页面同步资源加载时间
    • sslTime: HTTPS 的 SSL 通信时间
    • ttlTime: 交互时间
    • firstPackTime: 第一个包的时间
    • fmpTime: 首屏/重要内容加载时间
  • 3.上报异常信息。
    • js error: JS 异常
    • promise error: 全局 Promise 异常捕获
    • css/js/link resources error: 资源异常
    • vue errorHandler: Vue 异常捕获

js-sdk(skywalking-client-js)

  • 基本信息:ts 项目,业务依赖:js-base64。压缩后 js 大小 33.4k。
  • 功能:注册并触发上报前端性能、异常、片段、请求 trace 数据。

模式介绍

p-sw_structure.jpg

整个架构,分成上、下、左、右四部分:(考虑到让描述更简单,这里舍弃掉 Metric 指标相关,而着重在 Tracing 链路相关功能。)

  • 上部分 Agent :负责从应用中,收集链路信息,发送给 SkyWalking OAP 服务器。目前支持 SkyWalking、Zikpin、Jaeger 等提供的 Tracing 数据信息。而我们目前采用的是,SkyWalking Agent 收集 SkyWalking Tracing 数据,传递给服务器。
  • 下部分 SkyWalking OAP :负责接收 Agent 发送的 Tracing 数据信息,然后进行分析(Analysis Core) ,存储到外部存储器( Storage ),最终提供查询( Query )功能。
  • 右部分 Storage :Tracing 数据存储。目前支持 ES、MySQL、Sharding Sphere、TiDB、H2 多种存储器。而我们目前采用的是 ES ,主要考虑是 SkyWalking 开发团队自己的生产环境采用 ES 为主。
  • 左部分 SkyWalking UI :负责提供控台,查看链路等等。

使用方式

1.引用 skywalking-client-js(v0.5.1)

1
2
// ES6 module
import ClientMonitor from "skywalking-client-js";

或直接引入打包后的 js

1
2
3
...
<script src="./js/skywalking-client-js"></script>
...

2.注册

注册方式 1:自动上报,ClientMonitor.register(options)

1
2
3
4
5
6
ClientMonitor.register({
collector: "http://127.0.0.1:8080", // 采集器
service: "test-ui", // 服务标识
pagePath: "/current/page/name", // 服务路径
serviceVersion: "v1.0.0", // 服务版本信息
});

注册方式 2:手动上报,ClientMonitor.setPerformance(options)。注意手动上报需要将注册 SDK 的autoTracePerf参数改为false

1
2
3
4
5
6
7
ClientMonitor.setPerformance({
collector: "http://127.0.0.1:8080",
service: "browser-app",
serviceVersion: "1.0.0",
pagePath: location.href,
useFmp: true,
});

两者的区别在于:自动上报会根据 options 直接修改 ajax 请求方法(XMLHttpRequest、fetch),根据参数注册错误监听事件;而手动上报只会上报性能信息。

上报流程

p-chain.png

自动上报模式下,默认配置会执行以下流程:

  • 1.页面初始化,注册事件。执行到 skyWalking-client-js 时,此 js 会开始根据配置参数注册各种事件监听,比如 addListener error。
  • 2.判断 document Complete 状态,确定 performance 上报机制。如果执行 skyWalking-client-js 时 document.readyState 状态已经是’complete’(即 document 加载完成,并且所有 resource 都加载完毕)时,则直接记录 performance 信息;如果不是,则注册 window load 事件,触发事件时记录 performance 信息。
  • 3.判断是否记录 FMP (first meaningful paint)信息。如果设置里开启了 FMP 的记录,则根据首屏节点及媒体元素信息进行 FMP 计算。最后 6 秒后发出性能信息上报。
  • 4.判断是否开启了 SPA 的判断开关。如果开启,则在发生路由变化时(hash change 事件)进行性能上报。
  • 5.根据配置参数注册 error、unload 等事件监听。至此页面初始化的 SDK 逻辑执行完成。
  • 6.当触发注册事件时,上报对应信息。

default/custom options

字段 格式 默认值 说明
collector string location.origin 采集器
pagePath string ‘’ 路径/路由地址
jsErrors boolean true 是否采集 js 错误
apiErrors boolean true 是否采集 api 错误
resourceErrors boolean true 是否采集资源错误
autoTracePerf boolean true 是否采集性能信息
useFmp boolean false 是否采集首批加载信息
enableSPA boolean false 是否考虑 SPA 场景
vue any false 是否考虑 vue 全局异常捕获(需要打开 jsErrors)
traceSDKInternal boolean false 是否为自定义 trace SDK。true,则 trace 的实现由自己实现;false,则用 sw8 的默认 trace。
detailMode boolean true 是否开启详细模式,开启则可以添加 tags 标签(默认有 http.method 和 url 两个 tags);否则不开启 tags 标签
noTraceOrigins (string 或 RegExp) [] trace 过滤器

默认上传信息

  • 1.performance 性能信息,默认上传(6 秒后),没有队列机制
  • 2.error 信息,默认上传(60 秒后),没有队列机制
  • 3.页面生命周期中,每隔 300 秒发送片段信息;
  • 4.页面 unload 发送片段信息。

涉及接口

  • ERROR: 单个异常,POST /browser/errorLog
  • ERRORS: 队列异常,POST /browser/errorLogs
  • PERF: 性能上报,POST /browser/perfData
  • SEGMENT: 片段信息,POST /v3/segment
  • SEGMENTS: 定时片段信息,POST /v3/segments

performance 性能上报

  • POST /browser/perfData
    • post Params: {Object}
字段 格式 说明
redirectTime number 或 undefined Time of redirection
dnsTime number 或 undefined DNS query time
ttfbTime number 或 undefined Time to First Byte
tcpTime number 或 undefined Tcp connection time
transTime number 或 undefined Content transfer time
domAnalysisTime number 或 undefined Dom parsing time
fptTime number 或 undefined First Paint Time or Blank Screen Time
domReadyTime number 或 undefined Dom ready time
loadPageTime number 或 undefined Page full load time
resTime number 或 undefined Synchronous load resources in the page
sslTime number 或 undefined Only valid for HTTPS
ttlTime number 或 undefined Time to interact
firstPackTime number 或 undefined first pack time
fmpTime number 或 undefined First Meaningful Paint 依赖于资源图片的 load

性能上报默认在 js-sdk 代码执行 6s 后发送(setTimeout)

Error 异常信息

异常采集内容

  • ajax
  • promise error
  • js error
  • css/js/link resources error
  • vue errorHandler

上报接口

  • POST: /browser/errorLogs
    • post Params: Array,ArrayItem:
字段 格式 说明
uniqueId string 唯一标识符
category string 类型
grade string 级别
message any 信息
errorUrl string 错误地址
line? number 行数
col? number 列数
stack? string 堆栈信息
firstReportedError boolean 是否第一次报告

其中 grade:

  • 默认:Info
  • 资源错误:Warning
  • 异常:Error

ajax 全链路

js-sdk 会重写 XMLHttpRequest 和 fetch API,后续所有接口均带入 trace 信息。

3.trace 提交信息

默认请求 header 增加 sw8 字段,即 base64 处理后的 traceID。格式:

1
${1}-${traceIdStr}-${segmentId}-${index}-${service}-${instance}-${endpoint}-${peer}

其中:

  • traceIdStr:String,随机 traceID,uuid 生成规则;
  • segmentId:String,随机 segmentId,uuid 生成规则;
  • index:String,当前 spans 的数量;
  • service:String,segment 的服务;
  • instance:String,segment 的服务实例;
  • endpoint:String,segment 的路径地址;
  • peer:String,segment 的 host

4.追踪

可通过解码 base64,拿到 traceIdStr 并在 SkyWalking UI 的日志模块上查询链路信息,

上报的 traceIdStr 为MDQ3YTNhYWMtZWY0MS00M2U0LWI0ZTYtNWVkZDY1ZTIzNjM4,解码后得047a3aac-ef41-43e4-b4e6-5edd65e23638。然后可以在RocketBot平台进行查询。

其他

1.uuid

依赖Math.ramdon()生成

2.service

ServiceTag: <browser>

3.SPA 应用

如果要处理 SPA,区分各路由页面的话。可以在注册的时候开启 enableSPA 设置。并通过路由监听并动态设置服务。如:

1
2
3
4
// route change
ClientMonitor.setPerformance({
pagePath: location.hash.replace("#", ""),
});

4.上报接口的异常处理

在请求上报接口时,当出现以下情况时,js-sdk 会认为 report 失败,但不会做出业务处理:

  • XMLHttpRequest: 不满足xhr.readyState === 4 && xhr.status < 400
  • Fetch API: response.status >= 400 || response.status === 0

5.采集丢失风险

所有的上报都采用了定时和队列机制,存在页面销毁但队列未清空上报的风险。

  • onbeforeunload: report Segments; queues.length: report ERRORS
  • tasks.length: report ERRORS

业务使用分析

需要调整内容

  • uuid 和 tradeID 规则:

  • 异常信息字符长度:

  • 考虑 Vue 异常全局捕获的业务适配

  • FMP 的兼容问题

    • 用到了 MutationObserver,PC 兼容性
    • performance.getEntries,移动端兼容性
  • 定时器时间

    • pref: 6s,可能过长
    • trade fire: 60s
    • segments: 30s
  • 考虑采集丢失风险:

    • 借助客户端能力
    • 直接上报
  • 动态加载资源的异常收集:js/css 等

定制化方案技术可行性

  • 请求发送自定义字段:默认不支持,会导致服务端警告。方案:
    • 1.通过添加自定义 tags
    • 2.对服务端探针进行修改
    • 3.使用某一字段然后传 JSON

rocketbot-ui

  • 基本信息:vue+ts 项目,可视化部门由 echarts 及 d3 实现,自定义 UI。
  • 该项目目前存在不少 bug,比如日志分页,需要进行改造。

自定义组件

包含图标、按钮、日期选择、下拉菜单、选择、进度条等组件;

如果 APM 使用 Vue 且延续界面风格,可以直接使用。

使用说明

  • 日志
  • 性能信息。主要应用信息:
    • CPM:Cost Per Mille。PV 信息;
    • Error Rate;
    • Error Count
    • Page Error Rate
    • Performance
    • FPT: First Paint Time or Blank Screen Time
    • TTL: time to interact
    • DOM Ready time
    • Page load time
    • Page first pack time
    • FMP

定制化方案技术可行性

  • 数据层:接口是 GraphQL 的形式,可按需查询;
  • 视图层:如果沿用 UI 风格,可以基于 rocketbot-ui 继续开发;如果考虑适配多平台应用的话,适配难度低;重新开发平台成本也较低。

单从 web 侧来说,js-sdk 和 rocketbot-ui 目前还是存在一些问题的,所以在业务侧最好进行修改。


相关链接