最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

SpringBoot?Admin集成診斷利器Arthas示例實現(xiàn)

 更新時間:2022年06月08日 10:12:59   作者:橫云斷嶺  
這篇文章主要為大家介紹了SpringBoot?Admin集成診斷利器Arthas示例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步,早日升職加薪

前言

Arthas 是 Alibaba開源的Java診斷工具,具有實時查看系統(tǒng)的運行狀況,查看函數(shù)調用參數(shù)、返回值和異常,在線熱更新代碼,秒解決類沖突問題、定位類加載路徑,生成熱點圖,通過網(wǎng)頁診斷線上應用。  如今在各大廠都有廣泛應用,也延伸出很多產品。

這里將介紹如何將Arthas集成進SpringBoot監(jiān)控平臺中。

SpringBoot Admin

為了方便SpringBoot Admin 簡稱為SBA

版本:1.5.x

1.5版本的SBA如果要開發(fā)插件比較麻煩,需要下載SBA的源碼包,再按照spring-boot-admin-server-ui-hystrix的形式copy一份,由于JS使用的是Angular,本人放棄了

版本:2.x

2.x版本的SBA插件開發(fā),官網(wǎng)有介紹如何開發(fā),JS使用Vue,方便很多,由于我們項目還在使用1.5,所以并沒有使用該版本,請讀者自行嘗試

不能使用SBA的插件進行集成,那還有什么辦法呢?????

SBA 集成

鄙人的辦法是將Arthas的相關文件直接copy到admin服務中

arthas包該包下存放的是所有arthas的Java文件

  • endpoint包下的文件可以都注釋掉,沒多大用
  • ArthasController這個文件是我自己新建的,用來獲取所有注冊到Arthas的客戶端,這在后面是有用的
  • 其他文件直接copy過來就行
@RequestMapping("/api/arthas")
@RestController
public class ArthasController {
 @Autowired
 private TunnelServer tunnelServer;
 @RequestMapping(value = "/clients", method = RequestMethod.GET)
 public Set<String> getClients() {
  Map<String, AgentInfo> agentInfoMap = tunnelServer.getAgentInfoMap();
  return agentInfoMap.keySet();
 }
}

spring-boot-admin-server-ui

該文件建在resources.META-INF下,admin會在啟動的時候加載該目錄下的文件

index.html 覆蓋SBA原來的首頁,在其中添加一個導航,首頁會是這樣

<!DOCTYPE html>
<html class="no-js">
<head>
    <meta charset="utf-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <title>Spring Boot Admin</title>
    <meta name="description" content="">
    <meta name="viewport" content="width=device-width">
    <link rel="shortcut icon" type="image/x-icon" href="img/favicon.png" rel="external nofollow" />
    <link rel="stylesheet" type="text/css" href="core.css" rel="external nofollow" />
    <link rel="stylesheet" type="text/css" href="all-modules.css" rel="external nofollow" />
</head>
<body>
<header class="navbar header--navbar desktop-only">
    <div class="navbar-inner">
        <div class="container-fluid">
            <div class="spring-logo--container">
                <a class="spring-logo" href="#" rel="external nofollow"  rel="external nofollow"  rel="external nofollow"  rel="external nofollow" ><span></span></a>
            </div>
            <div class="spring-logo--container">
                <a class="spring-boot-logo" href="#" rel="external nofollow"  rel="external nofollow"  rel="external nofollow"  rel="external nofollow" ><span></span></a>
            </div>
            <ul class="nav pull-right">
              <!--增加Arthas導航-->
                <li class="navbar-link ng-scope">
                    <a  class="ng-binding" href="arthas/arthas.html" rel="external nofollow" >Arthas</a>
                </li>
                <li ng-repeat="view in mainViews" class="navbar-link" ng-class="{active: $state.includes(view.state)}">
                    <a ui-sref="{{view.state}}" ng-bind-html="view.title"></a>
                </li>
            </ul>
        </div>
    </div>
