Skywalking扩展实现 —— 监控数据的动态上报

把标题名整高大上一些,来掩盖需求的奇葩。

1. 需求背景

过去一段时间,接手了一个迭代了数年的"基于微服务架构"搭建的产品。

自介入开始,我就不断尝试给系统增加可观测性,包括但不限于:

  1. 重启架构中早已荒废的Swagger文档。
  2. 为原有的日志框架输出增加traceId,以实现最基础的"人肉链路追踪"功能。
  3. 基于SpringBoot的Actuator特性来对外提供符合我们内部规范的日志级别切换接口。
  4. 基于linux命令awk, sed等实现的日志精确查询功能。
  5. 为以上功能提供前端操作页面,最大化避免需要登录服务器进行问题排查这一耗时耗神的上世纪操作习惯。

以上方案在逐步推进过程中,我们发现落地效果不及预期,究其原因:

  1. 在宣传和推广上投入的时间和精力不足。
  2. 相关人员的旧有习惯作祟。(不过这也说明上面方式带来的好处,在当事人看到还没有达到让其主动脱离舒适区的程度)

基于以上现状,我们决定再进一步,重新捡起过往曾经动过,但受限于"思路过于新奇"而主动选择回避的念头:“扩展Skywalking,实现对于系统进行链路追踪功能的动态开启和关闭”。

之所以存在这么听上去很"神奇"的念头,当然是有着其现实原因:

  1. 该产品的大部分业务场景,其体量远远未达到需要上微服务架构的情况。
  2. 但现有的系统架构已经是微服务的模式。
  3. 于是矛盾就出现了:业务体量不是必须得微服务,那么用户势必不愿意在日常运维上投入太多的成本;但微服务架构经过多年的争论,终于用残酷的现实教育了所有将它当作马良神笔的从业者——别以为复杂度消失了。微服务只是将复杂度转移到基础设施上。CI/CD你没有,遭罪的是你自己,打碎牙你能自己咽;但链路追踪你要是没有,客户报告问题一般都是火急火燎赶deadline的时候,你猜他会不会和颜悦色跟你这演练"和人交流要讲礼貌"。

所以,如何在这个现状面前,找到那个平衡? 而不是直接把锅砸了,起一口新的。

截止写下此文的当下,我们交出的答卷如标题所示:通过skywalking提供的扩展,来增加我们自己的自定义逻辑,主动控制Agent端向Server端推送监控数据的方式,最小化监控这一块的运维成本,进而增加监控在团队里的落地范围和深度,尽可能地让其能够被绝大部分人作为日常工作中的一部分。

2. 需求描述

让我们用专门的小节描述下需求细节,也算是目标达成之后的操作流程。

  1. 默认情况下,Server端不启动,Agent端正常开启。不过Agent端基于我们的扩展配置,默认会直接丢弃所收集来的监控数据,不进行上报(毕竟你上报也没地方接收)。
  2. 发现问题时,开启Server端和开启agent端自定义配置,进入正常的链路追踪排错流程。
  3. 解决问题之后,关闭Server和Agent端自定义配置。(这一步为了确保执行,可在第二步的准备阶段,启动一个一次性定时任务)。

注意:
Server端启动时采用的存储是默认的h2数据库,这是为了减少在Server维护上的成本。也是因为使用h2数据库,注定了Server端不能常驻,或者说不能接收大量Agent端上报的数据,这就回到了本文出现的缘由。

3. 优势

我们过往在【CAT魔改】独立化cat-client的优势里所陈述的一系列诸如"站在巨人的肩膀上,更大的灵活性"等优势同样适合于这里。

除此之外,本次我们之所以接受这个魔改,根本目的是为了让团队尽早开始积累使用Skywalking的经验。一个产品想要长远发展,其所依赖的基础设施最好是稳固,经过千锤百炼的。毕竟你没有那么多的资源来将你的依赖项全部从零开发一遍;尽早确定一个稳定的基础依赖,不断对其精研,好过从零开始自己摸,也好过"看见这个觉得不错,看见那个好像更好"的狗熊掰棒子式地尝鲜式技术选型。

4. 实现

得益于Skywalking其所提供的强大扩展性,本次扩展功能实现过程异常地顺利。在没有系统阅读完Skywalking主体流程逻辑的前提下,只是通过借鉴Skywalking自身内置针对各个第三方组件的插件实现,编写个自定义Agent插件,就完成了本次需求。

不得不说Skywalking的扩展性确实好太多了。在以上实现自定义Agent插件过程中,笔者脑海里不时会回想起那句本以遗忘的经典教导 —— “对扩展开放,对修改关闭”。相较于笔者在过往迫不得已最终还是构建了分支版本的【CAT魔改】CAT-LOCAL项目的诞生,Skywalking真正做到了完全没有修改既有代码,真正采用扩展的方式实现。果然社区强大才是一切。

4.1 扩展点

以下直接列出需要被扩展的类型,具体的实现细节可以参见底部给出的gitee仓库。

