<acronym id="s8ci2"><small id="s8ci2"></small></acronym>
<rt id="s8ci2"></rt><rt id="s8ci2"><optgroup id="s8ci2"></optgroup></rt>
<acronym id="s8ci2"></acronym>
<acronym id="s8ci2"><center id="s8ci2"></center></acronym>
0
  • 聊天消息
  • 系統消息
  • 評論與回復
登錄后你可以
  • 下載海量資料
  • 學習在線課程
  • 觀看技術視頻
  • 寫文章/發帖/加入社區
會員中心
創作中心

完善資料讓更多小伙伴認識你,還能領取20積分哦,立即完善>

3天內不再提示

解析 Sermant 熱插拔能力:服務運行時動態掛載 JavaAgent 和插件

王程 ? 來源:jf_75796907 ? 作者:jf_75796907 ? 2024-02-18 10:09 ? 次閱讀

一、概述

Sermant 是基于 Java 字節碼增強技術的無代理服務網格,其利用 Java 字節碼增強技術,為宿主應用程序提供服務治理功能,以解決大規模微服務場景中的服務治理問題,通過 Java 字節碼增強技術,可以非侵入的提供服務治理能力。在以往版本中,Sermant 通過配置 - javaagent 指令在微服務啟動時接入服務治理能力,當需要接入及卸載 Sermant 時都需要通過重新啟動微服務來完成。但從 1.2.0 版本開始,Sermant 實現了在服務不停機狀態下進行安裝和卸載的能力,為服務治理能力帶來全新接入體驗。本文將會對這種動態接入的機制,從技術基礎到 Sermant 設計進行一次深入分析。

二、JavaAgent 加載方式

首先介紹一下 JavaAgent 的不同接入方式,這是 Sermant 實現動態接入能力的技術基礎。Java 中 Instrumentation API 提供了一種修改字節碼的機制,利用該 API,可以通過修改字節碼的方式來改變程序的行為,而不用觸及程序的源碼。JavaAgent 為 Instrumentation API 的客戶端,通過 JavaAgent 可以調用 API 進行字節碼的操作,其提供了兩種加載方式給開發者重載:

靜態加載:利用 premain,在應用程序啟動時加載 JavaAgent 稱為靜態加載,靜態加載會在啟動時在執行任何代碼之前修改字節碼。

wKgZomXPLDiAOeKFAACU6YF6H-4790.pngwKgZomXPK9uAWf__AACU6YF6H-4998.png

靜態加載時,字節碼增強是在類加載時發生的,當 Java 程序啟動時,類加載過程中所有被加載的類都會經過 JavaAgent 所定義的類文件轉換器的處理。

動態加載:利用 agentmain 通過 Java Attach API 將 JavaAgent 加載到已運行的 JVM 中,動態加載可以通過字節碼重轉換的方式在運行時修改字節碼。

wKgaomXPLDmAOjbwAACZQB7Vbyo997.pngwKgZomXPK--AcDYZAACZQB7Vbyo681.png

動態加載時,和靜態加載不同的是,此時 JVM 已在運行,目標類已被加載,就不能像靜態加載時一樣觸發字節碼增強過程,在使用動態加載的過程中,往。往會通過 Instrumentation API 來觸發目標類(當然也可以指定所有已被加載的類)的重轉換過程,在重轉換過程中就會觸發到 Agent 構建的類文件轉換器,從而完成字節碼增強過程。

動態加載方式為 JavaAgent 提供了在 JVM 運行時接入的能力,但通過類重轉換來觸發字節碼增強相對于在類加載時增強有一定的局限性,例如不能在增強時修改類的繼承關系,不能為類添加靜態代碼塊,不能增強內存中和資源文件中字節碼不一致的類等,這些也是在使用動態加載和多 JavaAgent 場景中常見的問題,綜上,兩種加載方式各有利弊,可以在使用時按照業務場景選擇。

三、Sermant 熱插拔能力關鍵問題剖析

