公众号关注 “ 杰哥的IT之旅 ”,
java
选择“ 星标 ”, 重磅干货,第一 时间送达!
mysql
在分布式系统,尤为是微服务系统中,一次外部请求每每须要内部多个模块,多个中间件,多台机器的相互调用才能完成。在这一系列的调用中,可能有些是串行的,而有些是并行的。在这种状况下,咱们如何才能肯定这整个请求调用了哪些应用?哪些模块?哪些节点?以及它们的前后顺序和各部分的性能如何呢?程序员
这就是涉及到链路追踪。算法
什么是链路追踪?
链路追踪是分布式系统下的一个概念,它的目的就是要解决上面所提出的问题,也就是将一次分布式请求还原成调用链路,将一次分布式请求的调用状况集中展现,好比,各个服务节点上的耗时、请求具体到达哪台机器上、每一个服务节点的请求状态等等。sql
链路追踪的原理
衡量一个接口,咱们通常会看三个指标:编程
一、接口的 RT(Route-Target)你怎么知道?
二、接口是否有异常响应?
三、接口请求慢在哪里?微信
一、单体架构时代网络
在创业初期,咱们的系统通常是单体架构,以下:架构
对于单体架构,咱们可使用 AOP(切面编程)来统计这三个指标,以下:分布式
使用 AOP(切面编程),对本来的逻辑代码侵入更少,咱们只须要在调用具体的业务逻辑先后分别打印一下时间便可计算出总体的调用时间。另外,使用 AOP(切面编程)来捕获异常也可知道是哪里的调用致使的异常。
二、微服务架构
随着业务的快速发展,单体架构愈来愈不能知足须要,咱们的系统慢慢会朝微服务架构发展,以下:
在微服务架构下,当有用户反馈某个页面很慢时,虽然咱们知道这个请求可能的调用链是 A -----> C -----> B -----> D,但服务这么多,并且每一个服务都有好几台机器,怎么知道问题具体出在哪一个服务?哪台机器呢?
这也是微服务这种架构下的几个痛点:
一、排查问题难度大,周期长
二、特定场景难复现
三、系统性能瓶颈分析较难
分布式调用链就是为了解决以上几个问题而生,它主要的做用以下:
一、自动采起数据
二、分析数据,产生完整调用链:有了请求的完整调用链,问题有很大几率可复现
三、数据可视化:每一个组件的性能可视化,能帮助咱们很好地定位系统的瓶颈,及时找出问题所在
经过分布式追踪系统,咱们能很好地定位请求的每条具体请求链路,从而轻易地实现请求链路追踪,进而定位和分析每一个模块的性能瓶颈。
三、分布式调用链标准(OpenTracing)
OpenTracing 是一个轻量级的标准化层,它位于应用程序/类库和追踪或日志分析程序之间。它的出现是为了解决不一样的分布式追踪系统 API 不兼容的问题。
OpenTracing 经过提供与平台和厂商无关的 API,使得开发人员可以方便地添加追踪系统,就像单体架构下的AOP(切面编程)同样。
说到这里,你们是否想过 Java 中相似的实现?还记得 JDBC 吧?JDBC 就是经过提供一套标准的接口让各个厂商去实现,程序员便可面对接口编程,不用关心具体的实现。这里的接口其实就是标准。因此,制定一套标准很是重要,能够实现组件的可插拔。
OpenTracing 的数据模型,主要有如下三个:
-
Trace:一个完整请求链路
-
Span:一次调用过程(须要有开始时间和结束时间)
-
SpanContext:Trace 的全局上下文信息,如里面有traceId
为了让你们更好地理解这三个概念,我特地画了一张图:
如图所示,一次下单的完整请求就是一个 Trace。TraceId是这个请求的全局标识。内部的每一次调用就称为一个 Span,每一个 Span 都要带上全局的 TraceId,这样才可把全局 TraceId 与每一个调用关联起来。这个 TraceId 是经过 SpanContext 传输的,既然要传输,显然都要遵循协议来调用。如图所示,若是咱们把传输协议比做车,把 SpanContext 比做货,把 Span 比做路应该会更好理解一些。
理解了这三个概念,接下来咱们就看看分布式追踪系统是如何采集图中的微服务调用链。
咱们能够看到底层有一个 Collector 一直在默默无闻地收集数据,那么每一次调用 Collector 会收集哪些信息呢。
一、全局 trace_id:这是显然的,这样才能把每个子调用与最初的请求关联起来
二、span_id: 图中的 0,1,1.1,2,这样就能标识是哪个调用
三、parent_span_id:好比 b 调用 d 的 span_id 是 1.1,那么它的 parent_span_id 即为 a 调用 b 的 span_id 即 1,这样才能把两个紧邻的调用关联起来。
有了这些信息,Collector 收集的每次调用的信息以下:
根据这些图表信息显然能够据此来画出调用链的可视化视图以下:
因而一个完整的分布式追踪系统就实现了。
以上实现看起来确实简单,但有如下几个问题须要咱们仔细思考一下:
一、怎么自动采集 span 数据:自动采集,对业务代码无侵入
二、如何跨进程传递 context
三、traceId 如何保证全局惟一
四、请求量这么多采集会不会影响性能
接下来,咱们来看看链路追踪系统 SkyWalking 是如何解决以上四个问题的。
链路追踪系统SkyWalking的原理
一、怎么自动采集 span 数据
SkyWalking 采用了插件化 + javaagent 的形式来实现了 span 数据的自动采集,这样能够作到对代码的无侵入性。插件化意味着可插拔,扩展性好。以下图所示:
二、如何跨进程传递 context
咱们知道数据通常分为 header 和 body,就像 http 有 header 和 body,RocketMQ 也有 MessageHeader,Message Body。body 通常放着业务数据,因此不宜在 body 中传递 context,应该在 header 中传递 context,如图所示:
dubbo 中的 attachment 就至关于 header,因此咱们把 context 放在 attachment 中,这样就解决了 context 的传递问题。
三、traceId 如何保证全局惟一
要保证全局惟一 ,咱们能够采用分布式或者本地生成的 ID。使用分布式的话,须要有一个发号器,每次请求都要先请求一下发号器,会有一次网络调用的开销。因此 SkyWalking 最终采用了本地生成 ID 的方式,它采用了大名鼎鼎的 snowflow 算法,性能很高。
不过 snowflake 算法有一个众所周知的问题:时间回拨,这个问题可能会致使生成的 id 重复。那么 SkyWalking 是如何解决时间回拨问题的呢。
每生成一个 id,都会记录一下生成 id 的时间(lastTimestamp),若是发现当前时间比上一次生成 id 的时间(lastTimestamp)还小,那说明发生了时间回拨,此时会生成一个随机数来做为 traceId。这里可能就有同窗要较真了,可能会以为生成的这个随机数也会和已生成的全局 id 重复,是否再加一层校验会好点。
这里要说一下系统设计上的方案取舍问题了,首先若是针对产生的这个随机数做惟一性校验无疑会多一层调用,会有必定的性能损耗,但其实时间回拨发生的几率很小(发生以后因为机器时间紊乱,业务会受到很大影响,因此机器时间的调整必然要慎之又慎),再加上生成的随机数重合的几率也很小,综合考虑这里确实没有必要再加一层全局惟一性校验。对于技术方案的选型,必定要避免过分设计,过犹不及。
四、请求量这么多,所有采集会不会影响性能?
若是对每一个请求调用都采集,那毫无疑问数据量会很是大,但反过来想一下,是否真的有必要对每一个请求都采集呢?其实没有必要,咱们能够设置采样频率,只采样部分数据,SkyWalking 默认设置了 3 秒采样 3 次,其他请求不采样,如图所示:
这样的采样频率其实足够咱们分析组件的性能了,按 3 秒采样 3 次,这样的频率来采样数据会有啥问题呢。理想状况下,每一个服务调用都在同一个时间点,这样的话每次都在同一时间点采样确实没问题。以下图所示:
但在生产上,每次服务调用基本不可能都在同一时间点调用,由于期间有网络调用延时等,实际调用状况极可能是下图这样:
这样的话就会致使某些调用在服务 A 上被采样了,在服务 B,C 上不被采样,也就无法分析调用链的性能。
那么 SkyWalking 是如何解决的呢?
它是这样解决的:若是上游有携带 Context 过来(说明上游采样了),则下游将强制采集数据,这样能够保证链路完整。
SkyWalking 的基础架构
SkyWalking 的基础以下架构,能够说几乎全部的的分布式调用都是由如下几个组件组成的。
首先固然是节点数据的定时采样,采样后将数据定时上报,将其存储到 ES, MySQL 等持久化层,有了数据天然而然可根据数据作可视化分析。
SkyWalking 的性能如何
以下是官方的测评数据:
图中蓝色表明未使用 SkyWalking 的表现,橙色表明使用了 SkyWalking 的表现,以上是在 TPS 为 5000 的状况下测出的数据,能够看出,不管是 CPU,内存,仍是响应时间,使用 SkyWalking 带来的性能损耗几乎能够忽略不计。
接下来咱们再来看 SkyWalking 与另外一款业界比较知名的分布式追踪工具 Zipkin、Pinpoint 的对比(在采样率为 1 秒 1 个,线程数 500,请求总数为 5000 的状况下作的对比)。
能够看到在关键的响应时间上, Zipkin(117ms),PinPoint(201ms)远逊于 SkyWalking(22ms)!从性能损耗这个指标上看,SkyWalking 完胜!
再看下另外一个指标:对代码的侵入性如何。
ZipKin 是须要在应用程序中埋点的,对代码的侵入强,而 SkyWalking 采用 javaagent + 插件化这种修改字节码的方式能够作到对代码无任何侵入。除了性能和对代码的侵入性上 SkyWaking 表现不错外,它还有如下优点几个优点:
-
对多语言的支持,组件丰富:目前其支持 Java、 .Net Core、PHP、NodeJS、Golang、LUA 语言,组件上也支持dubbo, mysql 等常见组件,大部分能知足咱们的需求。
-
扩展性:对于不知足的插件,咱们按照 SkyWalking 的规则手动写一个便可,新实现的插件对代码无入侵。
以上虽然主要以SkyWalking为例来介绍链路追踪系统,可是并非说其余链路追踪系统一点不适用。具体选择什么样的,你们可按实际场景灵活选择。
做者:猿话
来源:https://www.toutiao.com/i6884571378981274123/
若是您以为这篇文章对您有点用的话,麻烦您为本文来个四连:转发分享、点赞、点在看、留言,由于这将是我写做与分享更多优质文章的最强动力!
本公众号所有博文已整理成一个目录,请在公众号后台回复「 m
」获取!
推荐阅读:
一、 成为架构师,必须掌握 10 种常见的架构模式!
二、 程序员必知的 7 种软件架构模式
三、 一文读懂「分布式架构」
四、 Linux 经典的几款收包引擎
五、 最全 VxLAN 知识详解
六、 什么是堡垒机?为何须要堡垒机?
关注微信公众号「 杰哥的IT之旅」,后台回复「 1024」查看更多内容,回复「 加群」 备注:地区-职业方向-昵称 便可加入读者交流群。
点个[在看],是对杰哥最大的支持!
本文分享自微信公众号 - 杰哥的IT之旅(Jake_Internet)。
若有侵权,请联系 support@oschina.cn 删除。
本文参与“OSC源创计划”,欢迎正在阅读的你也加入,一块儿分享。