溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊(cè)×
其他方式登錄
點(diǎn)擊 登錄注冊(cè) 即表示同意《億速云用戶(hù)服務(wù)條款》

SpringBoot Admin2.0集成Java Arthas的實(shí)踐是怎樣的

發(fā)布時(shí)間:2021-09-29 14:33:51 來(lái)源:億速云 閱讀:142 作者:柒染 欄目:云計(jì)算

這期內(nèi)容當(dāng)中小編將會(huì)給大家?guī)?lái)有關(guān)SpringBoot Admin2.0集成Java Arthas的實(shí)踐是怎樣的,文章內(nèi)容豐富且以專(zhuān)業(yè)的角度為大家分析和敘述,閱讀完這篇文章希望大家可以有所收獲。

項(xiàng)目最初使用 Arthas 主要有兩個(gè)目的:

  1. 通過(guò) arthas 解決實(shí)現(xiàn)測(cè)試環(huán)境、性能測(cè)試環(huán)境以及生產(chǎn)環(huán)境性能問(wèn)題分析工具的問(wèn)題。

  2. 通過(guò)使用 jad、mc、redefine 功能組合實(shí)現(xiàn)生產(chǎn)環(huán)境部分節(jié)點(diǎn)代碼熱更新的能力。

技術(shù)選型相關(guān)

因?yàn)楣具€未能建立起較為統(tǒng)一的生產(chǎn)微服務(wù)配置以及狀態(tài)管理的能力,各自系統(tǒng)的研發(fā)運(yùn)維較為獨(dú)立。現(xiàn)在項(xiàng)目使用了 Spring Cloud 以及 Eureka 的框架結(jié)構(gòu),和 SBA 的基礎(chǔ)支撐能力較為匹配,同時(shí),SBA 已經(jīng)可以提供服務(wù)感知,日志級(jí)別配置管理,以及基于 actuator 的 JVM、Spring 容器的眾多管理插件,可以滿足基礎(chǔ)使用的需求。

在調(diào)研期間,Arthas 整體版本為 3.4.5,提供了基于 Webconsole 的 Tunner Server 模式,通過(guò)前面鏈接文章已經(jīng)實(shí)踐,與SBA已經(jīng)可以實(shí)現(xiàn)集成。因?yàn)轫?xiàng)目本身沒(méi)有歷史包袱,在實(shí)際集成的過(guò)程中采用了 SBA 2.0 版本以提供更多的管理功能和圖形界面能力。其他優(yōu)點(diǎn):

  • web console 界面嵌入 SBA 整體密碼登錄和網(wǎng)頁(yè)權(quán)限管理,實(shí)現(xiàn)登陸 SBA 后才可以使用相關(guān) arthas web console 的功能。

  • 基于SBA 客戶(hù)端依賴(lài)的 jolokia-core 開(kāi)放目標(biāo)服務(wù)進(jìn)程的 jmx 管理,通過(guò)實(shí)現(xiàn) jmx 接口復(fù)用 SBA 的相關(guān)操作界面,減少前端界面開(kāi)發(fā)能力的要求。

整體結(jié)構(gòu)

SpringBoot Admin2.0集成Java Arthas的實(shí)踐是怎樣的

幾個(gè)關(guān)鍵點(diǎn),使用 JVM 內(nèi)置 Arthas Spring Boot 插件,參考工商銀行的模式建立完善的客戶(hù)端下載以及修改腳本實(shí)現(xiàn)遠(yuǎn)程控制。內(nèi)置方案工作開(kāi)發(fā)量小,只需要集成相關(guān)的開(kāi)源組件即可實(shí)現(xiàn)相關(guān)的遠(yuǎn)程使用的模式并兼顧安全。工銀的方案大而全適合整體架構(gòu)規(guī)劃后配置專(zhuān)有研發(fā)團(tuán)隊(duì)之城。內(nèi)置方案同時(shí)包含通過(guò) JMX 的啟停操作(基于 3.4.5 的 Spring Boot 插件無(wú)法獲得相關(guān)句柄,暫時(shí)無(wú)法實(shí)現(xiàn)),默認(rèn)不啟動(dòng)。通過(guò)遠(yuǎn)程 JMX 開(kāi)通后,JVM 新增相關(guān)線程 8 個(gè),新增虛擬機(jī)內(nèi)存 30MB 左右,和本文參考的 SBA1.0 方案相同,需要考慮在線開(kāi)啟前 JVM 內(nèi)存是否可以支持。

