中文字幕av专区_日韩电影在线播放_精品国产精品久久一区免费式_av在线免费观看网站

溫馨提示×

溫馨提示×

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

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務條款》

Springboot Admin2.0如何整合Arthas

發布時間:2022-02-25 15:06:04 來源:億速云 閱讀:174 作者:小新 欄目:開發技術

這篇文章主要介紹了Springboot Admin2.0如何整合Arthas,具有一定借鑒價值,感興趣的朋友可以參考下,希望大家閱讀完這篇文章之后大有收獲,下面讓小編帶著大家一起了解一下。

    項目最初使用 Arthas 主要有兩個目的:

    1. 通過 arthas 解決實現測試環境、性能測試環境以及生產環境性能問題分析工具的問題。

    2. 通過使用 jad、mc、redefine 功能組合實現生產環境部分節點代碼熱更新的能力。

    技術選型相關

    因為公司還未能建立起較為統一的生產微服務配置以及狀態管理的能力,各自系統的研發運維較為獨立。現在項目使用了 Spring Cloud 以及 Eureka 的框架結構,和 SBA 的基礎支撐能力較為匹配,同時,SBA 已經可以提供服務感知,日志級別配置管理,以及基于 actuator 的 JVM、Spring 容器的眾多管理插件,可以滿足基礎使用的需求。

    在調研期間,Arthas 整體版本為 3.4.5,提供了基于 Webconsole 的 Tunner Server 模式,通過前面鏈接文章已經實踐,與SBA已經可以實現集成。因為項目本身沒有歷史包袱,在實際集成的過程中采用了 SBA 2.0 版本以提供更多的管理功能和圖形界面能力。其他優點:

    • web console 界面嵌入 SBA 整體密碼登錄和網頁權限管理,實現登陸 SBA 后才可以使用相關 arthas web console 的功能。

    • 基于SBA 客戶端依賴的 jolokia-core 開放目標服務進程的 jmx 管理,通過實現 jmx 接口復用 SBA 的相關操作界面,減少前端界面開發能力的要求。

    整體結構

    Springboot Admin2.0如何整合Arthas

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

    實現效果

    SBA 2.0 最大的方便就是提供了配置化鏈接外部網頁的能力,同時如果網頁實現在當前 JVM 進程,可以實現 Spring-Security 的本地權限管理,在生產環境下只有在登錄 SBA 后才能使用相關集成的 arthas 功能。

    • 登錄界面

    Springboot Admin2.0如何整合Arthas

    • 外嵌連接位置

    Springboot Admin2.0如何整合Arthas

    • JMX 的使用

    Springboot Admin2.0如何整合Arthas

    Springboot Admin2.0如何整合Arthas

    • 跳轉 arthas web console

    Springboot Admin2.0如何整合Arthas

    改造方案

    1. 整體工程結構

    Springboot Admin2.0如何整合Arthas

    整體工程修改自 SBA 開源項目的 example 工程,具體使用 custom-ui 的工程鏈接為:[spring-boot-admin-sample-custom-ui]_,_紅色框的部分是 arthas web console 的全部靜態文件,通過 Maven Resource 的指定配置打入指定目錄,實現 SBA 啟動時的自定義加載。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>

    2. 外部鏈接配置

    SBA 2.0 開始已經使用 vue 全家桶了,擴展集成均比較方便。其中,官方文檔給出了外嵌連接的配置方式:[Linking / Embedding External Pages]。

    參考 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. 對應 Spring MVC controller 實現

    參考引用原實現的 SBA 集成部分,該部分主要修改實現如下功能:

    • 實現 tunnel server 已經加載實例列表的刷新并展示到前段 AgentID 框供選擇點擊鏈接。

    • 實現自定義 IP 地址的刷新(解決生產環境雙生產 IP 和運維段 IP 不一致的問題)。

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

    參考引用原實現的 SBA 集成中插件修改以及客戶端配置 application.yml。

    對原版 Spring boot 插件修改主要在于原有插件是通過 Spring的@ConditionalOnMissingBean 實現自動加載。

    修改主要是通過修改這部分實現通過配置文件默認不啟動,然后使用時通過遠程啟動相關 agent 線程。

    5. 基于 Spring Actuator 的 JMX 實現

    SBA client 在 maven 引入中會默認引入 jolokia-core.jar,如果沒有因為 SBA client 依賴可以自行引入該包,可以實現通過 actuator 開放基于 http 的 jmx 操作能力和 SBA 控制臺的相關功能無縫配合。

    application.yml 中開放 management 相關配置,根據自身環境情況,也可以開在客戶端側開啟 Spring security 認證,SBA 也可以很好的支持通過服務發現實現密碼保護 actuator 端點的訪問。

    #放開management
        management:
          endpoints:
            web:
              exposure:
                # 這里用* 代表暴露所有端點只是為了觀察效果,實際中按照需進行端點暴露
                include: "*"
                exclude: env
          endpoint:
            health:
              # 詳細信息顯示給所有用戶。
              show-details: ALWAYS
          health:
            status:
              http-mapping:
                # 自定義健康檢查返回狀態碼對應的 http 狀態碼
                FATAL:  503

    JMX 實現參考原文中 EnvironmentChangeListener 的實現思路,基于 Spring 的 JMX 注解實現即可。

    @Component
       @ManagedResource(objectName = "com.ArthasAgentManageMbean:name=ArthasMbean", description = "Arthas遠程管理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 = "設置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 = "獲取應用名稱")
           public String getAppName() {
               return arthasProperties.getAppName();
           }
       
           @ManagedOperation(description = "獲取ArthasConfigMap")
           public HashMap<String, String> getArthasConfigMap() {
               return (HashMap) arthasConfigMap;
           }
       
           @ManagedOperation(description = "返回是否已經加載Arthas agent")
           public Boolean isArthasAttched() {
               DefaultListableBeanFactory defaultListableBeanFactory = (DefaultListableBeanFactory) applicationContext.getAutowireCapableBeanFactory();
               String bean = "arthasAgent";
               if (defaultListableBeanFactory.containsBean(bean)) {
                   return true;
               }
               return false;
           }
       
           @ManagedOperation(description = "啟動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 = "關閉Arthas agent,暫未實現")
           public Boolean stopArthasAgent() {
               // TODO 無法獲取自定義tmp文件夾加載的classLoader,因此無法獲取到com.taobao.arthas.core.server.ArthasBootstrap類并調用destroy方法
               DefaultListableBeanFactory defaultListableBeanFactory = (DefaultListableBeanFactory) applicationContext.getAutowireCapableBeanFactory();
               String bean = "arthasAgent";
               if (defaultListableBeanFactory.containsBean(bean)) {
                   defaultListableBeanFactory.destroySingleton(bean);
                   return true;
               } else {
                   return false;
               }
           }
       }

    實際使用

    管理工程投產后,多次在生產環境用于問題排查和代碼熱修復。性能問題主要用于性能流控組件以及灰度發布相關配置參數的在線驗證和 debug。

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

    遺留問題

    現有官方提供的 com.taobao.arthas.agent.attach.ArthasAgent 中啟動 arthas agent 的客戶端使用的 arthasClassLoader 和 bootstrapClass 均為方法內的臨時變量,外部無法獲取相關句柄實現通過 bootstrapClass 關閉 arthas agent 的功能;臨時解決方案為通過 JMX 啟動后,在 web console 連接使用后,使用 stop 命令實現目標進程中 arthas agent 的關閉。

    現有字節碼加載工具可以很好的實現內部類,私有類的在線熱部署替換,同時經測試可以兼容 SkyWalk8.x 版本的 javaagent 插件,但是在測試環境因為配置有 jacoco 覆蓋度采集插件與 Arthas 字節碼產生了不兼容的情況,在部分環境使用時需要先關閉對應的 agent 后才能正常使用 arthas 的相關功能。

    感謝你能夠認真閱讀完這篇文章,希望小編分享的“Springboot Admin2.0如何整合Arthas”這篇文章對大家有幫助,同時也希望大家多多支持億速云,關注億速云行業資訊頻道,更多相關知識等著你來學習!

    向AI問一下細節

    免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。

    AI

    桂阳县| 北海市| 堆龙德庆县| 名山县| 全州县| 石河子市| 隆子县| 西安市| 内黄县| 陈巴尔虎旗| 崇阳县| 甘谷县| 原阳县| 梓潼县| 承德县| 仙桃市| 奈曼旗| 弋阳县| 宣威市| 沧源| 朝阳县| 阿城市| 恩平市| 镇远县| 海原县| 木兰县| 手机| 越西县| 汉源县| 兖州市| 达孜县| 巨野县| 屏东市| 阳信县| 楚雄市| 枝江市| 康定县| 南昌县| 安泽县| 鄄城县| 平凉市|