首页 » Web前端 » snowflowphp实现技巧_厉害40 张图看懂分布式追踪系统事理及实践

snowflowphp实现技巧_厉害40 张图看懂分布式追踪系统事理及实践

访客 2024-12-01 0

扫一扫用手机浏览

文章目录 [+]

来源 | 码海

在微做事架构中,一次要求每每涉及到多个模块,多个中间件,多台机器的相互协作才能完成。

snowflowphp实现技巧_厉害40 张图看懂分布式追踪系统事理及实践

这一系列调用要求中,有些是串行的,有些是并行的,那么如何确定这个要求背后调用了哪些运用,哪些模块,哪些节点及调用的先后顺序?如何定位每个模块的性能问题?本文将为你揭晓答案。

snowflowphp实现技巧_厉害40 张图看懂分布式追踪系统事理及实践
(图片来自网络侵删)

本文将会从以下几个方面来阐述:

分布式追踪系统事理及浸染

SkyWalking的事理及架构设计

我司在分布式调用链上的实践

分布式追踪系统的事理及浸染

如何衡量一个接口的性能好坏,一样平常我们至少会关注以下三个指标:

接口的 RT 你怎么知道?

是否有非常相应?

紧张慢在哪里?

单体架构

在初期,公司刚起步的时候,可能多会采取如下单体架构,对付单体架构我们该用什么办法来打算以上三个指标呢?

最随意马虎想到的显然是用 AOP:

利用 AOP 在调用详细的业务逻辑前后分别打印一下韶光即可打算出整体的调用韶光,利用 AOP 来 catch 住非常也可知道是哪里的调用导致的非常。

微做事架构

在单体架构中由于所有的做事,组件都在一台机器上,以是相对来说这些监控指标比较随意马虎实现,不过随着业务的快速发展,单体架构一定会朝微做事架组成长,如下:

如图示:一个轻微繁芜的微做事架构

如果有用户反馈某个页面很慢,我们知道这个页面的要求调用链是 A -----> C -----> B -----> D,此时如何定位可能是哪个模块引起的问题。
每个做事 Service A,B,C,D 都有好几台机器。
怎么知道某个要求调用了做事的详细哪台机器呢?

可以明显看到,由于无法准确定位每个要求经由的确切路径,在微做事这种架构下有以下几个痛点:

排查问题难度大,周期长

特定场景难复现

系统性能瓶颈剖析较难

分布式调用链便是为理解决以上几个问题而生,它紧张的浸染如下:

自动采纳数据

剖析数据产生完全调用链:有了要求的完全调用链,问题有很大概率可复现

数据可视化:每个组件的性能可视化,能帮助我们很好地定位系统的瓶颈,及时找出问题所在

通过分布式追踪系统能很好地定位如下要求的每条详细要求链路,从而轻易地实现要求链路追踪,每个模块的性能瓶颈定位与剖析。

分布式调用链标准 - OpenTracing

知道了分布式调用链的浸染,那我们来看下如何实现分布式调用链的实现及事理, 首先为理解决不同的分布式追踪系统 API 不兼容的问题,出身了 OpenTracing 规范,OpenTracing 是一个轻量级的标准化层,它位于运用程序/类库和追踪或日志剖析程序之间。

这样 OpenTracing 通过供应平台无关,厂商无关的 API,使得开拓职员能够方便地添加追踪系统的实现。

说到这大家是否想过 Java 中类似的实现?还记得 JDBC 吧,通过供应一套标准的接口让各个厂商去实现,程序员即可面对接口编程,不用关心详细的实现。

这里的接口实在便是标准,以是制订一套标准非常主要,可以实现组件的可插拔。

接下来我们来看 OpenTracing 的数据模型,紧张有以下三个:

Trace:一个完全要求链路

Span:一次调用过程(须要有开始韶光和结束韶光)

SpanContext:Trace 的全局高下文信息, 如里面有traceId

理解这三个观点非常主要,为了让大家更好地理解这三个观点,我特意画了一张图:

如图示,一次下单的完全要求完全便是一个 Trace, 显然对付这个要求来说,必须要有一个全局标识来标识这一个要求,每一次调用就称为一个 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 的通报问题。

小提示:这里的通报 context 流程均是在 dubbo plugin 处理的,业务无感知,这个 plugin 是怎么实现的呢,下文会剖析。

traceId 如何担保全局唯一

