一 。现状?问题
随着需求不断迭代,业务系统的业务代码突飞猛进,在你自豪于自己的代码量产出很高时,有没有回头看看线上真正的客户使用量又有多少呢?
~ 费事费力耗费大量人力成本~上线的功能,可能一年没人使用,如果不进行适当的下线,就会增加系统维护成本,此时就需要计划删除无用代码 。但是我们怎么知道真实线上的一行行代码层面,是否真实在使用,或者真实没人用,怎么可以放心删除下线功能呢!
二 。分析原因实际上多数业务系统都会存在这个通病:线上僵尸代码
- 可能是前期产品对业务场景没有分析到位
- 可能是研发期间需求功能偏离了正确方向
- 可能是上线后因外界因素使客户业务量下降
- ······
观测 UMP 接口是否有流量?NO 只知道接口维度,有流量的接口难道所有代码都有用么
使用 jacoco(JAVA Code Coverage)进行线上代码分析,对系统做瘦身 。
Jacoco 本质上是一个测试覆盖率工具,通过 ASM 字节码增强技术在源代码中加入探针从而获取代码覆盖率 。Jacoco 主要是通过 Jave agent 在 mAIn 函数执行之前通过指定方法在执行的代码中加入探针来记录代码是否被执行过 。
Java agent 是 Java 提供的一个启动参数,有别于代理方式的动态增强和 annotation processor 的编译时增强,该参数通过指定路径的 jar 包中的 premain 方法将在 main 方法执行之前被调用增强源代码,通过实现该方法我们可以对加载的 Class 文件进行修改源代码增强,使用此技术的还有大部分 APM 工具 。https://www.jacoco.org/jacoco/trunk/doc/index.html
四 。实践步骤4.1 依赖 jacoco.ant
在工程内的 pom 中引入 jar 依赖
<dependency>
<groupId>org.jacoco</groupId>
<artifactId>org.jacoco.ant</artifactId>
<version>0.8.3</version>
</dependency>
<dependency>
<groupId>org.Apache.ant</groupId>
<artifactId>ant</artifactId>
<version>1.9.9</version>
</dependency>
4.2 赋能 Rest 请求
添加一个 url 地址,通过 ant 执行 dump task 用于 Dump Coverage 文件,避免使用配置文件且同时需要运维同事帮忙操作的问题 。
@RestController
@RequestMApping("/coverage")
public class CoverageController {
@PostMapping("dump")
@NoCheckMenuPermission
public Result<Boolean> dumpCoverageFile() {
DumpTask dumpTask = new DumpTask();
// dump文件地址
dumpTask.setDestfile(new File("/export/Data/coverage/code-cover.exec"));
// 多次dump追加形式
dumpTask.setAppend(true);
// 选一个空闲接口即可
dumpTask.setPort(8840);
// 默认本机
dumpTask.setAddress("127.0.0.1");
dumpTask.execute();
return Result.succeed(true);
}
}
4.3 嵌入 jacocoagent
由于 jacoco 需要在服务端由 jacocoagent 增强的 jar 包,为了避免需要麻烦运维同事,通过 maven 依赖我们可以发现 org.jacoco.agent 这个 jar 包中包含由 jacocoagent 这个包,所以通过在部署的启动脚本添加以下命令即可通过解压的方式获得该 jar 包!
java 启动参数添加如下:存在多个 javaagent 时比如 pfinder 之类在其后添加即可 。
#decompress file 解压依赖,获得jacocoagent.jar包,避免需要联系运维上传包
jar -xvf $BASEDIR/lib/org.jacoco.agent-0.8.3.jar
-javaagent:$BASEDIR/bin/jacocoagent.jar=includes=com.jdwl.*,output=tcpserver,port=8840,address=127.0.0.1 -Xverify:none
文章插图
premain 方法中我们可以通过 Instrumention 的 addTransformer 添加 ClassFileTransformer 接口的实现类,该接口中仅有一个方法如下,通过实现 ClassTransformer 我们可以定义自己的代码增强方法 。可以使用 ASM,亦可以使用 javasist 等高级类库 。
相关实践:Diving Into Bytecode Manipulation: Creating an Audit Log With ASM and Javassist | New Reli4.4 JDOS 资源预留
资源预留 /export 目录自定义处理
- 增加配置脚本 /home/admin/clean_export.sh(脚本默认内容上增加了 && $9 != "coverage")
#! /bin/bash
【JaCoCo 助您毁灭线上僵尸代码】ls -lh /export | awk 'NR >1 {print}' | awk '{if ($9 != "Data") print $9}' | xargs -i /bin/rm -rf /export/{} > /dev/null 2>&1
推荐阅读
- 一份重庆美食攻略,帮助您发掘这座城市的美食宝藏。
- 三种可视化方法帮助您轻松理解Docker Compose架构
- “奶油小生”陈浩民的毁灭史,他的故事远比你想得还要精彩!
- 妖精的尾巴公会被毁灭
- 富婆|白马会所毁灭史回顾:让无数富婆痴迷向往,却因“鸭王”一夜倒闭
- 傅艺伟|傅艺伟的毁灭史:从“最美妲己”到“阶下囚”,她到底做错了啥?
- 硅谷预言家安德森万字长文:人工智能不会毁灭世界,反而可能拯救世界
- 杨乐乐|杨乐乐毁灭史:从“湖南一姐”到“万人唾”,她都做了什么事?
- 张一山|张一山的“毁灭史”,他的故事比你想象的更恶劣
- 庞贝古城的毁灭是由哪种自然灾害导致的 庞贝城的毁灭