JVM沙箱容器,一種JVM的非侵入式運行期AOP解決方案

目標羣體

  • BTRACE好強大,也曾技癢想做一個更便捷、更適合自己的問題定位工具,既可支持線上鏈路監控排查,也可支持單機版問題定位。

  • 有時候突然一個問題反饋上來,需要入參才能完成定位,但恰恰沒有任何日誌,甚至出現在別人的代碼裏,好想開發一個工具可以根據需要動態添加日誌,最好還能按照業務ID進行過濾。

  • 系統間的異常模擬可以使用的工具很多,可是系統內的異常模擬怎麼辦,加開關或是用AOP在開發系統中實現,好想開發一個更優雅的異常模擬工具,既能模擬系統間的異常,又能模擬系統內的異常。

  • 好想獲取行調用鏈路數據,可以用它識別場景、覆蓋率統計等等,覆蓋率統計工具不能原生支持,統計鏈路數據不準確。想自己開發一個工具獲取行鏈路數據。

  • 我想開發錄製回放、故障模擬、動態日誌、行鏈路獲取等等工具,就算我開發完成了,這些工具底層實現原理相同,同時使用,要怎麼消除這些工具之間的影響,怎麼保證這些工具動態加載,怎麼保證動態加載/卸載之後不會影響其他工具,怎麼保證在工具有問題的時候,快速消除影響,代碼還原

如果你有以上研發訴求,那麼你就是JVM-SANDBOX(以下簡稱沙箱容器)的潛在客戶。沙箱容器提供

  1. 動態增強類你所指定的類,獲取你想要的參數和行信息甚至改變方法執行

  2. 動態可插拔容器框架

項目簡介

JVM-SANDBOX(沙箱)實現了一種在不重啓、不侵入目標JVM應用的AOP解決方案。

沙箱的特性

  1. 無侵入:目標應用無需重啓也無需感知沙箱的存在

  2. 類隔離:沙箱以及沙箱的模塊不會和目標應用的類相互干擾

  3. 可插拔:沙箱以及沙箱的模塊可以隨時加載和卸載,不會在目標應用留下痕跡

  4. 多租戶:目標應用可以同時掛載不同租戶下的沙箱並獨立控制

  5. 高兼容:支持JDK[6,11]

沙箱常見應用場景

  • 線上故障定位

  • 線上系統流控

  • 線上故障模擬

  • 方法請求錄製和結果回放

  • 動態日誌打印

  • 安全信息監測和脫敏

JVM-SANDBOX還能幫助你做很多很多,取決於你的腦洞有多大了。

實時無侵入AOP框架

在常見的AOP框架實現方案中,有靜態編織和動態編織兩種。

  1. 靜態編織:靜態編織發生在字節碼生成時根據一定框架的規則提前將AOP字節碼插入到目標類和方法中,實現AOP;

  2. 動態編織:動態編織則允許在JVM運行過程中完成指定方法的AOP字節碼增強.常見的動態編織方案大多采用重命名原有方法,再新建一個同簽名的方法來做代理的工作模式來完成AOP的功能(常見的實現方案如CgLib),但這種方式存在一些應用邊界:

  • 侵入性:對被代理的目標類需要進行侵入式改造。比如:在Spring中必須是託管於Spring容器中的Bean

  • 固化性:目標代理方法在啓動之後即固化,無法重新對一個已有方法進行AOP增強

要解決無侵入的特性需要AOP框架具備 在運行時完成目標方法的增強和替換。在JDK的規範中運行期重定義一個類必須準循以下原則

  1. 不允許新增、修改和刪除成員變量

  2. 不允許新增和刪除方法

  3. 不允許修改方法簽名

JVM-SANDBOX屬於基於Instrumentation的動態編織類的AOP框架,通過精心構造了字節碼增強邏輯,使得沙箱的模塊能在不違反JDK約束情況下實現對目標應用方法的無侵入運行時AOP攔截。

核心原理

事件驅動

在沙箱的世界觀中,任何一個Java方法的調用都可以分解爲BEFORE、RETURN和THROWS三個環節,由此在三個環節上引申出對應環節的事件探測和流程控制機制。

// BEFORE
try {
 /*
 * do something...
 */
 // RETURN
 return;
} catch (Throwable cause) {
 // THROWS
}

基於BEFORE、RETURN和THROWS三個環節事件分離,沙箱的模塊可以完成很多類AOP的操作。

  1. 可以感知和改變方法調用的入參

  2. 可以感知和改變方法調用返回值和拋出的異常

  3. 可以改變方法執行的流程

  • 在方法體執行之前直接返回自定義結果對象,原有方法代碼將不會被執行

  • 在方法體返回之前重新構造新的結果對象,甚至可以改變爲拋出異常

  • 在方法體拋出異常之後重新拋出新的異常,甚至可以改變爲正常返回

類隔離策略

沙箱通過自定義的SandboxClassLoader破壞了雙親委派的約定,實現了和目標應用的類隔離。所以不用擔心加載沙箱會引起應用的類污染、衝突。各模塊之間類通過ModuleJarClassLoader實現了各自的獨立,達到模塊之間、模塊和沙箱之間、模塊和應用之間互不干擾。

JVM沙箱容器,一種JVM的非侵入式運行期AOP解決方案


類增強策略

沙箱通過在BootstrapClassLoader中埋藏的Spy類完成目標類和沙箱內核的通訊

JVM沙箱容器,一種JVM的非侵入式運行期AOP解決方案


整體架構

JVM沙箱容器,一種JVM的非侵入式運行期AOP解決方案


快速安裝

  • 下載並安裝

# 下載最新版本的JVM-SANDBOX
wget http://ompc.oss-cn-hangzhou.aliyuncs.com/jvm-sandbox/release/sandbox-stable-bin.zip
# 解壓
unzip sandbox-stable-bin.zip
  • 掛載目標應用

# 進入沙箱執行腳本
cd sandbox/bin
# 目標JVM進程33342
./sandbox.sh -p 33342
  • 掛載成功後會提示

./sandbox.sh -p 33342
 NAMESPACE : default
 VERSION : 1.2.0
 MODE : ATTACH
 SERVER_ADDR : 0.0.0.0
 SERVER_PORT : 55756
 UNSAFE_SUPPORT : ENABLE
 SANDBOX_HOME : /Users/vlinux/opt/sandbox
 SYSTEM_MODULE_LIB : /Users/vlinux/opt/sandbox/module
 USER_MODULE_LIB : ~/.sandbox-module;
 SYSTEM_PROVIDER_LIB : /Users/vlinux/opt/sandbox/provider
 EVENT_POOL_SUPPORT : DISABLE
  • 卸載沙箱

./sandbox.sh -p 33342 -S
jvm-sandbox[default] shutdown finished.


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章