在了解技術基礎后,我們能輕易的想到,理論上基于 JavaAgent 的動態加載方式,只需要在使用 Sermant 時,將通過 premain 方式啟動改為通過 agentmain 方式啟動,就可以將微服務治理能力動態的接入到微服務中,做到微服務零侵入、微服務不停機的狀態下接入服務治理能力,但通往前方的路上總是充滿了障礙:

3.1 如何保證動態安裝過程中重轉換可順利執行?

這個問題的出現,根源在于 JavaAgent 通過 agentmain 方式加載到已運行的 JVM 中時,不同于靜態加載,會在類初次被加載時完成字節碼的轉換,動態加載時一些需要被字節碼增強類已經完成了類加載過程,這時候需要使用 Instrumentation 提供的類重轉換(retransform classes)能力來修改字節碼,在 Instrumentation 的 Javadoc 中關于這個能力有這樣一段描述:

“The retransformation must not add, remove or rename fields or methods, change the signatures of methods, or change inheritance.(重轉換過程中,我們不能新增、刪除或者重命名字段和方法,不能更改方法的簽名,不能更改類的繼承。)”

從中可以看出,在引入動態加載能力前,優先要保證字節碼增強時,不可以有上述內容中所描述的限制操作。

不過 Sermant 不太需要擔心這個問題,因為這種限制不僅僅在動態加載時會觸發,在多個 JavaAgent 同時使用時也可能會觸發,可以參考 Sermant 團隊的另一篇文章:《記一次多個 JavaAgent 同時使用的類增強沖突問題及分析》。為了保證在多 Agent 場景下的兼容性,Sermant 的字節碼增強模板嚴格遵循 Instrumentation API 的限制,因此 Sermant 在兼容性上的不斷改進過程中無心插柳,幫助動態加載能力鋪平了路。

3.2 如何保證在服務治理插件安裝和卸載時不互相影響?

Sermant 的設計中,通過字節碼增強引入的服務治理能力,是通過在目標方法上添加服務治理功能切面來完成的,每一個服務治理插件,通過一系列切面的配合來達成最終的服務治理效果。不同的服務治理功能,可能會對同一個目標方法進行處理。但并不會對同一個方法進行多次字節碼增強,而是通過一次字節碼增強織入調度切面(onMethodEnter、onMethodExit 等),通過該切面對相關的服務治理能力(通過攔截器實現,每一個切面會對應一個攔截器的列表)進行調度:

wKgZomXPLDmALI3hAACenH9Ro5I964.pngwKgaomXPK_6AAENeAACenH9Ro5I795.png

對于服務治理能力的調度邏輯我們在另一篇文章《開發者能力機制解析,玩轉 Sermant 開發》有講過,本篇不再贅述。

基于框架的基本設計,就需要考慮兩個問題,當插件在動態安裝時,如何保證不重復字節碼增強?當插件卸載時,如何保證不會導致有相同目標方法的插件失效。

安裝時如何保證不重復執行字節碼增強?

在字節碼增強開發過程中,類文件轉換器(ClassFileTransformer)是一定會接觸到的概念,開發者需要基于該轉換器來進行字節碼的處理。在大多數的字節碼增強框架中,都會對其進行封裝,用于降低字節碼處理的難度。Sermant 基于 ByteBuddy 提供的類文件轉換器實現了一種可重入的類轉換器,在插件動態安裝時,雖然目標方法已經被已安裝的插件增強過了,但此時還是會觸發類文件轉換(因為動態安裝插件的過程是獨立的),當觸發類文件轉換時,所有相關的類文件轉換器都會被喚醒,再次觸發類文件轉換過程。每次可重入類轉換器被喚醒時,將發生以下行為:

wKgaomXPLDqAPjSxAAJmM8E6Ha0534.pngwKgZomXPLBGARfotAAJmM8E6Ha0706.png

在 Sermant 中維護了一個針對目標方法的字節碼增強鎖(AdviceKey 鎖),即針對每一個目標方法,維護了 1 個信號量當做鎖,用于讓各類文件轉換器來檢查目標方法的字節碼增強狀態,當目標方法對應的類被類轉換時,就會觸發 Sermant 所提供的類文件轉換器,此時類文件轉換器將嘗試獲取針對目標方法的信號量,如果能獲取信號量,則執行對目標方法的字節碼增強,如果不能獲取,則不執行字節碼增強。

