https://github.com/alibaba/arthashttps://github.com/alibaba/arthas/blob/master/README_CN.mdhttps://www.cnkirito.moe/arthas-redefine/https://manuals.jrebel.com/jrebel/standalone/maven.htmlhttps://manuals.jrebel.com/jrebel/advanced/launch-quick-start.html#quick-start
關於 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 使用安裝
下載地址:https://github.com/alibaba/arthas/releases,下載最新版本即可,以下測試使用的是 3.4.5 版本
$ cd /opt/arthas$ wget https://github.com/alibaba/arthas/releases/download/arthas-all-3.4.5/arthas-bin.zip$ unzip arthas-bin.zip
其他安裝方式請參考:https://arthas.aliyun.com/doc/install-detail.html
使用
執行下面的語句後,會進入 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 classLoaderHashclassLoaderHash 18b4aac2
mc 記憶體編譯
在編譯之前可以將之前反編譯原始碼檔案裡的程式碼修改掉,比如修改為如下片段:
case 254: { LOGGER.info("Unsupported statement test test test test test:" + sql); this.service.writeErrMessage(1149, "Unsupported statement"); return;}
下面我們透過 mc 命令將修改後的反編譯原始碼檔案編譯為 class 檔案。
mc 命令中 -c 後面的值 18b4aac2 即 sc 查詢到的 ServerQueryHandler 類載入器的 hash 值。
redefine 熱更新程式碼
其實在這裡我們也可以透過在本地修改對應版本的原始檔,本地編譯好後上傳到 /tmp/com/actiontech/dble/server/ 路徑下,再執行 redefine,效果是一樣的:
$ redefine /tmp/com/actiontech/dble/server/ServerQueryHandler.classredefine 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
透過此方式,可以更方便的透過指令碼管理整個流程。