20能力进阶:APM工具自燃?随时客串APM工程师
文章目录
你好,从今天起我们就开始了对最后部分“APM 软技能”的学习了。在本部分的课程中,我会从典型案例故事出发,让你感同身受问题现场,然后加之相应软技能辅助,让你在前面课程中学习到的硬实力更加充分地发挥出来,最终让你独自排查问题时可以更有头绪,具备独当一面的能力。
解决常规的应用服务问题或是故障排查手段,每个团队都有着适用于自身的“白皮书”或是“三板斧”。其主要作用,就是让一线开发人员遇到问题时,具备定位常规问题的思路,并能梳理好团队已有的 APM 工具以及项目干系人,从而做到处理问题有章法、解决问题有效率。
然而 APM 工具自身出现问题时,如何去排查解决,是不在“白皮书”中的。所以我就将近些年,我在解决 APM 客户端自燃问题上的经验和方法与你分享。
“断链”案例
根据“10 | 亲和线程模型:分布式链路追踪,学习 SkyWalking 就够了”,我们知道分布式链路追踪是 APM 的重要领域,分布式链路追踪最常见的就是链路串联不起来,也就是“断链”问题。
那我们今天就学习一个案例,看看问题排查过程是怎样的。
在某个时间节点后,有业务线反馈 SkyWalking 的监控链路的部分数据丢失,起初我刚开始接到问题时,第一反应就是认为其出现了“插件不支持”或“内存泄漏造成断链”问题,这也是“10 | 亲和线程模型:分布式链路追踪,学习 SkyWalking 就够了”讲述过的。
所以我根据上报问题的内容,去查看了分布式链路的存储数据;并通过在线剖析工具,去跟进任务线程的监控周期。最终发现并没有出现内存泄漏,链路模型也被“完整”地收集到了后端收集器。
但是当使用链路 ID 查看链路的存储模型时,我发现丢失的数据为部分组件的监控数据,比如 Apache HttpClient 组件,那便排除了内存泄漏问题。剩下常见的诱发问题的原因,便就是“插件不支持”,然后通过 maven 分析应用程序的依赖树,我却发现组件的版本是支持的。
这时再向下开展工作就遇到了僵局,如果缺乏解决 APM 问题经验的话,再往下解决问题的思路就会变得没有章法。
所以接下来,我就介绍几招通用的“三板斧”,让你解决问题的能力更上一个维度。
复现问题
1.摸清现场
在上文“断链”案例中,我的第一步排查手段就是及时去摸清现场,这与常规解决应用服务线上问题,以及常规的解题思维是一致的。
在时间上,任何问题的现场,第一手案发资料都会随着时间流逝愈发模糊,所以要尽早排查摸清问题现场,那如何摸清现场呢?
这时就要使用 APM 工具了,APM 工具不仅可以排查业务服务这些非自身问题,也可以通过 APM 工具来排查 APM 工具自身的问题,正如用 Arthas 排查现场是否有内存泄漏问题的思考是一致的。
关于工具如何选择,你可以回顾“08 | 工匠精神:熟悉 APM 产品的能力是 RD 的分内之事”。
总之工具掌握越透彻,现场记录就越清晰,这也是一个持续精进的过程。所以每次定位、解决问题的过程都需要你反复思考。
2.增加拟真度
现场记录完毕后,就是进行问题复现了。能复现的问题,就是可以解决的问题。APM 技术栈只是相对应用服务技术栈相较冷门而已,如果能稳定复现 APM 工具引发应用服务自燃的问题,那这个问题肯定就能被解决。
那复现案发现场的关键因素是什么呢?和业务问题复现一样,就是相似度。相似度越高,复现的成功率就越高,这也是核心场景都有沙箱环境的原因之一。通过极致的拟真线上,沙箱环境可用于验证功能是否具备线上预期的完整性。如果你的应用服务没有沙箱环境,那可以根据问题类型的不同,去针对性地增强某些方面的拟真性。
正如线上业务流程问题,需要增加数据方向的拟真需要。APM 属于基础设施,那就需要增加线上环境配置的拟真性。那针对线上 APM 环境,由于线上配置很多,我首先将线上 SkyWalking 配置进行拟真。很不巧,没有复现问题。
那接下来继续升级拟真度,公司线上环境往往是有多个无侵入的探针配置的,将所有探针配置进行拟真。结果问题在调试环境可以稳定复现,基于对比复现问题的过程,问题也逐渐明朗。单个 SkyWalking 探针不会有问题,多个探针并存的情况存在着一些兼容性问题,
问题复现后,可以根据问题的复杂度,让更多资源加入去并行解决问题。我建议出现问题的业务线和负责 APM 建设的技术人员都进行资源投入,在调试环境下进行问题的并行分析。而分析的最常规有效手段就是开启调试模式,那如何去调试探针程序呢?
调试探针程序
业务系统开启调试很简单,就是通过调整依赖框架暴露出的日志级别,进行启动调试模式。但是字节码增强技术怎么开启调试模式呢?
首先探针日志调试模式的开启只是一方面,另一方面就是对字节码加载前后的过程。开启调试,对于 SkyWalking 而言,可以通过开启 agent.is_open_debugging_class 参数,让探针在检测到的类文件保存在 /debugging 文件夹中,以解决兼容问题。
以此类推,通过打开每个探针的修改后的类文件,我发现 SkyWalking 的增强代码并没有生效。
有了线索,那接下来就是找出其中原因了。那问题就可以确定了,当两个探针同时增强一个类时,它的加载顺序是什么样的呢?根据设计常识得知,加载顺序是根据探针的先后次序,那事实真的如此吗?
验证思路非常简单,我调整了两个探针的位置,发现 SkyWalking 探针依然无法实现增强。
解决思路
由于使用 APM 用户少,所以 APM 引发的问题很难在搜索引擎中找到相关的解决方案。本次问题也是一样,我之前的认知一直是:探针对目标类增强的过程,是根据命令行中探针的次序决定的。但根据复现场景,以及前后调整两个探针的不同顺序,发现结论与认知相悖。
这是 Oracle 官方都对探针字节码增强过程的详细解释,我就不详细进行原文翻译了。
其核心翻译是:类文件的转换是通过类似优先级队列的数据结构实现的,在每个优先级队列里,探针的类加载过程与我们认知一致,就是在同一个优先级队列中的探针,加载顺序按照次序进行顺序加载。但在反复进行多个优先级队列的类转化的场景中,不会调用没有转换能力的类转换器。
显然 SkyWalking 探针满足了这个规则,所以造成在与其他优先级队列共存的类转换场景下,没有生效的。
那你可能会问,为什么是四个优先级队列呢?原因非常简单,因为决定类转换器有如下两个布尔属性。
Can-Redefine-Classes(是否可以重新定义类)
Can-Retransform-Classes(是否可以重新转换类)
这两个属性可以有四种组合,也就对应着四种优先级队列。
找到原因了,修复问题也变得轻而易举。我们只需要将两个探针的优先级队列,调整到统一队列中,然后这些探针会按顺序加载类转换器。
那应该是用哪个优先级队列呢?
确认修复
我的想法是用兼容性较高的优先级队列,就是使用支持重新转换功能的类加载器的优先级队列。那之后使用 Apache SkyWalking 发起讨论 issue 的模板,将故障现场、故障原因、文献内容等相关信息发起讨论;和多方 review 后,将解决方案合到仓库主干,这样在上百个公司的用户案例下,此功能的改造会被进一步验证兼容性。
本案例详细的现场描述,解决思路我都写在了 SkyWalking 的社区,你可以点击链接,查看详细查看我与社区一起完成的修复过程
小结与思考
今天的课程,先讲述了在使用 SkyWalking 过程中,出现的“断链”的场景,虽然问题案例涉及知识点超出了已有认知,我们也不必慌张,坚信“可以复现的问题都是可以被解决的问题”这一信念,去复现问题。
复现问题最重要的就是复现环境与案发环境的环境相似度,开发人员根据问题的类型去针对性的拟真线上:
对于业务问题,拟真可以专注于数据方向;
对于 APM 问题,可以专注于系统环境,拟真到一定程度后,问题就会被复现。
有了复现的场景后,就可以根据问题的复杂度,投入更多的研发资源去并行解决问题,针对 APM 探针引发的问题,我们可以通过摸清案例、复现问题、开启调试、与社区共同解决这四个步骤,最终将问题解决。
你在工作开发中遇到过哪些 APM 工具自身的问题呢?你解决问题的思路是什么?最后效果怎么样?欢迎在评论区写下你的思考,期待与你的讨论。
-– ### 精选评论
文章作者 anonymous
上次更新 2024-06-05