基于字節碼增強鎖,在轉換器觸發時,主要有兩條路徑可以走,類文件轉換器會通過目標方法的 AdviceKey(類名 + 方法 hash+ 類加載器組成的一個唯一表示,用于表示字節碼增強的目標) 來檢查其所關聯的鎖,判斷當前目標方法是否已被 Sermant 進行過字節碼增強(織入攔截器調度的切面):

1.能獲取鎖,說明未被增強:則當前文件轉換器獲取當前 AdviceKey 所關聯的鎖,將其獲取的鎖通過其對應的插件來維護,并且執行字節碼增強,將服務治理所需的攔截器放入該 AdviceKey 所對應的攔截器列表;

2.不能獲取鎖,說明已被增強:則只將攔截器放入該 AdviceKey 對應的攔截器列表中,不執行字節碼增強。
通過上述機制,就可以保證 Sermant 在安裝不同服務治理插件時,不會進行重復的字節碼增強,避免無端的性能和資源損耗。

卸載時如何保證不會導致其他插件失效?

當插件需要卸載時,會再次觸發相關目標類的重轉換,與安裝時不同的是,這次需要被卸載的插件釋放自身已經持有的 AdviceKey 鎖。釋放鎖后,觸發目標類重轉換時,目標類所對應的各個插件的類文件轉換器將會再次觸發和安裝時相同的流程:

wKgZomXPLDuAJYdJAAJ4ZuzkUMQ275.pngwKgaomXPLCSABj97AAJ4ZuzkUMQ731.png

在這個過程中,未被卸載的插件所提供的對目標類的類文件轉換器,會在目標類重轉換時,再次觸發,并且只會經歷獲取鎖和字節碼增強的過程。這樣就保證,如果還有插件需要對該目標方法進行字節碼增強時,可以獲得目標方法所對應的鎖,不會因為目標方法的交集而導致其他插件能力失效。

審核編輯 黃宇

聲明:本文內容及配圖由入駐作者撰寫或者入駐合作網站授權轉載。文章觀點僅代表作者本人,不代表電子發燒友網立場。文章及其配圖僅供工程師學習之用,如有內容侵權或者其他違規問題,請聯系本站處理。 舉報投訴
  • 轉換器
    +關注

    關注

    27

    文章

    8270

    瀏覽量

    142793
  • 熱插拔
    +關注

    關注

    2

    文章

    197

    瀏覽量

    33852
  • JAVA
    +關注

    關注

    19

    文章

    2908

    瀏覽量

    103134