實(shí)現(xiàn)效果

SBA 2.0 最大的方便就是提供了配置化鏈接外部網(wǎng)頁(yè)的能力,同時(shí)如果網(wǎng)頁(yè)實(shí)現(xiàn)在當(dāng)前 JVM 進(jìn)程,可以實(shí)現(xiàn) Spring-Security 的本地權(quán)限管理,在生產(chǎn)環(huán)境下只有在登錄 SBA 后才能使用相關(guān)集成的 arthas 功能。

  • 登錄界面

SpringBoot Admin2.0集成Java Arthas的實(shí)踐是怎樣的

  • 外嵌連接位置

SpringBoot Admin2.0集成Java Arthas的實(shí)踐是怎樣的

  • JMX 的使用

SpringBoot Admin2.0集成Java Arthas的實(shí)踐是怎樣的

SpringBoot Admin2.0集成Java Arthas的實(shí)踐是怎樣的

  • 跳轉(zhuǎn) arthas web console

SpringBoot Admin2.0集成Java Arthas的實(shí)踐是怎樣的

改造方案

參考原文 -SpringBoot Admin 集成 Arthas 實(shí)踐中實(shí)現(xiàn)的幾個(gè)步驟。

1. 整體工程結(jié)構(gòu)

SpringBoot Admin2.0集成Java Arthas的實(shí)踐是怎樣的

