随着微服务架构的流行,一次请求往往需要涉及到多个服务,需要一些可以帮助理解系统行为、用于分析性能问题的工具,以便发生故障的时候,能够快速定位和解决问题。
单体架构中可以使用 AOP 在调用具体的业务逻辑前后分别打印一下时间即可计算出整体的调用时间,使用 AOP 来 catch 住异常也可知道是哪里的调用导致的异常。
一个完整请求链路的追踪ID(traceid)用于查出本次请求调用的所有服务,每一次服务调用的跨度ID(spanid)用来记录调用顺序
上游服务parenetid用来记录调用的层级关系
调用时间timestamp,把请求发出、接收、处理的时间都记录下来,计算业务处理耗时和网络耗时,然后用可视化界面展示出来每个调用链路,性能,故障
还可以记录一些其他信息,比如发起调用服务名称、被调服务名称、返回结果、IP、调用服务的名称等,最后,我们再把相同spanid的信息合成一个大的span块,就完成了一个完整的调用链。
节点数据的定时采样,采样后将数据定时上报,将其存储到 ES, MySQL 等持久化层,有了数据自然而然可根据数据做可视化分析。
skywalking的工作机制,需要三块协同。工作原理图大致如下:
SkyWalking采用组件式开发,易于扩展,主要组件作用如下:
1. Skywalking Agent:链路数据采集tracing(调用链数据)和metric(指标)信息并上报,上报通过HTTP或者gRPC方式发送数据到Skywalking Collector
2. Skywalking Collector : 链路数据收集器,对agent传过来的tracing和metric数据进行整合分析通过Analysis Core模块处理并落入相关的数据存储中,同时会通过Query Core模块进行二次统计和监控告警
3. Storage: Skywalking的存储,支持以ElasticSearch、Mysql、TiDB、H2等主流存储作为存储介质进行数据存储,H2仅作为临时演示单机用。
4. SkyWalking UI: Web可视化平台,用来展示落地的数据,目前官方采纳了RocketBot作为SkyWalking的主UI
SkyWalking 采用了插件化 + javaagent 的形式来实现了 span 数据的自动采集,这样可以做到对代码的 无侵入性,插件化意味着可插拔,扩展性好
我们知道数据一般分为 header 和 body, 就像 http 有 header 和 body, RocketMQ 也有 MessageHeader,Message Body, body 一般放着业务数据,所以不宜在 body 中传递 context,应该在 header 中传递 context,如图示
dubbo 中的 attachment 就相当于 header ,所以我们把 context 放在 attachment 中,这样就解决了 context 的传递问题。
小提示:这里的传递 context 流程均是在 dubbo plugin 处理的,业务无感知
要保证全局唯一 ,我们可以采用分布式或者本地生成的 ID,使用分布式话需要有一个发号器,每次请求都要先请求一下发号器,会有一次网络调用的开销,所以 SkyWalking 最终采用了本地生成 ID 的方式,它采用了大名鼎鼎的 snowflow 算法,性能很高。
不过 snowflake 算法有一个众所周知的问题:时间回拨,这个问题可能会导致生成的 id 重复。那么 SkyWalking 是如何解决时间回拨问题的呢。
每生成一个 id,都会记录一下生成 id 的时间(lastTimestamp),如果发现当前时间比上一次生成 id 的时间(lastTimestamp)还小,那说明发生了时间回拨,此时会生成一个随机数来作为 traceId。
如果对每个请求调用都采集,那毫无疑问数据量会非常大,但反过来想一下,是否真的有必要对每个请求都采集呢,其实没有必要,我们可以设置采样频率,只采样部分数据,SkyWalking 默认设置了 3 秒采样 3 次,其余请求不采样,如图示
这样的采样频率其实足够我们分析组件的性能了,按 3 秒采样 3 次这样的频率来采样数据会有啥问题呢。理想情况下,每个服务调用都在同一个时间点(如下图示)这样的话每次都在同一时间点采样确实没问题。
但在生产上,每次服务调用基本不可能都在同一时间点调用,因为期间有网络调用延时等,实际调用情况很可能是下图这样。
这样的话就会导致某些调用在服务 A 上被采样了,在服务 B,C 上不被采样,也就没法分析调用链的性能,那么 SkyWalking 是如何解决的呢。
它是这样解决的:如果上游有携带 Context 过来(说明上游采样了),则下游强制采集数据。这样可以保证链路完整。
Skywalking已经支持从6个可视化维度剖析分布式系统的运行情况。
仪表盘主要包含Service Dashboard和Database Dashboard
SkyWalking能够根据获取的数据自动绘制服务之间的调用关系图,并能识别常见的服务显示在图标上,例如图上的tomcat、CAS服务
每条连线的颜色反应了服务之间的调用延迟情况,可以非常直观的看到服务与服务之间的调用状态,连线中间的点能点击,可显示两个服务之间链路的平均响应时间、吞吐率以及SLA等信息
展示服务的性能数据:
选中其中一个服务,可以查看调用关系及服务基础状态。
拓扑图还有个扁平展示效果
3、链路追踪:可以根据需求,查看链路调用过程
显示请求的响应内部执行情况,一个完整的请求都经过了哪些服务、执行了哪些代码方法、每个方法的执行时间、执行状态等详细信息,快速定位代码问题。
失败调用还有错误日志:
Zipkin 分为两端,Zipkin 服务端和Zipkin 客户端,客户端也就是微服务的应用。客户端配置服务端的 URL 地址,一旦发生服务间的调用的时候,会被配置在微服务里面的 Sleuth 的监听器监听,并生成相应的 Trace 和 Span 信息发送给服务端。发送的方式主要有两种,一种是 HTTP 报文的方式,另一种是消息总线的方式如 RabbitMQ。
不论哪种方式,我们都需要:一个 Eureka 服务注册中心,先看下Zipkin运行架构:
左侧应用服务,同时也是Zipkin-clinet,Eureka-client, 中间是依赖,包括Zipkin-server和Eureka-server,最右侧是WebUI展示及开发接口。
Google的Dapper,阿里的鹰眼,大众点评的CAT,Twitter的Zipkin,LINE的pinpoint,国产的skywalking。
市面上的全链路监控理论模型大多都是借鉴Google Dapper论文,本文重点关注以下三种APM组件:
类型 | zipkin | SKYwalking |
---|---|---|
基本原理 | 拦截请求,发送(HTTP,mq)数据至zipkin服务 | java探针,字节码增强 |
接入方式 | 基于linkerd或者sleuth方式,引入配置即可 | avaagent字节码 |
支持OpenTracing | 是 | 是 |
颗粒度 | 接口级(类级别) | 方法级 |
存储 | ES,mysql,Cassandra,内存 | ES,H2,TIDB |
agent到collector的协议 | http,MQ | http,gRPC |
以上三种全链路监控方案需要对比的项提炼出来 :
接下来大家肯定比较关心 SkyWalking 的性能,那我们来看下官方的测评数据
图中蓝色代表未使用 SkyWalking 的表现,橙色代表使用了 SkyWalking 的表现,以上是在 TPS 为 5000 的情况下测出的数据,可以看出,不论是 CPU,内存,还是响应时间,使用 SkyWalking 带来的性能损耗几乎可以忽略不计。
接下来我们再来看 SkyWalking 与另一款业界比较知名的分布式追踪工具 Zipkin, Pinpoint 的对比(在采样率为 1 秒 1 个,线程数 500,请求总数为 5000 的情况下做的对比),可以看到在关键的响应时间上, Zipkin(117ms),PinPoint(201ms)远逊色于 SkyWalking(22ms)
从性能损耗这个指标上看,SkyWalking 完胜!
对代码无任何侵入,除了性能和对代码的侵入性上 SkyWaking 表现不错外,它还有以下优势几个优势
对多语言的支持,组件丰富:目前其支持 Java, .Net Core, PHP, NodeJS, Golang, LUA 语言,组件上也支持dubbo, mysql 等常见组件,大部分能满足我们的需求。
扩展性:对于不满足的插件,我们按照 SkyWalking 的规则手动写一个即可,新实现的插件对代码无入侵。
参考:
skywalking原理_微服务链路追踪原理:https://blog.csdn.net/weixin_39595621/article/details/111574769
skywalking原理_40张图看懂:分布式追踪系统原理及实践:https://blog.csdn.net/weixin_39866487/article/details/111581322
分布式全链路追踪 SkyWalking基本原理(一):https://www.pianshen.com/article/87011016639/
如何通过Zipkin或SKYwalking实现链路追踪:https://blog.51cto.com/u_10705830/2433647
Pinpoint、SkyWalking、Zipkin,哪个好:https://xcbeyond.blog.csdn.net/article/details/114683836