</header>
<div ui-view></div>
<footer class="footer">
    <ul class="inline">
        <li><a  rel="external nofollow"  target="_blank">Reference
            Guide</a></li>
        <li>-</li>
        <li><a  rel="external nofollow"  target="_blank">Sources</a></li>
        <li>-</li>
        <li>Code licensed under <a  rel="external nofollow"  target="_blank">Apache License
            2.0</a></li>
    </ul>
</footer>
<script src="dependencies.js" type="text/javascript"></script>
<script type="text/javascript">
  sbaModules = [];
</script>
<script src="core.js" type="text/javascript"></script>
<script src="all-modules.js" type="text/javascript"></script>
<script type="text/javascript">
  angular.element(document).ready(function () {
    angular.bootstrap(document, sbaModules.slice(0), {
      strictDi: true
    });
  });
</script>
</body>
</html>

arthas.html 新建頁面,用于顯示arthas控制臺頁面

<!DOCTYPE html>
<html class="no-js">
<head>
    <meta charset="utf-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <title>Spring Boot Admin</title>
    <meta name="description" content="">
    <meta name="viewport" content="width=device-width">
    <link rel="shortcut icon" type="image/x-icon" href="../img/favicon.png" rel="external nofollow" />
    <link rel="stylesheet" type="text/css" href="../core.css" rel="external nofollow" />
    <link rel="stylesheet" type="text/css" href="../all-modules.css" rel="external nofollow" />
    <script src="js/jquery-3.3.1.min.js"></script>
    <script src="js/popper-1.14.6.min.js"></script>
    <script src="js/xterm.js"></script>
    <script src="js/web-console.js"></script>
    <script src="js/arthas.js"></script>
    <link href="js/xterm.css" rel="external nofollow"  rel="stylesheet" />
    <script type="text/javascript">
        window.addEventListener('resize', function () {
            var terminalSize = getTerminalSize();
            ws.send(JSON.stringify({ action: 'resize', cols: terminalSize.cols, rows: terminalSize.rows }));
            xterm.resize(terminalSize.cols, terminalSize.rows);
        });
    </script>
</head>
<body>
<header class="navbar header--navbar desktop-only">
    <div class="navbar-inner">
        <div class="container-fluid">
            <div class="spring-logo--container">
                <a class="spring-logo" href="#" rel="external nofollow"  rel="external nofollow"  rel="external nofollow"  rel="external nofollow" ><span></span></a>
            </div>
            <div class="spring-logo--container">
                <a class="spring-boot-logo" href="#" rel="external nofollow"  rel="external nofollow"  rel="external nofollow"  rel="external nofollow" ><span></span></a>
            </div>
            <ul class="nav pull-right">
                <li class="navbar-link ng-scope">
                    <a  class="ng-binding" href="arthas.html" rel="external nofollow" >Arthas</a>
                </li>
                <li class="navbar-link ng-scope">
                    <a  class="ng-binding" href="../" rel="external nofollow" >Applications</a>
                </li>
                <li class="navbar-link ng-scope">
                    <a  class="ng-binding" href="../#/turbine" rel="external nofollow" >Turbine</a>
                </li>
                <li class="navbar-link ng-scope">
                    <a  class="ng-binding" href="../#/events" rel="external nofollow" >Journal</a>
                </li>
                <li class="navbar-link ng-scope">
                    <a  class="ng-binding" href="../#/about" rel="external nofollow" >About</a>
                </li>
                <li class="navbar-link ng-scope">
                    <a  class="ng-binding" href="../#/logout" rel="external nofollow" ><i class="fa fa-2x fa-sign-out" aria-hidden="true"></i></a>
                </li>
            </ul>
        </div>
    </div>
