SpringBoot實戰電商項目mall(35k+star)地址:github.com/macrozheng/…java
線上項目遇到問題沒法調試,線下又沒法重現,難道只能加日誌再從新發布麼?有了這款神器,既能夠線上調試,又能夠實現熱修復,推薦給你們!git
Arthas是Alibaba開源的Java診斷工具,深受開發者喜好。它採用命令行交互模式,同時提供豐富的 Tab 自動補全功能,進一步方便進行問題的定位和診斷。github
爲了還原一個真實的線上環境,咱們將經過Arthas來對Docker容器中的Java程序進行診斷。docker
使用arthas-boot
,下載對應jar包,下載地址:alibaba.github.io/arthas/arth…json
將咱們的Spring Boot應用mall-tiny-arthas
使用Docker容器的方式啓動起來,打包和運行腳本在項目的src\main\docker
目錄下;api
將arthas-boot.jar
拷貝到咱們應用容器的\
目錄下;bash
docker container cp arthas-boot.jar mall-tiny-arthas:/
複製代碼
arthas-boot
,直接當作jar包啓動便可;docker exec -it mall-tiny-arthas /bin/bash
java -jar arthas-boot.jar
複製代碼
1
,就能夠開始診斷了;咱們先來介紹一些Arthas的經常使用命令,會結合實際應用來說解,帶你們瞭解下Arthas的使用。服務器
使用dashboard
命令能夠顯示當前系統的實時數據面板,包括線程信息、JVM內存信息及JVM運行時參數。app
查看當前線程信息,查看線程的堆棧,能夠找出當前最佔CPU的線程。工具
經常使用命令:
# 打印當前最忙的3個線程的堆棧信息
thread -n 3
# 查看ID爲1都線程的堆棧信息
thread 1
# 找出當前阻塞其餘線程的線程
thread -b
# 查看指定狀態的線程
thread -state WAITING
複製代碼
查看當前JVM的系統屬性,好比當容器時區與宿主機不一致時,可使用以下命令查看時區信息。
sysprop |grep timezone
複製代碼
user.timezone Asia/Shanghai
複製代碼
查看JVM的環境屬性,好比查看下咱們當前啓用的是什麼環境的Spring Boot配置。
使用logger
命令能夠查看日誌信息,並改變日誌級別,這個命令很是有用。
好比咱們在生產環境上通常是不會打印DEBUG
級別的日誌的,當咱們在線上排查問題時能夠臨時開啓DEBUG
級別的日誌,幫助咱們排查問題,下面介紹下如何操做。
INFO
級別的日誌,使用logger
命令能夠查看;DEBUG
,須要使用-c
參數指定類加載器的HASH值;logger -c 21b8d17c --name ROOT --level debug
複製代碼
logger
命令查看,發現ROOT
級別日誌已經更改;docker logs -f mall-tiny-arthas
命令查看容器日誌,發現已經打印了DEBUG級別的日誌;INFO
級別。logger -c 21b8d17c --name ROOT --level info
複製代碼
查看JVM已加載的類信息,Search-Class
的簡寫,搜索出全部已經加載到 JVM 中的類信息。
com.macro.mall
包下全部的類;sc com.macro.mall.*
複製代碼
-d
參數並指定全限定類名;sc -d com.macro.mall.tiny.common.api.CommonResult
複製代碼
-f
參數。sc -d -f com.macro.mall.tiny.common.api.CommonResult
複製代碼
查看已加載類的方法信息,Search-Method
的簡寫,搜索出全部已經加載的類的方法信息。
sm com.macro.mall.tiny.common.api.CommonResult
複製代碼
-d
參數並指定方法名稱;sm -d com.macro.mall.tiny.common.api.CommonResult getCode
複製代碼
反編譯已加載類的源碼,以爲線上代碼和預期不一致,能夠反編譯看看。
ClassLoader
信息;jad com.macro.mall.tiny.MallTinyApplication
複製代碼
--source-only
參數能夠只打印類信息。jad --source-only com.macro.mall.tiny.MallTinyApplication
複製代碼
內存編譯器,Memory Compiler
的縮寫,編譯.java
文件生成.class
。
加載外部的.class
文件,覆蓋掉 JVM中已經加載的類。
實時監控方法執行信息,能夠查看方法執行成功此時、失敗次數、平均耗時等信息。
monitor -c 5 com.macro.mall.tiny.controller.PmsBrandController listBrand
複製代碼
方法執行數據觀測,能夠觀察方法執行過程當中的參數和返回值。
使用以下命令觀察方法執行參數和返回值,-x
表示結果屬性遍歷深度。
watch com.macro.mall.tiny.service.impl.PmsBrandServiceImpl listBrand "{params,returnObj}" -x 2
複製代碼
儘管在線上環境熱更代碼並非一個很好的行爲,但有的時候咱們真的很須要熱更代碼。下面介紹下如何使用
jad/mc/redefine
來熱更新代碼。
id<=0
時,會拋出IllegalArgumentException
;/** * 品牌管理Controller * Created by macro on 2019/4/19. */
@Api(tags = "PmsBrandController", description = "商品品牌管理")
@Controller
@RequestMapping("/brand")
public class PmsBrandController {
@Autowired
private PmsBrandService brandService;
private static final Logger LOGGER = LoggerFactory.getLogger(PmsBrandController.class);
@ApiOperation("獲取指定id的品牌詳情")
@RequestMapping(value = "/{id}", method = RequestMethod.GET)
@ResponseBody
public CommonResult<PmsBrand> brand(@PathVariable("id") Long id) {
if(id<=0){
throw new IllegalArgumentException("id not excepted id:"+id);
}
return CommonResult.success(brandService.getBrand(id));
}
}
複製代碼
{
"timestamp": "2020-06-12T06:20:20.951+0000",
"status": 500,
"error": "Internal Server Error",
"message": "id not excepted id:0",
"path": "/brand/0"
}
複製代碼
id<=0
時,直接返回空數據的CommonResult
,代碼修改內容以下;/** * 品牌管理Controller * Created by macro on 2019/4/19. */
@Api(tags = "PmsBrandController", description = "商品品牌管理")
@Controller
@RequestMapping("/brand")
public class PmsBrandController {
@Autowired
private PmsBrandService brandService;
private static final Logger LOGGER = LoggerFactory.getLogger(PmsBrandController.class);
@ApiOperation("獲取指定id的品牌詳情")
@RequestMapping(value = "/{id}", method = RequestMethod.GET)
@ResponseBody
public CommonResult<PmsBrand> brand(@PathVariable("id") Long id) {
if(id<=0){
// throw new IllegalArgumentException("id not excepted id:"+id);
return CommonResult.success(null);
}
return CommonResult.success(brandService.getBrand(id));
}
}
複製代碼
PmsBrandController
類代碼進行修改,接着上傳到服務器,而後使用以下命令將java
文件拷貝到容器的/tmp
目錄下;docker container cp /tmp/PmsBrandController.java mall-tiny-arthas:/tmp/
複製代碼
sc -d *PmsBrandController | grep classLoaderHash
複製代碼
.java
文件編譯成.class
文件,注意須要使用-c
指定類加載器;mc -c 21b8d17c /tmp/PmsBrandController.java -d /tmp
複製代碼
redefine
命令加載.class
文件,將原來加載的類覆蓋掉;redefine -c 21b8d17c /tmp/com/macro/mall/tiny/controller/PmsBrandController.class
複製代碼
{
"code": 200,
"message": "操做成功",
"data": null
}
複製代碼
官方文檔:alibaba.github.io/arthas/
mall項目全套學習教程連載中,關注公衆號第一時間獲取。