自从项目上了SkyWalking,睡觉真香!(2)

本文涉及的产品
云数据库 RDS MySQL,集群系列 2核4GB
推荐场景:
搭建个人博客
RDS MySQL Serverless 基础系列,0.5-2RCU 50GB
云数据库 RDS PostgreSQL,集群系列 2核4GB
简介: 自从项目上了SkyWalking,睡觉真香!(2)

请求量这么多,全部采集会不会影响性能?

如果对每个请求调用都采集,那毫无疑问数据量会非常大,但反过来想一下,是否真的有必要对每个请求都采集呢,其实没有必要,我们可以设置采样频率,只采样部分数据,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 有很多优点,那么是不是我们用了它的全部组件了呢,其实不然,来看下其在我司的应用架构

image.png

从图中可以看出我们只采用了 SkyWalking 的 agent 来进行采样,放弃了另外的「数据上报及分析」,「数据存储」,「数据可视化」三大组件,那为啥不直接采用 SkyWalking 的整套解决方案呢,因为在接入 SkyWalking 之前我们的 Marvin 监控生态体系已经相对比较完善了,如果把其整个替换成  SkyWalking,一来没有必要,Marvin 在大多数场景下都能满足我们的需求,二来系统替换成本高,三来如果重新接入用户学习成本很高。

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

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

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

我司主要作了以下改造和实践

  1. 预发环境由于调试需要强制采样
  2. 实现更细粒度的采样?
  3. 日志中嵌入traceId
  4. 自研实现了 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 的插件,所以我们根据其规范自研了这两者的插件

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

  1. 插件定义类: 指定插件的定义类,最终会根据这里的定义类打包生成 plugin
  2. Instrumentation: 指定切面,切点,要对哪个类的哪个方法进行增强
  3. 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 的插件实现方式,不过其毕竟是工业级软件,要了解其博大精深,还要多读源码哦。



相关实践学习
如何快速连接云数据库RDS MySQL
本场景介绍如何通过阿里云数据管理服务DMS快速连接云数据库RDS MySQL,然后进行数据表的CRUD操作。
全面了解阿里云能为你做什么
阿里云在全球各地部署高效节能的绿色数据中心,利用清洁计算为万物互联的新世界提供源源不断的能源动力,目前开服的区域包括中国(华北、华东、华南、香港)、新加坡、美国(美东、美西)、欧洲、中东、澳大利亚、日本。目前阿里云的产品涵盖弹性计算、数据库、存储与CDN、分析与搜索、云通信、网络、管理与监控、应用服务、互联网中间件、移动服务、视频服务等。通过本课程,来了解阿里云能够为你的业务带来哪些帮助     相关的阿里云产品:云服务器ECS 云服务器 ECS(Elastic Compute Service)是一种弹性可伸缩的计算服务,助您降低 IT 成本,提升运维效率,使您更专注于核心业务创新。产品详情: https://www.aliyun.com/product/ecs
相关文章
|
8月前
|
消息中间件 安全 druid
GitHub昙花一现!《Spring Boot趣味实战课》神作开源几分钟被下架
今天给大家分享好书了:刘水镜老师的 《Spring Boot趣味实战课》,网上依旧是没有开源版本!小编会在文末附电子版免费下载方式。 刘水镜是谁? 十余年持续技术文章输出,CSDN博客专家。2020年《 Spring Boot趣味私房课》专栏上线,凭借风趣幽默、深入浅出的写作风格深受读者好评。 《Spring Boot趣味实战课》 内容丰富、趣味实战是本书的两大特色 涵盖 Spring MVC、MyBatis Plus、Spring DaJPA、Spring Security、Quartz等主流框架 整合MySQL. Druid、Redis、 RabbitMQ、Elastics
116 0
|
8月前
|
XML Java 数据格式
🚀今天,我们来详细的聊一聊SpringBoot自动配置原理,学了这么久,你学废了吗?
🚀今天,我们来详细的聊一聊SpringBoot自动配置原理,学了这么久,你学废了吗?
124 0
膜拜!清华大佬手撸多线程并发源码笔记Github上线3天星标35k+
你为什么要学习多线程?是因为理想吗?是因为热爱吗? 哦~原来是为了面试打基础、做准备啊!没错,这真的很现实!
膜拜!清华大佬手撸多线程并发源码笔记Github上线3天星标35k+
|
安全 NoSQL Java
秀出新天际的SpringBoot笔记,让开发像搭积木一样简单
什么是 Spring Boot Java (面向对象编程语言)经过30多年的发展,产生了非常多的优秀框架。Spring (为解决企业应用程序开发的复杂性而创建的框架)曾是最受欢迎的Java框架之一, 但随着Node、Ruby、Groovy、PHP等脚本语言的蓬勃发展,使用Spring开发应用就显得繁琐了,因为它使用了大量的XML配置文件,配置繁琐,整合不易,开发和部署效率低下。这时急切需要一-种新的能解决这些问题的快速开发框架,于是Pivotal Software公司在2013开始了Spring Boot的研发。
202 0
|
编解码 前端开发
重学JavaWeb第二天(七)
重学JavaWeb第二天
97 0
|
消息中间件 负载均衡 JavaScript
自从项目用了灰度发布,睡觉真香!
自从项目用了灰度发布,睡觉真香!
|
前端开发 Java 数据库
SpringBoot日记本系统全程直播01:先把框架搞起来撒~~
SpringBoot日记本系统全程直播01:先把框架搞起来撒~~
139 0
|
前端开发 容器
重学JavaWeb第二天(二)
重学JavaWeb第二天
151 0
|
前端开发 数据安全/隐私保护
重学JavaWeb第二天(六)
重学JavaWeb第二天
154 0
|
前端开发
重学JavaWeb第二天(一)
重学JavaWeb第二天
141 0