</header>
<div ui-view>
    <div class="container-fluid">
        <form class="form-inline">
            <input type="hidden" id="ip" name="ip" value="127.0.0.1">
            <input type="hidden" id="port" name="port" value="19898">
            Select Application:
            <select id="selectServer"></select>
            <button class="btn" onclick="startConnect()" type="button"><i class="fa fa-connectdevelop"></i> Connect</button>
            <button class="btn" onclick="disconnect()" type="button"><i class="fa fa-search-minus"></i> Disconnect</button>
            <button class="btn" onclick="release()" type="button"><i class="fa fa-search-minus"></i> Release</button>
        </form>
        <div id="terminal-card">
            <div id="terminal"></div>
        </div>
    </div>
</div>
</body>
</html>

arthas.js 存儲頁面控制的js

var registerApplications = null;
var applications = null;
$(document).ready(function () {
    reloadRegisterApplications();
    reloadApplications();
});
/**
 * 獲取注冊的arthas客戶端
 */
function reloadRegisterApplications() {
    var result = reqSync("/api/arthas/clients", "get");
    registerApplications = result;
    initSelect("#selectServer", registerApplications, "");
}
/**
 * 獲取注冊的應用
 */
function reloadApplications() {
    applications = reqSync("/api/applications", "get");
    console.log(applications)
}
/**
 * 初始化下拉選擇框
 */
function initSelect(uiSelect, list, key) {
    $(uiSelect).html('');
    var server;
    for (var i = 0; i < list.length; i++) {
        server = list[i].toLowerCase().split("@");
        if ("phantom-admin" === server[0]) continue;
        $(uiSelect).append("<option value=" + list[i].toLowerCase() + ">" + server[0] + "</option>");
    }
}
/**
 * 重置配置文件
 */
function release() {
    var currentServer = $("#selectServer").text();
    for (var i = 0; i < applications.length; i++) {
        serverId = applications[i].id;
        serverName = applications[i].name.toLowerCase();
        console.log(serverId + "/" + serverName);
        if (currentServer === serverName) {
            var result = reqSync("/api/applications/" +serverId+ "/env/reset", "post");
            alert("env reset success");
        }
    }
}
function reqSync(url, method) {
    var result = null;
    $.ajax({
        url: url,
        type: method,
        async: false, //使用同步的方式,true為異步方式
        headers: {
            'Content-Type': 'application/json;charset=utf8;',
        },
        success: function (data) {
            // console.log(data);
            result = data;
        },
        error: function (data) {
            console.log("error");
        }
    });
    return result;
}
  • 其他文件 jquery-3.3.1.min.js 新加Js

copy過來的js

popper-1.14.6.min.js

web-console.js

xterm.css

xterm.js

  • bootstrap.yml
# arthas端口
arthas:
  server:
    port: 9898

這樣子,admin端的配置完成了

客戶端配置

在配置中心加入配置

#arthas服務端域名
arthas.tunnel-server = ws://admin域名/ws
#客戶端id,應用名@隨機值,js會截取前面的應用名
arthas.agent-id = ${spring.application.name}@${random.value}
#arthas開關,可以在需要調試的時候開啟,不需要的時候關閉
spring.arthas.enabled = false

需要自動Attach的應用中引入arthas-spring-boot-starter 需要對starter進行部分修改,要將注冊arthas的部分移除,下面是修改后的文件。

我這里是將修改后的文件重新打包成jar包,上傳到私服,但有些應用會有無法加載arthasConfigMap的情況,可以將這兩個文件單獨放到項目的公共包中

