【工具】APM和SkyWalking小记
Jun 13, 2021工具质量skywalkingAPMAPM和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 数据。
模式介绍
整个架构,分成上、下、左、右四部分:(考虑到让描述更简单,这里舍弃掉 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 | // ES6 module |
或直接引入打包后的 js
1 | ... |
2.注册
注册方式 1:自动上报,ClientMonitor.register(options)
1 | ClientMonitor.register({ |
注册方式 2:手动上报,ClientMonitor.setPerformance(options)
。注意手动上报需要将注册 SDK 的autoTracePerf
参数改为false
。
1 | ClientMonitor.setPerformance({ |
两者的区别在于:自动上报会根据 options 直接修改 ajax 请求方法(XMLHttpRequest、fetch),根据参数注册错误监听事件;而手动上报只会上报性能信息。
上报流程
自动上报模式下,默认配置会执行以下流程:
- 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}
- post Params:
字段 | 格式 | 说明 |
---|---|---|
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 | // route change |
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 目前还是存在一些问题的,所以在业务侧最好进行修改。
相关链接
- https://skywalking.apache.org/
- 《Dapper, a Large-Scale Distributed Systems Tracing Infrastructure》
- (《SkyWalking 8.2.0 中的新特性: 浏览器端监控; 使用标签查询; 指标分析语言》)[https://skywalking.apache.org/zh/2020-10-29-skywalking8-2-release/]
- 《SkyWalking 调研与初步实践》
- https://opentracing.io/
Author
My name is Micheal Wayne and this is my blog.
I am a front-end software engineer.
Contact: michealwayne@163.com