收藏 人收藏

    評論

    相關推薦

    NI發布全新PXI機箱,全面提高系統正常運行時

      在NI PXIe-1066DC機全新機箱中,NI為PXI平臺系列增加了冗余、熱插拔和前端接入功能,顯著增加了系統的正常運行時
    發表于 05-28 09:08 ?1962次閱讀

    如何縮短Vivado的運行時

    在Vivado Implementation階段,有時是有必要分析一下什么原因導致運行時間(runtime)過長,從而找到一些方法來縮短運行時間。
    的頭像 發表于 05-29 14:37 ?1.4w次閱讀
    如何縮短Vivado的<b class='flag-5'>運行時</b>間

    基于PCIe-Native機制的熱插拔

    熱插拔即帶電插拔,在虛擬化場景下,熱插拔就是在虛擬機運行過程中對磁盤網卡等設備進行動態調整。
    的頭像 發表于 09-06 10:32 ?3309次閱讀

    如何檢查Linux服務器的運行時

    Linux 中的 uptime 用于查看系統啟動后的運行時間。它是一個比較簡單的 Linux 命令,可以不帶參數直接運行。
    發表于 11-25 15:25 ?1.5w次閱讀
    如何檢查Linux<b class='flag-5'>服務</b>器的<b class='flag-5'>運行時</b>間

    熱插拔是什么?熱插拔有哪些特點?

    恢復能力、擴展性和靈活性等,例如一些面向高端應用的磁盤鏡像系統都可以提供磁盤的熱插拔功能。具體用學術的說法就是:熱替換(Hot replacement)、熱添加(hot expansion)和熱升級
    發表于 12-13 10:53

    即插即用和熱插拔的區別

    閉系統,不切斷電源的情況下取出和更換損壞的硬盤、電源或板卡等部件,從而提高了系統對災難的及時恢復能力、擴展性和靈活性等,例如一些面向高端應用的磁盤鏡像系統都可以提供磁盤的熱插拔功能。 具體用學術的說法
    發表于 10-23 10:26

    TPS2490,采用 TI 1.4 代 NexFET 的 12V 輸出 60A 熱插拔控制器

    `描述此電路為熱插拔設計,使用具有功率限制功能的 TPS2490 熱插拔控制器和兩個 30V CSD17570Q5B NexFET。此系統可用于安全服務器中,允許在系統正常運行時插入線
    發表于 05-08 16:28

    通過測試的2V輸出60A熱插拔控制器完整設計

    描述此電路為熱插拔設計,使用具有功率限制功能的 TPS2490 熱插拔控制器和兩個 30V CSD17570Q5B NexFET。此系統可用于安全服務器中,允許在系統正常運行時插入線路
    發表于 11-16 16:50

    采用1.4 代NexFET的12V輸出60A熱插拔控制器參考設計

    描述此電路為熱插拔設計,使用具有功率限制功能的 TPS2490 熱插拔控制器和兩個 30V CSD17570Q5B NexFET。此系統可用于安全服務器中,允許在系統正常運行時插入線路
    發表于 09-26 07:26

    Go運行時:4年之后

    自 2018 年以來,Go GC,以及更廣泛的 Go 運行時,一直在穩步改進。近日,Go 社區總結了 4 年來 Go 運行時的一些重要變化。
    的頭像 發表于 11-30 16:21 ?568次閱讀

    如何保證它們容器運行時的安全?

    緊密耦合的容器運行時繼承了主機操作系統的安全態勢和攻擊面。運行時或主機內核中的任何漏洞及其利用都會成為攻擊者的潛在切入點。
    的頭像 發表于 11-03 15:24 ?344次閱讀

    熱插拔和非熱插拔的區別

    熱插拔和非熱插拔的區別? 熱插拔和非熱插拔是指電子設備或組件在工作狀態下是否可以進行插拔操作的一種分類。
    的頭像 發表于 12-28 10:01 ?1293次閱讀

    熱插拔是什么原理

    熱插拔(Hot Swap)是一種允許在系統運行過程中,動態地插入或移除硬件設備的技術。這種技術在計算機硬件、通信設備和存儲設備等領域得到了廣泛應用。熱插拔技術的目的是為了提高系統的可擴
    的頭像 發表于 01-16 11:03 ?1578次閱讀
    <b class='flag-5'>熱插拔</b>是什么原理

    鍵盤熱插拔和非熱插拔的區別

    鍵盤熱插拔和非熱插拔的區別 鍵盤是計算機外設設備之一,熱插拔是指在計算機運行中插入或拔出設備而無需重啟計算機,非熱插拔則需要重啟計算機才能生
    的頭像 發表于 02-02 17:34 ?2288次閱讀

    4針M5接口3針M5接口是否支持熱插拔

      德索工程師說道在討論4針M5接口和3針M5接口是否支持熱插拔之前,我們首先需要明確“熱插拔”這一概念。熱插拔,即在設備通電運行時,可以直接進行連接或斷開操作,而無需關閉整個系統或設
    的頭像 發表于 05-13 17:45 ?83次閱讀
    4針M5接口3針M5接口是否支持<b class='flag-5'>熱插拔</b>
    亚洲欧美日韩精品久久_久久精品AⅤ无码中文_日本中文字幕有码在线播放_亚洲视频高清不卡在线观看
    <acronym id="s8ci2"><small id="s8ci2"></small></acronym>
    <rt id="s8ci2"></rt><rt id="s8ci2"><optgroup id="s8ci2"></optgroup></rt>
    <acronym id="s8ci2"></acronym>
    <acronym id="s8ci2"><center id="s8ci2"></center></acronym>