一. 現(xiàn)狀·問題
隨著需求不斷迭代,業(yè)務(wù)系統(tǒng)的業(yè)務(wù)代碼突飛猛進(jìn),在你自豪于自己的代碼量產(chǎn)出很高時(shí),有沒有回頭看看線上真正的客戶使用量又有多少呢?
費(fèi)事費(fèi)力耗費(fèi)大量人力成本上線的功能,可能一年沒人使用,如果不進(jìn)行適當(dāng)?shù)南戮€,就會(huì)增加系統(tǒng)維護(hù)成本,此時(shí)就需要計(jì)劃刪除無用代碼。但是我們?cè)趺粗勒鎸?shí)線上的一行行代碼層面,是否真實(shí)在使用,或者真實(shí)沒人用,怎么可以放心刪除下線功能呢!
二. 分析原因
實(shí)際上多數(shù)業(yè)務(wù)系統(tǒng)都會(huì)存在這個(gè)通?。壕€上僵尸代碼
- 可能是前期產(chǎn)品對(duì)業(yè)務(wù)場(chǎng)景沒有分析到位
- 可能是研發(fā)期間需求功能偏離了正確方向
- 可能是上線后因外界因素使客戶業(yè)務(wù)量下降
- ······
三. 采取措施
問產(chǎn)品經(jīng)理哪些能下線?NO 沒人敢承諾
觀測(cè) UMP接口是否有流量?NO 只知道接口維度,有流量的接口難道所有代碼都有用么
使用jacoco(Java Code Coverage)進(jìn)行線上代碼分析,對(duì)系統(tǒng)做瘦身。
Jacoco本質(zhì)上是一個(gè)測(cè)試覆蓋率工具,通過ASM字節(jié)碼增強(qiáng)技術(shù)在源代碼中加入探針從而獲取代碼覆蓋率。Jacoco主要是通過Jave agent在main函數(shù)執(zhí)行之前通過指定方法在執(zhí)行的代碼中加入探針來記錄代碼是否被執(zhí)行過。
Java agent是Java提供的一個(gè)啟動(dòng)參數(shù),有別于代理方式的動(dòng)態(tài)增強(qiáng)和annotation processor的編譯時(shí)增強(qiáng),該參數(shù)通過指定路徑的jar包中的premain方法將在main方法執(zhí)行之前被調(diào)用增強(qiáng)源代碼,通過實(shí)現(xiàn)該方法我們可以對(duì)加載的Class文件進(jìn)行修改源代碼增強(qiáng),使用此技術(shù)的還有大部分APM工具。
https://www.jacoco.org/jacoco/trunk/doc/index.html
四. 實(shí)踐步驟
4.1 依賴jacoco.ant
在工程內(nèi)的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請(qǐng)求
添加一個(gè)url地址,通過ant執(zhí)行dump task用于Dump Coverage文件,避免使用配置文件且同時(shí)需要運(yùn)維同事幫忙操作的問題。
@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);
// 選一個(gè)空閑接口即可
dumpTask.setPort(8840);
// 默認(rèn)本機(jī)
dumpTask.setAddress("127.0.0.1");
dumpTask.execute();
return Result.succeed(true);
}
}
4.3 嵌入jacocoagent
由于jacoco需要在服務(wù)端由jacocoagent增強(qiáng)的jar包,為了避免需要麻煩運(yùn)維同事,通過maven依賴我們可以發(fā)現(xiàn)org.jacoco.agent這個(gè)jar包中包含由jacocoagent這個(gè)包,所以通過在部署的啟動(dòng)腳本添加以下命令即可通過解壓的方式獲得該jar包!
java啟動(dòng)參數(shù)添加如下:存在多個(gè)javaagent時(shí)比如pfinder之類在其后添加即可。
#decompress file 解壓依賴,獲得jacocoagent.jar包,避免需要聯(lián)系運(yùn)維上傳包
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接口的實(shí)現(xiàn)類,該接口中僅有一個(gè)方法如下,通過實(shí)現(xiàn)ClassTransformer我們可以定義自己的代碼增強(qiáng)方法??梢允褂肁SM,亦可以使用javasist等高級(jí)類庫。
相關(guān)實(shí)踐:Diving Into Bytecode Manipulation: Creating an Audit Log With ASM and Javassist | New Reli
4.4 JDOS資源預(yù)留
資源預(yù)留/export目錄自定義處理
- 增加配置腳本 /home/admin/clean_export.sh(腳本默認(rèn)內(nèi)容上增加了 && $9 != "coverage")
輸出的文件路徑為/export/Data/coverage/code-cover.exec
#! /bin/bash
ls -lh /export | awk 'NR >1 {print}' | awk '{if ($9 != "Data") print $9}' | xargs -i /bin/rm -rf /export/{} > /dev/null 2>&1
ls -lh /export/Data | awk 'NR >1 {print}' | awk '{if ($9 != "jdos.jd.com" && $9 != "coverage") print $9}' | xargs -i /bin/rm -rf /export/Data/{} > /dev/null 2>&1
4.5 下載cover文件
/export/Data/coverage/code-cover.exec
登錄堡壘機(jī)終端
cd /export/Data/coverage
jdos下載文件
curl -s up.bastion.jd.com/file/up | bash
4.6 分析代碼
打開idea -> run -> show coverage data選擇對(duì)應(yīng)的exec文件即可獲取服務(wù)端的代碼覆蓋情況。
綠色覆蓋(活躍代碼)
紅色未覆蓋(僵尸代碼)
Reference
- JaCoCo - Documentatio
- javaagent使用指南 - rickiyang - 博客園 (cnblogs.com
- 使用Jacoco統(tǒng)計(jì)服務(wù)端代碼覆蓋情況實(shí)踐 - M104 - 博客園 (cnblogs.com
- Diving Into Bytecode Manipulation: Creating an Audit Log With ASM and Javassist | New Reli
五. 效能提升
5.1 需求交付效率提升
5.1.1 縮短需求交付周期
因?yàn)榻┦a刪除,減少開發(fā)需求的范圍,降低老代碼認(rèn)知成本,降低測(cè)試回歸成本。
需求交付周期整體呈縮短趨勢(shì)!2023/1月落地實(shí)踐,之前需求交付周期約15天,之后約12天。
5.1.2 降低開發(fā)階段停留時(shí)長(zhǎng)
僵尸代碼大量存在,研發(fā)認(rèn)知需求改動(dòng)點(diǎn)負(fù)荷很高,需要耗費(fèi)大量時(shí)間成本。
2023/1月落地后,開發(fā)階段時(shí)長(zhǎng)縮短到 4天 以下(由 4.54 縮短至 3.11,縮短約31%),呈明顯縮短趨勢(shì)!
5.2 人效提升
5.2.1 降低研發(fā)認(rèn)知負(fù)荷
刪除無用僵尸代碼,圈復(fù)雜度會(huì)大幅度降低,重復(fù)代碼塊也會(huì)降低,則研發(fā)認(rèn)知負(fù)荷也會(huì)隨之降低!
平均系統(tǒng)重復(fù)代碼塊數(shù)從 31 下降至 27 左右,降低了系統(tǒng)維護(hù)成本!
5.2.2 提升人均需求吞吐量
因?yàn)闇p少人力認(rèn)知成本,縮小需求范圍,所以會(huì)直接提升需求的吞吐量!
自從2023/1月落地實(shí)踐后,人均需求的吞吐量也大幅度提升,從之前 1.5 提升到 2.5 左右。
5.3 過程質(zhì)量提升
5.3.1 減少自動(dòng)化bug數(shù)
由于存量僵尸代碼減少,則整體回滾用例和場(chǎng)景變得精簡(jiǎn),黃金流程也不會(huì)被僵尸代碼干擾,則自動(dòng)化bug數(shù)也有明顯下降趨勢(shì)!
隨著2023年1月以來的不斷實(shí)踐,自動(dòng)化發(fā)現(xiàn)的bug數(shù)也逐月遞減,從11個(gè)/月 -> 9個(gè)/月 -> 6個(gè)/月 -> 5個(gè)/月。
5.3.2 提升單測(cè)覆蓋率
自從2023年1月落地實(shí)踐后,隨著刪除掉大量僵尸代碼,整體代碼總量在減少,無效代碼被無情下線,同時(shí)提升了單測(cè)代碼覆蓋率,呈上升趨勢(shì)!單測(cè)行覆蓋率從 51.33% -> 52.28%,提升系統(tǒng)質(zhì)量!
六. 簡(jiǎn)要總結(jié)
- 隨著需求不斷迭代交付,業(yè)務(wù)代碼必然不斷累積,運(yùn)維成本不斷升高,如果線上無用功能的代碼一直殘留,對(duì)研發(fā)來說是巨大的累贅!對(duì)于此類代碼約定俗成為 “僵尸代碼”。
- 趕快利用jacoco探針深入分析系統(tǒng)的一行行代碼,看到線上功能運(yùn)行最真實(shí)的一面,參照代碼的覆蓋情況,針對(duì)性下線和刪除僵尸代碼,讓系統(tǒng)瘦身,讓研發(fā)減負(fù)!
作者:京東物流?周奕儒文章來源:http://www.zghlxwxcb.cn/news/detail-646478.html
來源:京東云開發(fā)者社區(qū) 自猿其說Tech文章來源地址http://www.zghlxwxcb.cn/news/detail-646478.html
到了這里,關(guān)于JaCoCo助您毀滅線上僵尸代碼的文章就介紹完了。如果您還想了解更多內(nèi)容,請(qǐng)?jiān)谟疑辖撬阉鱐OY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!