无标题文档
来源:无标题文档
面试官:如何设计一个对业务代码零侵入的通用“方法耗时监控”
链接: https://pan.baidu.com/s/1V2r6454aHgvaRxtQEK25eg?pwd=7wy4 提取码: 7wy4
兄弟们,凌晨三点被生产事故叫醒是什么感觉?
订单接口从 200 毫秒飙到 3 秒,监控平台只告诉你"接口慢了",但具体是哪里慢?数据库?还是第三方接口超时?完全看不出来!
今天我就教你如何设计一套生产级的零侵入监控系统,这可是阿里 P7 面试必考题!大家一定要看到最后!
【第1页:问题引入 - 30秒】
(切换到第1页)
先来看两种监控方案,你会选哪个?
左边这种(指向左边),你要在每个方法里手写监控代码:long start = 开始时间,try-catch-finally,然后打日志。哥们儿,你们公司有多少个方法?几百个?每个都这么改?改到怀疑人生!
再看右边(指向右边),只需要加一个 @Monitor 注解,业务代码保持纯净,啥都不用改!监控逻辑自动生效!
这就是零侵入的威力!但是,面试官可不会让你这么轻松过关...
【第2页:深入理解 - 25秒】
(切换到第2页)
面试官真正想考察的是什么?三个点!
第一,你真的理解"零侵入"吗? 不是少侵入,而是业务代码完全感知不到监控的存在!
第二,你知道 Spring AOP 的边界在哪吗? 什么场景能用,什么场景不能用?
第三,这是工程化思维的考验! 不只是"能跑",还要考虑性能、异常、动态配置!
你看左边这个错误理解(指向左边),业务方法里还要调用 MonitorUtil.start(),这叫零侵入吗?这叫换了个地方侵入!
真正的零侵入(指向右边),业务代码里连监控的影子都看不到!
【第3页:第一层回答 - 35秒】
(切换到第3页)
好,那我们来看第一层回答,也就是及格线!
三步走:第一步,定义注解(指向步骤1),就是一个简单的 @Monitor 注解;
第二步,写切面(指向步骤2),用 Spring AOP 的 @Around 环绕通知,记录开始时间,执行业务方法,计算耗时;
第三步,加注解(指向步骤3),在业务方法上加 @Monitor,搞定!
你看这个流程图(指向流程图),就是调用方法 → AOP 拦截 → 记录时间 → 执行业务 → 计算耗时 → 上报监控,一气呵成!
但是!面试官会追问(指向问题卡片):如果要监控 static 方法呢?第三方 jar 包呢?高并发下直接打日志会不会拖垮 I/O?
【第4页:AOP的局限性 - 25秒】
(切换到第4页)
来看这个表格(指向表格),Spring AOP 只能拦截 Spring Bean 的 public 方法!
private 方法?不行! static 方法?不行! 第三方 jar 包?不行!
那怎么办?用 Java Agent + 字节码增强!
你看下面这个决策树(指向决策树),业务方法用 Spring AOP,覆盖 90% 的场景;第三方库、工具类用 Java Agent,这才是生产级的完整方案!
【第5页:Java Agent - 30秒】
(切换到第5页)
什么是 Java Agent?简单说,就是 JVM 在类加载时,自动修改字节码,注入监控逻辑!
三步走:第一步(指向步骤1),写一个 Agent 入口类,用 ByteBuddy 拦截所有带 @Monitor 注解的方法;
第二步(指向步骤2),写拦截器,记录耗时并异步上报;
第三步(指向步骤3),启动应用时加上 -javaagent 参数,搞定!
你看这个对比表(指向表格),Spring AOP 只能拦截 Spring Bean,Java Agent 可以拦截所有类,包括 static、private、第三方库!这才是 APM 系统的底层原理!
【第6页:异步上报 - 35秒】
(切换到第6页)
好,现在来解决第二个问题:性能优化!
如果你在切面里直接调用 HTTP 接口上报监控数据(指向左边),同步阻塞啊兄弟! 监控平台挂了,你的业务也跟着挂!
正确做法(指向右边):把监控数据扔到内存队列,立即返回!后台有个异步线程每秒批量消费 500 条,发送到 Prometheus!
你看这个架构图(指向架构图),切面层只负责扔队列,异步线程负责批量发送,业务线程零感知!
再看这个实现代码(指向代码块),用 BlockingQueue,队列满了直接 offer,满了就丢弃,绝不阻塞业务! 记住这个原则:宁可丢监控数据,也不能拖累业务!
【第7页:采样策略 - 25秒】
(切换到第7页)
第二个性能优化:采样策略!
对于每秒调用上万次的超高频方法,比如缓存读取,全量监控意义不大,还会产生海量数据!
你看这三种策略(指向特性卡片):固定比例采样,只监控 1%;慢请求全量,超过阈值的 100% 监控;动态调整,根据 QPS 自动调整采样率!
再看这个表格(指向表格),通过采样,数据量直接降低 99%! 比如 5 万 QPS 的缓存读取,采样 0.1% 后,每秒只产生 50 条监控数据!
【第8页:异常隔离 - 30秒】
(切换到第8页)
第三个核心问题:异常隔离!
如果监控代码自己抛异常了,会不会导致业务方法执行失败?这是致命问题!
你看这个完整实现(指向代码块),有三层防护:
第一层(指向防护1),业务方法抛的异常,必须原样抛出,不能被监控逻辑吞掉!
第二层(指向防护2),监控代码的异常,必须全部捕获,只记日志,不向上传播!
第三层(指向防护3),队列满了直接丢弃,绝不阻塞业务线程!
记住这个核心原则(指向高亮框):监控代码的任何异常,都不能传播到业务层!宁可不监控,也不能影响业务稳定性!
【第9页:生产级特性 - 30秒】
(切换到第9页)
好,现在你已经掌握了核心原理,但是从"能用"到"好用",还需要三个生产级特性!
第一(指向步骤1),动态配置!通过 Nacos 或 Apollo 热更新监控开关,无需重启服务!
第二(指向步骤2),阈值告警!方法耗时超过 1 秒,自动发钉钉、邮件、短信!
第三(指向步骤3),监控平台集成!对接 Prometheus、Grafana、SkyWalking,实现全链路追踪!
你看这个完整链路(指向架构图),从业务方法到可视化,一条龙服务!这才是生产级的监控系统!
【第10页:总结 - 30秒】
(切换到第10页)
最后总结一下,面试回答分三个层次:
第一层(指向第一张卡片),会用 Spring AOP,写个切面打日志,这是及格线,Demo 级别;
第二层(指向第二张卡片),异步上报、异常隔离、采样策略、字节码增强,这是优秀水平,体现工程化思维;
第三层(指向第三张卡片),动态配置、阈值告警、平台集成、全链路追踪,这是卓越水平,生产级方案!
记住这六个核心点(指向下面的架构图):零侵入、AOP+Agent、异常隔离、异步上报、动态配置、监控集成!
【收尾 - 20秒】
好了,今天的内容就到这里!
“如果今天的内容对你有启发,别忘了点赞、收藏、加关注,不然一划走就找不到了!”
“有需要这套方案的完整文章和PPT资料的兄弟,私信“方法耗时监控”,我会把相关资料毫无保留的发给你!”
感谢大家的观看!下期视频我们再见,拜拜~”