@EnableConfigurationProperties({ ArthasProperties.class })
public class ArthasConfiguration {
 private static final Logger logger = LoggerFactory.getLogger(ArthasConfiguration.class);
 @ConfigurationProperties(prefix = "arthas")
 @ConditionalOnMissingBean
 @Bean
 public HashMap<String, String> arthasConfigMap() {
  return new HashMap<String, String>();
 }
}
@ConfigurationProperties(prefix = "arthas")
public class ArthasProperties {
 private String ip;
 private int telnetPort;
 private int httpPort;
 private String tunnelServer;
 private String agentId;
 /**
  * report executed command
  */
 private String statUrl;
 /**
  * session timeout seconds
  */
 private long sessionTimeout;
 private String home;
 /**
  * when arthas agent init error will throw exception by default.
  */
 private boolean slientInit = false;
 public String getHome() {
  return home;
 }
 public void setHome(String home) {
  this.home = home;
 }
 public boolean isSlientInit() {
  return slientInit;
 }
 public void setSlientInit(boolean slientInit) {
  this.slientInit = slientInit;
 }
 public String getIp() {
  return ip;
 }
 public void setIp(String ip) {
  this.ip = ip;
 }
 public int getTelnetPort() {
  return telnetPort;
 }
 public void setTelnetPort(int telnetPort) {
  this.telnetPort = telnetPort;
 }
 public int getHttpPort() {
  return httpPort;
 }
 public void setHttpPort(int httpPort) {
  this.httpPort = httpPort;
 }
 public String getTunnelServer() {
  return tunnelServer;
 }
 public void setTunnelServer(String tunnelServer) {
  this.tunnelServer = tunnelServer;
 }
 public String getAgentId() {
  return agentId;
 }
 public void setAgentId(String agentId) {
  this.agentId = agentId;
 }
 public String getStatUrl() {
  return statUrl;
 }
 public void setStatUrl(String statUrl) {
  this.statUrl = statUrl;
 }
 public long getSessionTimeout() {
  return sessionTimeout;
 }
 public void setSessionTimeout(long sessionTimeout) {
  this.sessionTimeout = sessionTimeout;
 }
}

實現(xiàn)開關效果

為了實現(xiàn)開關效果,還需要一個文件用來監(jiān)聽配置文件的改變
我這里使用的是在SBA中改變環(huán)境變量,對應服務監(jiān)聽到變量改變,當監(jiān)聽spring.arthas.enabled為true的時候,注冊arthas, 到下面是代碼

@Component
public class EnvironmentChangeListener implements ApplicationListener<EnvironmentChangeEvent> {
    @Autowired
    private Environment env;
    @Autowired
    private Map<String, String> arthasConfigMap;
    @Autowired
    private ArthasProperties arthasProperties;
    @Autowired
    private ApplicationContext applicationContext;
    @Override
    public void onApplicationEvent(EnvironmentChangeEvent event) {
        Set<String> keys = event.getKeys();
        for (String key : keys) {
            if ("spring.arthas.enabled".equals(key)) {
                if ("true".equals(env.getProperty(key))) {
                    registerArthas();
                }
            }
        }
    }
    private void registerArthas() {
        DefaultListableBeanFactory defaultListableBeanFactory = (DefaultListableBeanFactory) applicationContext.getAutowireCapableBeanFactory();
        String bean = "arthasAgent";
        if (defaultListableBeanFactory.containsBean(bean)) {
            ((ArthasAgent)defaultListableBeanFactory.getBean(bean)).init();
            return;
        }
        defaultListableBeanFactory.registerSingleton(bean, arthasAgentInit());
    }
    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;
    }
}

結束

到此可以愉快的在SBA中調試應用了,看看最后的頁面

調試流程

開啟Arthas

在Select Application中選擇應用

  • Connect 連接應用
  • DisConnect 斷開應用
  • Release 釋放配置文件

這種集成方式有一些缺陷:

  • 使用jar包的方式引入應用,具有一定的侵略性,如果arthas無法啟動,會導致應用也無法啟動
  • 如果使用docker,需要適當調整JVM內存,防止開啟arthas的時候,內存炸了
  • 沒有使用SBA插件的方式集成
  • 如上集成僅供參考,還是需要根據(jù)自己企業(yè)的情況來做

以上就是SpringBoot Admin集成診斷利器Arthas示例實現(xiàn)的詳細內容,更多關于SpringBoot Admin集成Arthas的資料請關注腳本之家其它相關文章!

