1. 程式人生 > >阿里巴巴正式開源自研動態非侵入AOP解決方案:JVM-Sandbox

阿里巴巴正式開源自研動態非侵入AOP解決方案:JVM-Sandbox

徐冬晨

寫在前面

隨著軟體部署規模的擴大,系統的功能的細化,系統間耦合度和鏈路複雜度不斷加強。若要繼續保持現規模系統的穩定性,需要實現並完善監控體系、故障定位分析、流量錄製回放、強弱依賴檢測、故障演練等支撐工具平臺。出於對伺服器規模和業務穩定性的考量,這些配套工具平臺要具備對目標應用具有無侵入、實時生效、動態可插拔的特點。

要實現這些,多少都會觸及到一塊底層技術——動態位元組碼增強。如果每個工具都自己實現一套位元組碼增強邏輯,前期實現的門檻與後期維護成本高,且不同工具間相互影響造成不可預知的風險。如何遮蔽位元組碼增強技術的高門檻,降低研發運維成本,同時又能支援上層多個工具平臺功能的快速實現和動態管理,成為阿里集團的目標。從去年開始潛心修行,創新的研發了一套實時無侵入的位元組碼增強框架。

於是 JVM-Sandbox 誕生了!

應用場景JVM-Sandbox 的目標群體
  • Btrace 好強大,也曾技癢想做一個更便捷、更適合自己的問題定位工具,既可支援線上鏈路監控排查,也可支援單機版問題定位。

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

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

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

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

如果你有以上訴求,那麼你就是 JVM-Sandbox 的潛在客戶。JVM-Sandbox 提供動態增強類你所指定的類,獲取你想要的引數和行資訊;提供動態可插拔容器,管理基於 JVM-Sandbox 的模組。

JVM-Sandbox 能做什麼?

在 JVM-Sandbox(以下簡稱沙箱)的世界觀中,任何一個 Java 方法的呼叫都可以分解為BEFORE

RETURNTHROWS三個環節,由此在三個環節上引申出對應環節的事件探測流程控制機制。不僅如此還有LINE事件,可以完成程式碼行的記錄。

// BEFORE-EVENT
try {

   /*
    * do something...
    */
    //LINE-EVENT
    a();
    // RETURN-EVENT
    return;

} catch (Throwable cause) {
    // THROWS-EVENT
}

基於BEFORERETURNTHROWS三個環節事件以及LINE事件,可以完成很多類 AOP 的操作。

  1. 可以感知和改變方法呼叫的入參

  2. 可以感知和改變方法呼叫返回值和丟擲的異常

  3. 可以感知一個請求按順序執行了哪些行

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

    • 在方法體執行之前直接返回自定義結果物件,原有方法程式碼將不會被執行

    • 在方法體返回之前重新構造新的結果物件,甚至可以改變為丟擲異常

    • 在方法體丟擲異常之後重新丟擲新的異常,甚至可以改變為正常返回

JVM-Sandbox 都有哪些可能的應用場景
  • 線上故障定位

  • 線上系統流控

  • 線上故障模擬

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

  • 動態日誌列印

  • 安全資訊監測和脫敏

  • 行鏈路計算和覆蓋率統計

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

JVM-Sandbox 在阿里集團的應用 線上故障演練

17 年故障演練平臺在 JVM-Sandbox 基礎上僅耗時 1 周即完成故障注入部分的系統重構。重構後的系統在掛載效率和掛載成功率方面有了明顯的提升,極大的縮短的故障演練的時間,演練效率提升了數十倍。基於 JVM-Sandbox 改造後的故障演練平臺,通用性強,所有基於 JVM 啟動的系統均支援,極大的拓展了故障演練的範圍,故障演練已達到集團級部署。

與 16 年故障演練資料對比,17 年的故障演練平臺,覆蓋 BU 提升了 1.6 倍,覆蓋應用提升了 5 倍,覆蓋場景提升了 37 倍。

 依賴檢測

17 年強弱依賴自動化檢測平臺誕生。它提供了依賴檢測、強弱分析、依賴掃描、故障注入等多種能力,底層能力基於 JVM-Sandbox 在 1 周內完成功能開發。利用其模組容器的特性,將前人開發的模組與新增模組一起掛載共同工作,完成平臺功能。

強弱依賴梳理方面,承載了淘寶的系統強弱依賴梳理工作,260+ 個應用一鍵接入系統,並實現了 0 人工成本的自動化、智慧化梳理。

 服務端錄製隔離回放機制

在 JVM-Sandbox 基礎上開發了一個 SS 模組,相當於一個錄音機 + 回放機, 在呼叫中介軟體的時候, 順序錄制下了我們的中介軟體請求, 並且儲存這份‘磁帶’到伺服器上。當我們需要隔離回放的時候, 將這份‘磁帶’找到, 並且在需要的時候直接從‘磁帶’讀取, 並不需要真實地請求我們的中介軟體, 這樣就保證了我們的讀、寫介面也能做到可重複使用,從而實現服務端的隔離回放。

線上錄製隔離回放不僅極大的縮短的業務迴歸的耗時,把業務測試同學從繁瑣的資料準備和介面自動化指令碼的編寫過程中解放出來,而且極大的拓展了覆蓋範圍,使迴歸的範圍更貼近使用者,且場景更豐富。

 精準迴歸

服務端錄製隔離回放機制誕生之後,雖然有效的提升了覆蓋範圍,降低了自動化指令碼的人工投入,但是也帶來了新的問題。線上錄製的場景是海量的,單個系統都可以達到萬級、十萬級甚至百萬級別的錄製,這些錄製的場景中,存在大量的重複場景,如何識別重複場景,實現有效、精準的回放,成為新的待解決問題。

