SpringBoot Admin集成诊断利器Arthas实践

前言

Arthas 是 Alibaba开源的Java诊断工具,具有实时查看系统的运行状况,查看函数调用参数、返回值和异常,在线热更新代码,秒解决类冲突问题、定位类加载路径,生成热点图,通过网页诊断线上应用。  如今在各大厂都有广泛应用,也延伸出很多产品。

这里将介绍如何将Arthas集成进SpringBoot监控平台中。

SpringBoot Admin

为了方便SpringBoot Admin 简称为SBA

版本:1.5.x
1.5版本的SBA如果要开发插件比较麻烦,需要下载SBA的源码包,再按照spring-boot-admin-server-ui-hystrix的形式copy一份,由于JS使用的是Angular,本人放弃了

版本:2.x 2.x版本的SBA插件开发,官网有介绍如何开发,JS使用Vue,方便很多,由于我们项目还在使用1.5,所以并没有使用该版本,请读者自行尝试

不能使用SBA的插件进行集成,那还有什么办法呢?????

SBA 集成

鄙人的办法是将Arthas的相关文件直接copy到admin服务中

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

  • endpoint包下的文件可以都注释掉,没多大用

  • ArthasController这个文件是我自己新建的,用来获取所有注册到Arthas的客户端,这在后面是有用的

  • 其他文件直接copy过来就行

@RequestMapping("/api/arthas")
@RestController
public class ArthasController {@Autowiredprivate TunnelServer tunnelServer;@RequestMapping(value = "/clients", method = RequestMethod.GET)public Set getClients() {Map agentInfoMap = tunnelServer.getAgentInfoMap();return agentInfoMap.keySet();}
}

spring-boot-admin-server-ui
该文件建在resources.META-INF下,admin会在启动的时候加载该目录下的文件

  • index.html 覆盖SBA原来的首页,在其中添加一个导航,首页会是这样



Spring Boot Admin

Arthas{view.state}}" ng-bind-html="view.title">
  • ReferenceGuide
  • -
  • Sources
  • -
  • Code licensed under Apache License2.0
  • sbaModules = []; angular.element(document).ready(function () {angular.bootstrap(document, sbaModules.slice(0), {strictDi: true});});
    • arthas.html 新建页面,用于显示arthas控制台页面

    
    
    Spring Boot Adminwindow.addEventListener('resize', function () {var terminalSize = getTerminalSize();ws.send(JSON.stringify({ action: 'resize', cols: terminalSize.cols, rows: terminalSize.rows }));xterm.resize(terminalSize.cols, terminalSize.rows);});
    
    ArthasApplicationsTurbineJournalAbout
    Select Application: Connect Disconnect Release
    
    
    
    • 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("" + server[0] + "");}
    }/*** 重置配置文件*/
    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@Beanpublic HashMap arthasConfigMap() {return new HashMap();}}
    
    @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;}}
    
    • 实现开关效果
      为了实现开关效果,还需要一个文件用来监听配置文件的改变
      我这里使用的是在SBA中改变环境变量,对应服务监听到变量改变,当监听spring.arthas.enabled为true的时候,注册arthas, 到下面是代码

    @Component
    public class EnvironmentChangeListener implements ApplicationListener {@Autowiredprivate Environment env;@Autowiredprivate Map arthasConfigMap;@Autowiredprivate ArthasProperties arthasProperties;@Autowiredprivate ApplicationContext applicationContext;@Overridepublic void onApplicationEvent(EnvironmentChangeEvent event) {Set 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 mapWithPrefix = new HashMap(arthasConfigMap.size());for (Map.Entry 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插件的方式集成

    • 如上集成仅供参考,还是需要根据自己企业的情况来做

    作者:阿提说说,绿城理想生活Java工程师

    那些年,用Arthas排查过的问题

    欢迎大家在“原文链接”里投稿,有丰富的奖品等你噢。

    • 凡提交满足投稿要求文章的同学,将获得 Arthas Most Valuable User 福袋一份(礼品随机),包含淘公仔、Arthas 贴纸、阿里云 T 恤、JetBrains 周边礼包;

    • 第一期最受欢迎的 top3 文章,获得天猫精灵一台;

    • 年度 top 20 文章,将有机会获得 cherry 键盘及 JetBrains 提供的包括 Coupon 等周边礼包 。


    本文来自互联网用户投稿,文章观点仅代表作者本人,不代表本站立场,不承担相关法律责任。如若转载,请注明出处。 如若内容造成侵权/违法违规/事实不符,请点击【内容举报】进行投诉反馈!

    相关文章

    立即
    投稿

    微信公众账号

    微信扫一扫加关注

    返回
    顶部