要担保全局唯一 ,我们可以采取分布式或者本地天生的 ID,利用分布式话须要有一个发号器,每次要求都要先要求一下发号器,会有一次网络调用的开销,以是 SkyWalking 终极采取了本地天生 ID 的办法,它采取了大名鼎鼎的 snowflow 算法,性能很高。

图示: snowflake 算法天生的 id

不过 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 的表现,橙色代表利用了 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 在我司的运用架构

由上文可知 SkyWalking 有很多优点,那么是不是我们用了它的全部组件了呢,实在不然,来看下其在我司的运用架构:

从图中可以看出我们只采取了 SkyWalking 的 agent 来进行采样,放弃了其余的「数据上报及剖析」,「数据存储」,「数据可视化」三大组件,那为啥不直接采取 SkyWalking 的整套办理方案呢,由于在接入 SkyWalking 之前我们的 Marvin 监控生态体系已经相比拟较完善了。

如果把其全体更换成 SkyWalking,一来没有必要,Marvin 在大多数场景下都能知足我们的需求,二来系统更换本钱高,三来如果重新接入用户学习本钱很高。

这也给我们一个启迪:任何产品抢占先机很主要,后续产品的更换本钱会很高,抢占先机,也便是抢占了用户的心智,这就像微信虽然 UI,功能上制作精良,但在国外还是干不过 Whatsapp 一样,由于先机已经没了。

从另一方面来看,对架构来说,没有最好的,最有最得当的,结合当前业务场景去平衡折中才是架构设计的实质。

我司对 SkyWalking 作了哪些改造和实践

我司紧张作了以下改造和实践:

预发环境由于调试须要逼迫采样

实现更细粒度的采样?

日志中嵌入traceId

自研实现了 SkyWalking 插件

预发环境由于调试须要逼迫采样

从上文剖析可知 Collector 是在后台定时采样的,这不挺好的吗,为啥要实现逼迫采样呢。

还是为了排查定位问题,有时线上涌现问题,我们希望在预发上能重现,希望能看到这个要求的完全调用链,以是在预发上实现逼迫采样很有必要。
以是我们对 Skywalking 的 dubbo 插件进行了改造,实现逼迫采样。

我们在要求的 Cookie 上带上一个类似 force_flag = true 这样的键值对来表示我们希望逼迫采样,在网关收到这个 Cookie 后,就会在 dubbo 的 attachment 里带上force_flag = true 这个键值对,然后 skywalking 的 dubbo 插件就可以据此来判断是否是逼迫采样了,如果有这个值即逼迫采样,如果没有这个值,则走正常的定时采样。

实现更细粒度的采样?

哈叫更细粒度的采样。
先来看下 skywalking 默认的采样办法 ,即统一采样。

我们知道这种办法默认是 3 秒采样前 3 次,其他要求都丢弃,这样的话有个问题,假设在这台机器上在 3 秒内有多个 dubbo,mysql,redis 调用,但在如果前三次都是 dubbo 调用的话,其它像 mysql, redis 等调用就采样不到了,以是我们对 skywalking 进行了改造,实现了分组采样,如下:

便是说 3 秒内进行 3 次 redis, dubbo, mysql 等的采样,也就避免了此问题。

日志中如何嵌入traceId?

输出日志中嵌入 traceId 便于我们排查问题,以是打出出 traceId 非常有必要,该怎么在日志中嵌入 traceId 呢?

我们用的是 log4j,这里就要理解一下 log4j 的插件机制了,log4j 许可我们自定义插件来输出日志的格式,首先我们须要定义日志的格式,在自定义的日志格式中嵌入 %traceId, 作为占位符,如下:

然后我们再实现一个 log4j 的插件,如下:

首先 log4j 的插件要定义一个类,这个类要继续 LogEventPatternConverter 这个类,并且用标准 Plugin 将其自身声明为 Plugin,通过 @ConverterKeys 这个表明指定了要更换的占位符,然后在 format 方法里将其更换掉。

这样在日志中就会涌现我们想要的 TraceId ,如下:

我司自研了哪些 skywalking 插件

SkyWalking 实现了很多插件,不过未供应 memcached 和 druid 的插件,以是我们根据其规范自研了这两者的插件。

插件如何实现呢,可以看到它紧张由三个部分组成:

插件定义类: 指定插件的定义类,终极会根据这里的定义类打包天生 plugin