17 年在 JVM-Sandbox 的基礎上,利用 LineEvnet 實現了行鏈路識別和標記,有效的提升了回放的精準度和效率。

JVM-Sandbox 在阿里集團已經實現全網部署,在其上載入不同的模組實現了不同的功能,每個功能根據 BU 和應用的需要進行載入:

  • 強弱依賴檢測功能:覆蓋淘寶、天貓、業務平臺、菜鳥、飛豬、ICBU、CBU 等 7 個 BU,240+ 個應用;

  • 線上故障演練功能:覆蓋集團客戶體驗事業群、淘寶網、雲零售事業部、天貓、業務平臺、飛豬、菜鳥、釘釘、阿里健康、CBU、集團安全、支付寶等 16 個 BU,391 個應用;

  • 服務端錄製回放:覆蓋淘寶網、釘釘 2 個 BU;

  • 精準迴歸:覆蓋淘寶網、業務平臺、釘釘 3 個 BU。

通過上邊的事例,想必大家對 JVM-Sandbox 是什麼,核心功能是什麼,還能做哪些事情,以及是否可以為阿里以外的同學提供服務等問題更感興趣了,下面我們著重介紹這部分內容。

JVM-Sandbox技術背景

故障演練、強弱依賴檢測、錄製回放、精準迴歸,要解決這些問題本質就是如何完成 java 方法的環繞管控和執行時行鏈路的獲取,即 AOP 框架的解決方案。目前常用 AOP 框架的解決方案有兩種:proxy 和埋點。proxy 的優點在於已實現了統一的 API,減少了重複投入,但是不能實時生效,需要系統編譯重啟。埋點的優點在於動態生效靈活度高,但是沒有統一 API。

要快速解決上邊的四個問題,我們需要的 AOP 解決方案必須具備兩個特性:

  • 動態可插拔,即實現埋點方式的統一的 API

  • 無侵入性,即解決 JVM 類隔離的問題

基於以上需求,我們研發了 JVM-Sandbox。

JVM-Sandbox 的核心功能

JVM-Sandbox 由純 Java 編碼完成,基於 JVMTI 技術規範,為觀察和改變程式碼執行結果提供了即插即用模組介面的容器,提供核心功能:

  • 使用埋點技術提供統一的 API,來實現無需重啟的 AOP 解決方案

  • 使用容器完成 JVM 類隔離,來解決侵入性問題

  • 提供容器管理機制,來完成各種容器的管理

JVM—Sandbox 的核心事件模型

BEFORE、RETURN 和 THROWS 三個環節事件的正常流轉和干預流轉

隔離和通訊

隔離:

  • 沙箱通過自定義的SandboxClassLoader破壞了雙親委派的約定,實現了和觀察應用的類隔離。所以不用擔心載入沙箱會引起應用的類汙染、衝突。

  • 沙箱各模組之間類通過ModuleClassLoader實現了各自的獨立,達到模組之間、模組和沙箱之間、模組和應用之間互不干擾。

通訊

  • 通過向 Bootstrap ClassLoader 中注入 Spy 類,完成觀察應用與 JVM-Sandbox 的通訊

  • JVM-Sandbox 會將事件分發給各個 Module,完成 JVM-Sandbox 與 Module 之間的通訊

模組動態管理
  • 事件監控表,完成模組的管理

  • trasform 方法形變原生位元組碼

程式碼編織

插入 Spy 類到位元組碼中,Spy 方法中反射呼叫 JVM-Sandbox 的方法。

以 BeforeEvent 為例,進行程式碼編織展示。

整體架構

沙箱一共由三大核心功能元件構成

  1. 程式碼編織元件

    負責完成預設程式碼的重寫和生效

  2. 事件處理分發元件

    負責完成事件的分發和方法流控控制的執行

  3. 模組管理元件

    負責控制和管理沙箱的各個模組

沙箱的底層提供了一個 HTTP-SERVER(Jetty),通過 HTTP 協議完成sandbox.sh和沙箱的控制互動,同時也給各個模組提供了基於 HttpServlet 和 WebSocket 規範的 API,各模組可以複用沙箱完成各自模組的控制與互動。

開源和共建

1、已開源,尋求更多的同學一起完善 JVM-Sandbox 的功能。Github 地址:

https://github.com/alibaba/JVM-Sandbox

2、希望有同學和我們一起共同完善 JVM-Sandbox 的功能;

3、希望更多的同學想到跟多的應用場景,並能開源出來供大家使用。

綜上,JVM-Sandbox 是一個純 java 編寫的 AOP 解決方案。它為研發人員提供了一個快速實現位元組碼增強工具的平臺。他的模組管理功能可以最大限度的複用模組、協同合作,減少重複投入。

隨著 JVM-Sandbox 的開源,我們期待更多的人加入到功能擴張和優化上,使其適配更多的開源中介軟體和 JVM。

希望有更多的同學,發揮其聰明才智,開發更多、更好的上層模組,提供給自己和其他人的人使用。也希望能夠利用好已有的模組,組裝出新的工具平臺和應用場景。

JVM-Sandbox 建設和應用期待大家共同建設。

作者介紹

徐冬晨,花名鸞伽,阿里巴巴測試開發專家,2010年加入阿里巴巴,先後負責商品平臺、交易平臺、手機淘寶的測試開發工作,一直致力用技術解決業務測試中遇到的各種問題,提升測試效率和系統穩定性。連續參與6年天貓雙十一,在服務端穩定性方面,經驗豐富、見解獨到。

原文 

轉載僅為學習交流,如冒犯請聯絡刪除~