前言
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 { @Autowired private TunnelServer tunnelServer; @RequestMapping(value = "/clients", method = RequestMethod.GET) public SetgetClients() { Map agentInfoMap = tunnelServer.getAgentInfoMap(); return agentInfoMap.keySet(); } }
spring-boot-admin-server-ui
该文件建在resources.META-INF下,admin会在启动的时候加载该目录下的文件
index.html 覆盖SBA原来的首页,在其中添加一个导航,首页会是这样
Spring Boot Admin
arthas.html 新建页面,用于显示arthas控制台页面
Spring Boot Admin
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(""); } } /** * 重置配置文件 */ 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 HashMaparthasConfigMap() { 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{ @Autowired private Environment env; @Autowired private Map arthasConfigMap; @Autowired private ArthasProperties arthasProperties; @Autowired private ApplicationContext applicationContext; @Override public 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插件的方式集成
- 如上集成仅供参考,还是需要根据自己企业的情况来做
以上就是SpringBoot Admin集成诊断利器Arthas示例实现的详细内容,更多关于SpringBoot Admin集成Arthas的资料请关注脚本之家其它相关文章!