为什么我没有选 SkyWalking,而是自己写了一个 Java 方法级监控探针
这是一次真实的工程决策复盘,而不是“为了造轮子而造轮子”。
一、背景:APM 很强,但并不总是“合适”
在很多 Java 项目中,只要一提到线上监控,大家第一反应往往是:
- SkyWalking
- Zipkin
- OpenTelemetry
- Prometheus + Exporter
这些工具都非常成熟,也非常强大,这一点毫无疑问。
但在我最近处理的几个线上问题中,我逐渐意识到一个现实矛盾:
我并不需要一整套“全链路 APM”,
我只想知道:某几个关键方法,到底慢在哪、有没有异常。
正是这个需求,最终让我没有选现成的 APM,而是选择自己实现一个轻量级 Java 方法监控探针。
二、我遇到的真实问题(其实很常见)
典型场景如下:
- 老项目,历史包袱重
- 核心方法调用链并不复杂
- 但存在 偶发慢、偶发异常
- 日志分散,排查成本高
- 全量 APM 的接入和运行成本又显得“过重”
我真正想要的是:
- 精确监控 指定的方法
- 不侵入业务代码
- 不强制引入完整 Trace / Span 模型
- 性能影响可控
- 数据上报方式可自由扩展(HTTP / Kafka / Log 等)
而不是直接引入一整套平台级 APM。
三、APM vs 方法级监控:不是对立,而是取舍
后来我把需求拆解后发现,这两类方案本质上解决的是不同层级的问题。
APM 更适合的场景:
- 微服务体系
- 分布式调用复杂
- 需要完整的 Trace / Span 视角
- 有成熟的可观测性体系
- 可以接受一定的运行时开销
方法级监控更适合的场景:
- 单体或中小规模服务
- 已明确存在问题的“热点方法”
- 更关注 执行耗时、异常、关键参数
- 对性能和侵入性高度敏感
- 希望“随用随加、随时可控”
这并不是谁更高级的问题,而是工程成本与收益的权衡。
四、为什么我最终选择“自己写一个探针”
总结下来,核心原因其实只有四点。
1️⃣ 只监控被明确标记的方法
我不希望:
- 所有 Controller 都被采集
- 所有 RPC 自动进入链路
- 所有方法都产生监控数据
我希望的使用方式是:
@Monitored
public Order createOrder(...) {
...
}
只有被标记的方法才会被增强和采集,其余路径零开销。
2️⃣ 探针必须无感知、可拔插
不改业务代码
不侵入框架
出现问题可以直接关闭
Java Agent + 字节码增强,天然满足这些要求。
3️⃣ 数据上报方式必须可控
我不希望监控数据:
-
被强绑定到某一个平台
-
或只能通过某一种协议
因此在设计上,我将结构拆分为:
-
Agent(采集)
-
Reporter(SPI 上报接口)
-
HTTP、Kafka、日志、Prometheus

你想怎么接,就怎么接。
4️⃣ 性能影响是第一优先级
在工程实践中:
-
监控本身,不能成为性能问题的一部分。
-
因此我刻意控制了以下几点:
-
仅在方法入口 / 出口进行增强
-
监控数据异步、批量上报
-
上报失败直接降级,不影响业务线程
五、这是不是“重复造轮子” ?
这是我被问得最多的一个问题。
我的回答是:
如果目标是“替代 APM”,那确实是造轮子;
但如果目标是“解决特定工程问题”,那是工程判断。
事实上:
-
APM 解决的是 可观测性体系问题
-
方法级探针解决的是 工程可控性问题
-
两者并不冲突,甚至可以同时存在。
六、这个探针目前能做什么?
目前已经支持的能力包括:
- 方法级耗时统计
- 成功 / 异常状态标识
- 入参 / 返回值采集(可配置)
- Reporter SPI 扩展机制
- Java Agent 无侵入接入
它的定位非常明确:
它不是一个 APM,
而是一个“工程师可控的监控工具”。
七、如果你也有类似困惑,可以看看这个实现
在上一篇文章中,我详细介绍了这个探针的整体设计和实现思路,包括:
- 为什么没有选择现成 APM
- Java Agent 的设计取舍
- Reporter SPI 的抽象方式
- 性能控制与降级策略
👉 上一篇文章:
《我做了一个轻量级 Java 方法监控探针,解决了这些线上问题》
八、后续我还计划写什么?
后续会继续补充以下内容:
- Java Agent 对性能影响的实测数据
- 与 SkyWalking / OpenTelemetry 的具体差异对比
- 方法级监控在实际工程中的使用边界
- 探针与 Prometheus / Grafana 的组合方式
- 如果你也遇到过类似问题,欢迎交流。
更多推荐
所有评论(0)