Instrumentation: 指定切面,切点,要对哪个类的哪个方法进行增强

Interceptor,指定步骤 2 中要在方法的前置,后置还是非常中写增强逻辑

可能大家看了还是不懂,那我们以 dubbo plugin 来大略讲解一下,我们知道在 dubbo 做事中,每个要求从 netty 吸收到,递交给业务线程池处理开始,到真正调用到业务方法结束,中间经由了十几个 Filter 的处理。

而 MonitorFilter 可以拦截所有客户端发出要求或者做事端处理要求,以是我们可以对 MonitorFilter 作增强,在其调用 invoke 方法前,将全局 traceId 注入到其 Invocation 的 attachment 中,这样就可以确保在要求到达真正的业务逻辑前就已经存在全局 traceId。

以是显然我们须要在插件中指定我们要增强的类(MonitorFilter),对其方法(invoke)做增强,要对这个方法做哪些增强呢,这便是拦截器(Inteceptor)要做的事,来看看 Dubbo 插件中的 instrumentation(DubboInstrumentation)。

我们再看看下代码中描写的拦截器(Inteceptor)干了什么事,以下列出关键步骤:

首先 beforeMethod 代表在实行 MonitorFilter 的 invoke 方法前会调用这里的方法,与之对应的是 afterMethod,代表在实行 invoke 方法后作增强逻辑。

其次我们从第 2,3点可以看到,不管是 consumer 还是 provider, 都对其全局 ID 作了相应处理,这样确保到达真正的业务层的时候担保有了此全局 traceid,定义好 Instrumentation 和 Interceptor 后,末了一步便是在 skywalking.def 里指定定义的类。

// skywalking-plugin.def 文件dubbo=org.apache.skywalking.apm.plugin.asf.dubbo.DubboInstrumentation

这样打包出来的插件就会对 MonitorFilter 的 invoke 方法进行增强,在 invoke 方法实行前对期 attachment 作注入全局 traceId 等操作,这统统都是静默的,对代码无侵入的。

总结

本文由浅入深地先容了分布式追踪系统的事理,相信大家对其浸染及事情机制有了比较深的理解。

特殊须要把稳的是,引入某项技巧,一定要结合现有的技能架构作出最合理的选择,就像 SkyWalking 有四个模块,我司只采取其 agent 采样功能一样,没有最好的技能,只有最得当的技能。

通过此文,相信大家该当对 SkyWalking 的实现机制有了比较清晰的认识,文中只是先容了一下 SkyWalking 的插件实现办法,不过其毕竟是工业级软件,要理解其博大精湛,还要多读源码哦。

点分享

标签:

相关文章

倚天剑法,剑走偏锋,升级之路的奥秘

自古以来,武侠世界中的剑法升级一直是广大武侠迷津津乐道的话题。而《倚天屠龙记》中的倚天剑法,更是以其独特的升级之路,成为了无数武侠...

Web前端 2025-01-01 阅读0 评论0

倒问号的魅力,探索语言符号的深层意义

倒问号,这个看似简单却又充满神秘色彩的符号,在我国语言文字中扮演着举足轻重的角色。它不仅仅是一个标点符号,更是一种独特的语言艺术。...

Web前端 2025-01-01 阅读0 评论0

业务刷单,步骤与方法,助力企业稳健增长

在当今竞争激烈的市场环境下,企业要想脱颖而出,除了创新、品质和服务,还要善于运用各种营销手段。其中,业务刷单作为一种有效的营销策略...

Web前端 2025-01-01 阅读0 评论0

业余时间,如何高效利用,提升自我价值

在快节奏的现代生活中,业余时间成为了人们渴望拥有的宝贵财富。如何高效利用业余时间,提升自我价值,却成为了一个值得深思的问题。本文将...

Web前端 2025-01-01 阅读0 评论0

保速捷,汽车领域的璀璨明珠

随着科技的飞速发展,汽车行业竞争日益激烈。在这片激烈的市场竞争中,保速捷以其独特的魅力和卓越的品质脱颖而出,成为了众多消费者心中的...

Web前端 2025-01-01 阅读0 评论0

保险管如何选_介绍保险规划的艺术与智慧

保险,作为一种重要的风险管理工具,在我们的生活中扮演着至关重要的角色。面对种类繁多、条款复杂的保险产品,如何选择适合自己的保险管成...

Web前端 2025-01-01 阅读0 评论0