關於 dble 小版本修改代碼的熱更新,主要調研了兩種工具:
arthasjrebel使用 arthas 更新小版本時,需要運維人員直接操作變更的 class 文件並修改,需要一套運維規範。
使用 jrebel 後,jrebel 可以對 dble 的 jar 包配置一個 class 目錄,jrebel 自動監聽 class 目錄中 class 文件的變化,監聽到變化後自動加載類,此外該軟體需要付費。
在進行小版本升級時,需要控制 dble 的版本號,因此每次熱更新時需要替換 Versions.class 文件維護 dble 的版本號,經測試,發現 jrebel 對靜態類的支持並不友好,實際測試沒有生效,相比較而言 arthas 則可以生效。因此下面主要對 arthas 在 dble 中的使用進行說明。
前置環境
jre,使用 dble 的 jre 即可搭建好的 3.20.10.0 版本 dble 環境
arthas 使用
安裝
下載最新版本即可,以下測試使用的是 3.4.5 版本
使用
執行下面的語句後,會進入 arthas 的交互界面:
$ java -jar arthas-boot.jar <dble_pid>
下面以在 dble 中簡單修改一行日誌為例:
在 3.20.10.0 版本的 dble 中,當輸入"optimize a; " 這種 dble 不認識的語句時,日誌中會輸出 「Unsupported statement:optimize a」 這樣的日誌,如下圖:
下面我們通過 arthas 修改這個日誌輸出,以下操作都是在 arthas 的命令行界面操作。
jad 反編譯
$ jad --source-only com.actiontech.dble.server.ServerQueryHandler > /tmp/ServerQueryHandler.java
下面是反編譯文件裡面截取的相關代碼片段:
case 254: {
LOGGER.info("Unsupported statement:" + sql);
this.service.writeErrMessage(1149, "Unsupported statement");
return;
}
sc 查找類加載器
$ sc -d com.actiontech.dble.server.ServerQueryHandler | grep classLoaderHash
classLoaderHash 18b4aac2
mc 內存編譯
在編譯之前可以將之前反編譯源碼文件裡的代碼修改掉,比如修改為如下片段:
LOGGER.info("Unsupported statement test test test test test:" + sql);
下面我們通過 mc 命令將修改後的反編譯源碼文件編譯為 class 文件。
mc 命令中 -c 後面的值 18b4aac2 即 sc 查找到的 ServerQueryHandler 類加載器的 hash 值。
redefine 熱更新代碼
其實在這裡我們也可以通過在本地修改對應版本的源文件,本地編譯好後上傳到路徑下,再執行 redefine,效果是一樣的:
$ redefine /tmp/com/actiontech/dble/server/ServerQueryHandler.class
redefine success, size: 1, classes:
com.actiontech.dble.server.ServerQueryHandler
到此為止,ServerQueryHandler 類的更新就結束了。下面我們來看下效果:
以上方式是通過 arthas 的交互界面的方式完成的,arthas 也可以通過非交互方式來執行命令:
$ java -jar arthas-boot.jar <dble_pid> -c "redefine /tmp/com/actiontech/dble/server/ServerQueryHandler.class" > /dev/null
通過此方式,可以更方便的通過腳本管理整個流程。