相關文章

  • IDEA編譯報錯“java: 常量字符串過長”的原因及解決方法

    IDEA編譯報錯“java: 常量字符串過長”的原因及解決方法

    今天在開發(fā)過程中,由于嘗試將一個文件的 Base64 字符串設置為常量,結果導致 IDEA 編譯的時候出現(xiàn)了如下報錯java: 常量字符串過長,所以本文給大家記錄了IDEA編譯報錯“java: 常量字符串過長”的原因及解決方法,需要的朋友可以參考下
    2025-02-02
  • Java?Spring中Bean的作用域及生命周期

    Java?Spring中Bean的作用域及生命周期

    這篇文章主要介紹了Java?Spring中Bean的作用域及生命周期,Bean的作用域默認是單例模式的,也就是說所有?的使?的都是同?個對象,更多相關內容需要的朋友可以參考一下
    2022-08-08
  • java面試LruCache?和?LinkedHashMap及算法實現(xiàn)

    java面試LruCache?和?LinkedHashMap及算法實現(xiàn)

    這篇文章主要為大家介紹了java面試LruCache?和?LinkedHashMap及算法實現(xiàn)示例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步,早日升職加薪
    2023-02-02
  • SpringBoot日志框架如何使用

    SpringBoot日志框架如何使用

    這篇文章主要介紹了SpringBoot日志框架如何使用,幫助大家更好的理解和使用springboot日志框架,感興趣的朋友可以了解下
    2021-01-01
  • JDK1.7以上javaFTP上傳刪除文件的實現(xiàn)方法

    JDK1.7以上javaFTP上傳刪除文件的實現(xiàn)方法

    下面小編就為大家分享一篇JDK1.7以上javaFTP上傳刪除文件的實現(xiàn)方法,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧
    2017-11-11
  • java使用es查詢的示例代碼

    java使用es查詢的示例代碼

    本篇文章主要介紹了java使用es查詢的示例代碼,小編覺得挺不錯的,現(xiàn)在分享給大家,也給大家做個參考。一起跟隨小編過來看看吧
    2018-01-01
  • spring batch 讀取多個文件數(shù)據(jù)導入數(shù)據(jù)庫示例

    spring batch 讀取多個文件數(shù)據(jù)導入數(shù)據(jù)庫示例

    本篇文章主要介紹了spring batch 讀取多個文件數(shù)據(jù)導入數(shù)據(jù)庫示例,小編覺得挺不錯的,現(xiàn)在分享給大家,也給大家做個參考。一起跟隨小編過來看看吧
    2017-03-03
  • SpringBoot根據(jù)Word模板導出復雜格式的文檔

    SpringBoot根據(jù)Word模板導出復雜格式的文檔

    這篇文章主要為大家詳細介紹了Spring Boot 中根據(jù) Word 模板導出包含表格、圖表等復雜格式的文檔的相關實現(xiàn)方法,大家可以根據(jù)自己的需求進行選擇
    2025-08-08
  • java 中http請求為了防止亂碼解決方案

    java 中http請求為了防止亂碼解決方案

    這篇文章主要介紹了java 中http請求為了防止亂碼解決方案的相關資料,需要的朋友可以參考下
    2017-02-02
  • Java super和this的對比及使用

    Java super和this的對比及使用

    這篇文章主要介紹了Java super和this的對比及使用的相關資料,java中this與super會經(jīng)常在使用的時候混淆,需要的朋友可以參考下
    2017-08-08

最新評論

敖汉旗| 定结县| 二连浩特市| 原平市| 新平| 富阳市| 江口县| 赫章县| 铁岭县| 凤山县| 交口县| 伊吾县| 额尔古纳市| 资中县| 浦江县| 南江县| 澄城县| 宁津县| 鄢陵县| 清镇市| 绿春县| 阿瓦提县| 肥西县| 白银市| 白水县| 米易县| 修武县| 儋州市| 太康县| 沙田区| 融水| 东乡县| 苏尼特右旗| 新竹县| 九寨沟县| 中江县| 商南县| 黑山县| 洛南县| 蛟河市| 巨野县|