扩展点 说明
TraceSegmentServiceClient Skywalking在其中进行收集来的监控链路数据上报。
GRPCChannelManager Skywalking在其中进行Server端的grpc验活。默认间隔30秒。
LogReportServiceClient Skywalking在其中进行收集来的监控日志数据上报。
JVMService Skywalking在其中实现定期地JVM状态数据上报。
EventReportServiceClient Skywalking在其中实现Java应用的启停等事件的上报。

4.2 配置项

针对上面的扩展,我们还需要一些skywalking提供的配置项进行支持。

# 确保我们开启Server和Agent端之后, Agent端可以将监控数据正确推送到Server端
-Dskywalking.collector.backend_service={
    
    SW_IP}:11800 \
# 同上。不过推送的是日志数据。
-Dskywalking.plugin.toolkit.log.grpc.reporter.server_host={
    
    SW_IP} \
# 本次扩展的目的是最大化减轻Server端的存储压力, 所以我们需要排除诸如健康状态检查等接口.
-Dskywalking.trace.ignore_path=**/acutator/**,**/swCustomPlugin/** \
# 兼容过往无服务端时的日志链路查询. 同时该配置项对于本次扩展也提供支持, 毕竟对于本文的需求场景而言, Server端大部分时候也是不存在的.
-Dskywalking.agent.keep_tracing=true

5. 优化

  1. 只限制特定的链路进行上报。这一步在底部的gitee项目里也给出了相应的示例类:TraceCaptureSpecialSamplingService
  2. 提供组件的可观测性。 这一步的主要实现逻辑参见Gitee - dynamic-enable-runtime 项目中的ReportStatusOfAgentPushToServerInterceptor实现。

6. Server端优化(2023-03-18补充)

上面小节部分的扩展实现和相应的优化,以及本文的主题也都是针对Agent端。本小节我们将扩展延申到Server端。

之所以以h2数据库作为存储单元的skywalking-oap不能存在太久,其主要原因是内存空间有限,而默认情况下Skywalking会保存三天之内的监控数据。

据此我们马上能够想到的不就是"我把这个间隔时间缩短不就完事了"?接下来我们就来实现这个思路。

扩展点 说明
H2HistoryDeleteDAO h2存储模式下,Skywalking-oap使用它来删除超期数据。
H2StorageConfig h2存储模式下,配置项对应的类型就是它。

具体的实现细节可以参见Gitee - storage-jdbc-h2-snapshot-plugin

注意:

  1. 在实际使用过程中,发现经过一段时间后,Server Collector端依然会出现内存溢出的情况。使用arthas等工具分析之后,发现是direct memory区域溢出导致的。
    在这里插入图片描述
    解决方案: 修改脚本oapService.bat / oapService.sh,增加-XX:MaxDirectMemorySize=64M配置项。
    set OAP_OPTS="-Xms256M -Xmx1024M -XX:MetaspaceSize=256M -XX:MaxMetaspaceSize=512m -XX:CompressedClassSpaceSize=128M -XX:MaxDirectMemorySize=64M -Doap.logDir=%OAP_HOME%\logs"
    

7. 提醒

  1. 本文这种方式下,对于Skywalking的使用就只限于可观测性三支柱的Tracing和Logging,就别奢望剩下的那条支柱的Metrics也生效了。
  2. 本文需求出现的前提条件是业务特点决定的。毕竟"所有的技术上的决策实际都是政治上的决策",我们必须面对这个现实。
  3. 我们对"系统有监控"的理解:是平时自己人排错的时候,会不会用到这些?毕竟按照产品设计的基本理念之"吃自己的狗粮",如果你自己都不用自己构建的监控体系,那这个叫做"系统有监控"吗
  4. 现实的矛盾就是"最小化运维和基础设施成本,与系统微服务架构之间的矛盾"。不要说什么这个玩意搭建起来花不了多少时间。运维这个职业存在多年,区分出不同的等级,要求还越来越高,是因为把这些玩意搭建起来很难吗?

8. 补充 - 关于微服务

过往我尝试总结了微服务的一些怪现象,也收集了不少相关的讨论(具体参见下面的链接)。

这里我想再表明一下个人看法,也算是对过往总结的一个补充:

“除非系统体量达到必须微服务,否则业务方绝对不会愿意在基础设施和运维上投入成本,只希望越少越好。即使是他将微服务的要求写在了招标文件里。你有一千条,一万条理由痛诉对方多么不专业,多么坑爹;但回到现实你依然还得解决这个问题;当然相较之下有个选择更简单:**客户,**公司,劳*不伺候了。”

9. 参考

  1. skywalking官网
  2. 吴晟 - 《SkyWalking的发展之路;从无名小卒到拥抱全球》
  3. 专访吴晟:开源没有黑魔法,两年后泡沫将会破灭
  4. 【CAT魔改】CAT-LOCAL项目的诞生
  5. 微服务了个寂寞
  6. 如何做好既有产品技术架构的升级改造
  7. Gitee - dynamic-enable-runtime
  8. Gitee - storage-jdbc-h2-snapshot-plugin

猜你喜欢

转载自blog.csdn.net/lqzkcx3/article/details/129433020