整體工程修改自 SBA 開(kāi)源項(xiàng)目的 example 工程,具體使用 custom-ui 的工程鏈接為:[_[spring-boot-admin-sample-custom-ui]_](https://github.com/codecentric/spring-boot-admin/tree/master/spring-boot-admin-samples/spring-boot-admin-sample-custom-ui)_,_紅色框的部分是 arthas web console 的全部靜態(tài)文件,通過(guò) Maven Resource 的指定配置打入指定目錄,實(shí)現(xiàn) SBA 啟動(dòng)時(shí)的自定義加載。maven resource 配置--下:

<resource>
                <directory>static</directory>
                <targetPath>${project.build.directory}/classes/META-INF/spring-boot-admin-server-ui/extensions/arthas
                </targetPath>
                <filtering>false</filtering>
            </resource>

最終構(gòu)建的 jar 中 META-INFO 中包含相關(guān)的文件即可在 SBA 自帶的 tomcat 啟動(dòng)后加載到相關(guān)的靜態(tài)資源,最后的 url 和自定義實(shí)現(xiàn)的 arthas console 配置的外部 URL 對(duì)應(yīng)即可。

2. 外部鏈接配置

SBA 2.0 開(kāi)始已經(jīng)使用 vue 全家桶了,擴(kuò)展集成均比較方便。其中,官方文檔給出了外嵌連接的配置方式:[_[Linking / Embedding External Pages]_](https://codecentric.github.io/spring-boot-admin/2.3.1/#customizing-external-views)_

參考 sba example 工程的 application.yml 配置即可:

# tag::customization-external-views[]
    spring:
      boot:
        admin:
          ui:
            external-views:
              - label: "Arthas Console"
                url: http://21.129.49.153:8080/
                order: 1900
    # end::customization-external-views[]

3. 對(duì)應(yīng) Spring MVC controller 實(shí)現(xiàn)

參考引用原實(shí)現(xiàn)的 SBA 集成部分,該部分主要修改實(shí)現(xiàn)如下功能:

  • 實(shí)現(xiàn) tunnel server 已經(jīng)加載實(shí)例列表的刷新并展示到前段 AgentID 框供選擇點(diǎn)擊鏈接。

  • 實(shí)現(xiàn)自定義 IP 地址的刷新(解決生產(chǎn)環(huán)境雙生產(chǎn) IP 和運(yùn)維段 IP 不一致的問(wèn)題)。

4. Arthas Spring Boot 插件修改和配置

參考引用原實(shí)現(xiàn)的 SBA 集成中插件修改以及客戶(hù)端配置 application.yml。

對(duì)原版 Spring boot 插件修改主要在于原有插件是通過(guò) Spring的@ConditionalOnMissingBean 實(shí)現(xiàn)自動(dòng)加載。

修改主要是通過(guò)修改這部分實(shí)現(xiàn)通過(guò)配置文件默認(rèn)不啟動(dòng),然后使用時(shí)通過(guò)遠(yuǎn)程啟動(dòng)相關(guān) agent 線程。

5. 基于 Spring Actuator 的 JMX 實(shí)現(xiàn)

SBA client 在 maven 引入中會(huì)默認(rèn)引入 jolokia-core.jar,如果沒(méi)有因?yàn)?SBA client 依賴(lài)可以自行引入該包,可以實(shí)現(xiàn)通過(guò) actuator 開(kāi)放基于 http 的 jmx 操作能力和 SBA 控制臺(tái)的相關(guān)功能無(wú)縫配合。

application.yml 中開(kāi)放 management 相關(guān)配置,根據(jù)自身環(huán)境情況,也可以開(kāi)在客戶(hù)端側(cè)開(kāi)啟 Spring security 認(rèn)證,SBA 也可以很好的支持通過(guò)服務(wù)發(fā)現(xiàn)實(shí)現(xiàn)密碼保護(hù) actuator 端點(diǎn)的訪問(wèn)。

#放開(kāi)management
    management:
      endpoints:
        web:
          exposure:
            # 這里用* 代表暴露所有端點(diǎn)只是為了觀察效果,實(shí)際中按照需進(jìn)行端點(diǎn)暴露
            include: "*"
            exclude: env
      endpoint:
        health:
          # 詳細(xì)信息顯示給所有用戶(hù)。
          show-details: ALWAYS
      health:
        status:
          http-mapping:
            # 自定義健康檢查返回狀態(tài)碼對(duì)應(yīng)的 http 狀態(tài)碼
            FATAL:  503

JMX 實(shí)現(xiàn)參考原文中 EnvironmentChangeListener 的實(shí)現(xiàn)思路,基于 Spring 的 JMX 注解實(shí)現(xiàn)即可。

@Component
   @ManagedResource(objectName = "com.ArthasAgentManageMbean:name=ArthasMbean", description = "Arthas遠(yuǎn)程管理Mbean")
   public class ArthasMbeanImpl {
   
       @Autowired
       private Map<String, String> arthasConfigMap;
   
       @Autowired
       private ArthasProperties arthasProperties;
   
       @Autowired
       private ApplicationContext applicationContext;
   
       /**
        * 初始化
        *
        * @return
        */
       private ArthasAgent arthasAgentInit() {
           arthasConfigMap = StringUtils.removeDashKey(arthasConfigMap);
           // 給配置全加上前綴
           Map<String, String> mapWithPrefix = new HashMap<String, String>(arthasConfigMap.size());
           for (Map.Entry<String, String> entry : arthasConfigMap.entrySet()) {
               mapWithPrefix.put("arthas." + entry.getKey(), entry.getValue());
           }
           final ArthasAgent arthasAgent = new ArthasAgent(mapWithPrefix, arthasProperties.getHome(),
                   arthasProperties.isSlientInit(), null);
           arthasAgent.init();
           return arthasAgent;
       }
   
       @ManagedOperation(description = "獲取配置Arthas Tunnel Server地址")
       public String getArthasTunnelServerUrl() {
           return arthasProperties.getTunnelServer();
       }
   
       @ManagedOperation(description = "設(shè)置Arthas Tunnel Server地址,重新attach后生效")
       @ManagedOperationParameter(name = "tunnelServer", description = "example:ws://127.0.0.1:7777/ws")
       public Boolean setArthasTunnelServerUrl(String tunnelServer) {
           if (tunnelServer == null || tunnelServer.trim().equals("") || tunnelServer.indexOf("ws://") < 0) {
               return false;
           }
           arthasProperties.setTunnelServer(tunnelServer);
           return true;
       }
   
       @ManagedOperation(description = "獲取AgentID")
       public String getAgentId() {
           return arthasProperties.getAgentId();
       }
   
       @ManagedOperation(description = "獲取應(yīng)用名稱(chēng)")
       public String getAppName() {
           return arthasProperties.getAppName();
       }
   
       @ManagedOperation(description = "獲取ArthasConfigMap")
       public HashMap<String, String> getArthasConfigMap() {
           return (HashMap) arthasConfigMap;
       }
   
       @ManagedOperation(description = "返回是否已經(jīng)加載Arthas agent")
       public Boolean isArthasAttched() {
           DefaultListableBeanFactory defaultListableBeanFactory = (DefaultListableBeanFactory) applicationContext.getAutowireCapableBeanFactory();
           String bean = "arthasAgent";
           if (defaultListableBeanFactory.containsBean(bean)) {
               return true;
           }
           return false;
       }
   
       @ManagedOperation(description = "啟動(dòng)Arthas agent")
       public Boolean startArthasAgent() {
           DefaultListableBeanFactory defaultListableBeanFactory = (DefaultListableBeanFactory) applicationContext.getAutowireCapableBeanFactory();
           String bean = "arthasAgent";
           if (defaultListableBeanFactory.containsBean(bean)) {
               ((ArthasAgent) defaultListableBeanFactory.getBean(bean)).init();
               return true;
           }
           defaultListableBeanFactory.registerSingleton(bean, arthasAgentInit());
           return true;
       }
   
       @ManagedOperation(description = "關(guān)閉Arthas agent,暫未實(shí)現(xiàn)")
       public Boolean stopArthasAgent() {
           // TODO 無(wú)法獲取自定義tmp文件夾加載的classLoader,因此無(wú)法獲取到com.taobao.arthas.core.server.ArthasBootstrap類(lèi)并調(diào)用destroy方法
           DefaultListableBeanFactory defaultListableBeanFactory = (DefaultListableBeanFactory) applicationContext.getAutowireCapableBeanFactory();
           String bean = "arthasAgent";
           if (defaultListableBeanFactory.containsBean(bean)) {
               defaultListableBeanFactory.destroySingleton(bean);
               return true;
           } else {
               return false;
           }
       }
   }

實(shí)際使用

管理工程投產(chǎn)后,多次在生產(chǎn)環(huán)境用于問(wèn)題排查和代碼熱修復(fù)。性能問(wèn)題主要用于性能流控組件以及灰度發(fā)布相關(guān)配置參數(shù)的在線驗(yàn)證和 debug。

代碼熱加載相關(guān)初期通過(guò) jad+mc 的方式進(jìn)行操作,后續(xù)發(fā)現(xiàn) jad 在部分代碼上因環(huán)境配置以及 jvm 問(wèn)題產(chǎn)生反編譯代碼不一致的情況,后續(xù)通過(guò) maven 打包部署應(yīng)用程序 source 壓縮包的方式解決,直接使用和應(yīng)用 jar 同版本構(gòu)建的 source 進(jìn)行修改更加可靠。整體方案在管理較為嚴(yán)格的生產(chǎn)環(huán)境提供了有效的性能分析以及熱修復(fù)的能力。

遺留問(wèn)題

現(xiàn)有官方提供的
com.taobao.arthas.agent.attach.ArthasAgent 中啟動(dòng) arthas agent 的客戶(hù)端使用的 arthasClassLoader 和 bootstrapClass 均為方法內(nèi)的臨時(shí)變量,外部無(wú)法獲取相關(guān)句柄實(shí)現(xiàn)通過(guò) bootstrapClass 關(guān)閉 arthas agent 的功能;臨時(shí)解決方案為通過(guò) JMX 啟動(dòng)后,在 web console 連接使用后,使用 stop 命令實(shí)現(xiàn)目標(biāo)進(jìn)程中 arthas agent 的關(guān)閉。

現(xiàn)有字節(jié)碼加載工具可以很好的實(shí)現(xiàn)內(nèi)部類(lèi),私有類(lèi)的在線熱部署替換,同時(shí)經(jīng)測(cè)試可以兼容 SkyWalk8.x 版本的 javaagent 插件,但是在測(cè)試環(huán)境因?yàn)榕渲糜?jacoco 覆蓋度采集插件與 Arthas 字節(jié)碼產(chǎn)生了不兼容的情況,在部分環(huán)境使用時(shí)需要先關(guān)閉對(duì)應(yīng)的 agent 后才能正常使用 arthas 的相關(guān)功能。

上述就是小編為大家分享的SpringBoot Admin2.0集成Java Arthas的實(shí)踐是怎樣的了,如果剛好有類(lèi)似的疑惑,不妨參照上述分析進(jìn)行理解。如果想知道更多相關(guān)知識(shí),歡迎關(guān)注億速云行業(yè)資訊頻道。

向AI問(wèn)一下細(xì)節(jié)

免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如果涉及侵權(quán)請(qǐng)聯(lián)系站長(zhǎng)郵箱:is@yisu.com進(jìn)行舉報(bào),并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。

AI