接上一篇服务端改造
核心改造说明
- 基于arthas-springboot-starter进行改造,自动启动更改为通过jmx mbean的方式手动启动和停止
- 我们的服务都是springcloud基于K8S的,在docker上做了微调适配
- 基于nacos,arthas的服务端配置使用了公共文件
arthas-springboot-starter改造
此步骤主要参考博文进行整合改造,核心改造点:
![](https://img.laitimes.com/img/9ZDMuAjOiMmIsIjOiQnIsIiNx8FesU2cfdGLwczX0xiRGZkRGZ0Xy9GbvNGL5EzXlpXazxSPwMUcjF2TxNWYtgVQClGVF5UMR9Fd4VGdsATNfd3bkFGazxycykFaKdkYzZUbapXNXlleSdVY2pESa9VZwlHdssmch1mclRXY39CXldWYtlWPzNXZj9mcw1ycz9WL49zZuBnL4QWMlFWM4IWO3EDO4EGMiFGN4QjZ3U2NhNmY3kjM4kzLc52YucWbp5GZzNmLn9Gbi1yZtl2Lc9CX6MHc0RHaiojIsJye.png)
pom引用
<properties>
<maven.compiler.source>8</maven.compiler.source>
<maven.compiler.target>8</maven.compiler.target>
<arthas.version>3.4.5</arthas.version>
</properties>
<dependencies>
<dependency>
<groupId>com.taobao.arthas</groupId>
<artifactId>arthas-agent-attach</artifactId>
<version>${arthas.version}</version>
</dependency>
<dependency>
<groupId>com.taobao.arthas</groupId>
<artifactId>arthas-packaging</artifactId>
<version>${arthas.version}</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-configuration-processor</artifactId>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-context</artifactId>
</dependency>
<dependency>
<groupId>org.jolokia</groupId>
<artifactId>jolokia-core</artifactId>
</dependency>
</dependencies>
ArthasMbeanImpl
/**
* jmx实现 <br>
*
* @date: 2021/8/22 <br>
* @author: llxiao <br>
* @since: 1.0 <br>
* @version: 1.0 <br>
*/
@Component
@ManagedResource(objectName = "ArthasMbean:name=ArthasMbean", description = "Arthas远程管理Mbean")
@Slf4j
public class ArthasMbeanImpl {
private static final String ARTHAS_AGENT_BEAN_NAME = "arthasAgent";
private static final String ARTHAS_PREFIX = "arthas.";
@Autowired
private Map<String, String> arthasConfigMap;
@Autowired
private ArthasProperties arthasProperties;
@Autowired
private ApplicationContext applicationContext;
/**
* 初始化&启动arthas
*
* @return
*/
private ArthasAgent arthasAgentInit() {
arthasConfigMap = StringUtils.removeDashKey(arthasConfigMap);
// 给配置全加上前缀
Map<String, String> mapWithPrefix = new HashMap<>(arthasConfigMap.size());
for (Map.Entry<String, String> entry : arthasConfigMap.entrySet()) {
mapWithPrefix.put(ARTHAS_PREFIX + entry.getKey(), entry.getValue());
}
final ArthasAgent arthasAgent = new ArthasAgent(mapWithPrefix, arthasProperties.getHome(),
arthasProperties.isSlientInit(), null);
log.info("开始连接Arthas tunnel server,配置信息:{}", JSON.toJSONString(arthasProperties));
arthasAgent.init();
String errorMessage = arthasAgent.getErrorMessage();
log.info("连接Arthas tunnel server,返回结果:{}", errorMessage);
return arthasAgent;
}
@ManagedOperation(description = "获取Tunnel Server地址")
public String getArthasTunnelServerUrl() {
return arthasProperties.getTunnelServer();
}
@ManagedOperation(description = "重置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 = "获取Arthas配置")
public HashMap<String, String> getArthasConfigMap() {
return (HashMap) arthasConfigMap;
}
@ManagedOperation(description = "是否启动Arthas")
public Boolean isArthasAttched() {
DefaultListableBeanFactory defaultListableBeanFactory = (DefaultListableBeanFactory) applicationContext
.getAutowireCapableBeanFactory();
if (defaultListableBeanFactory.containsBean(ARTHAS_AGENT_BEAN_NAME)) {
return true;
}
return false;
}
@ManagedOperation(description = "启动Arthas")
public Boolean startArthasAgent() {
DefaultListableBeanFactory defaultListableBeanFactory = (DefaultListableBeanFactory) applicationContext
.getAutowireCapableBeanFactory();
if (defaultListableBeanFactory.containsBean(ARTHAS_AGENT_BEAN_NAME)) {
((ArthasAgent) defaultListableBeanFactory.getBean(ARTHAS_AGENT_BEAN_NAME)).init();
return true;
}
defaultListableBeanFactory.registerSingleton(ARTHAS_AGENT_BEAN_NAME, arthasAgentInit());
return true;
}
@ManagedOperation(description = "关闭Arthas(暂未实现)")
public Boolean stopArthasAgent() {
// TODO 无法获取自定义tmp文件夹加载的classLoader,因此无法获取到com.taobao.arthas.core.server.ArthasBootstrap类并调用destroy方法
// TODO 现有官方提供的com.taobao.arthas.agent.attach.ArthasAgent 中启动arthas agent的客户端使用的arthasClassLoader和bootstrapClass均为方法内的临时变量,外部无法获取相关句柄实现通过bootstrapClass关闭arthas agent的功能;
// TODO 临时解决方案为通过JMX启动后,在web console连接使用后,使用stop命令实现目标进程中 arthas agent的关闭
DefaultListableBeanFactory defaultListableBeanFactory = (DefaultListableBeanFactory) applicationContext
.getAutowireCapableBeanFactory();
if (defaultListableBeanFactory.containsBean(ARTHAS_AGENT_BEAN_NAME)) {
defaultListableBeanFactory.destroySingleton(ARTHAS_AGENT_BEAN_NAME);
return true;
} else {
return false;
}
}
}
ArthasConfiguration
import java.util.HashMap;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
/**
* @ClassName: arthas agent加载,需要扫描包,加载jmx的信息,通过jmx的方式启动arthas agent
* @Description: 线程池初始化
* @author: xiaolinlin
* @date: 2020/9/1 13:45
**/
@EnableConfigurationProperties({ArthasProperties.class})
@ComponentScan("com.xiaogj.arthas.spring")
public class ArthasConfiguration {
@ConfigurationProperties(prefix = "arthas")
@ConditionalOnMissingBean
@Bean
public HashMap<String, String> arthasConfigMap() {
return new HashMap<>();
}
}
SpringCloud服务使用
- 客户端改造后的引入
<dependency>
<groupId>com.xx.xxx</groupId>
<artifactId>xx-arthas-springboot-starter</artifactId>
<version>1.0.0-SNAPSHOT</version>
</dependency>
-
基于spring-actutor,需要开放对应的监控目录
application.yml
# 监控监控
management:
endpoints:
web:
exposure:
include: '*'
endpoint:
health:
show-details: ALWAYS
metrics:
tags:
application: ${spring.application.name}
- nacos配置
spring:
main:
## 解决 xxx.FeignClientSpecification异常
allow-bean-definition-overriding: true
application:
name: arthas-service-name
profiles:
active: ${SPRING_PROFILES:dev}
cloud:
nacos:
config:
file-extension: yml
# 读取公共配置文件
refreshable-dataids: arthas-commom.yml
shared-dataids: arthas-commom.yml
namespace: ${NACOS_NAMESPACE:you group}
username: ${NACOS_USERNAME:nacos}
password: ${NACOS_PASSWORD:nacos}
server-addr: ${NACOS_SERVER_ADDR:you naco url}
discovery:
namespace: ${NACOS_NAMESPACE:you group}
- arthas-commom.yml
arthas:
tunnel-server: ws://10.0.30.205:31817/ws
app-name: paymonitor
telnet-port: 3658
ip: 0.0.0.0
#agent-id: ${spring.application.name}@${random.value}
# 保证agentid 唯一,由于容器部署,我这里用应用名词+ip,类似取注册中心的服务和地址
agent-id: ${spring.application.name}@${spring.cloud.client.ip-address}
-
容器部署调整
我们是用K8S+容器部署,打包的时候调整了dockerfile文件,主要是:
开放jmx-Dspring.jmx.enabled=true
## 开放端口
EXPOSE 3658
ENTRYPOINT ["java","-Dspring.jmx.enabled=true","-jar","/app.jar"]
实战演示
- SBA控制台,找到刚刚集成的服务,进入到服务信息,要绿色的才能使用,红色的标识没有开放actutor相关权限
Springboot Admin(SBA) + Nacos + Arthas 搭建你的在线性能分析和问题定位工具-客户端改造篇核心改造说明arthas-springboot-starter改造SpringCloud服务使用实战演示以上服务端&客户端的整合完成,整体代码待后续开放… - 找到你集成的服务,点击进入详情,找到JVM,JAVA管理扩展
Springboot Admin(SBA) + Nacos + Arthas 搭建你的在线性能分析和问题定位工具-客户端改造篇核心改造说明arthas-springboot-starter改造SpringCloud服务使用实战演示以上服务端&客户端的整合完成,整体代码待后续开放… - 找到arthas客户端定义的mbean名称
Springboot Admin(SBA) + Nacos + Arthas 搭建你的在线性能分析和问题定位工具-客户端改造篇核心改造说明arthas-springboot-starter改造SpringCloud服务使用实战演示以上服务端&客户端的整合完成,整体代码待后续开放… - 点击进入,启动客户端的arthas
Springboot Admin(SBA) + Nacos + Arthas 搭建你的在线性能分析和问题定位工具-客户端改造篇核心改造说明arthas-springboot-starter改造SpringCloud服务使用实战演示以上服务端&客户端的整合完成,整体代码待后续开放… - 启动成功后,正常到sba- arthas console控制台刷新后会看到对应的arthas agentid
Springboot Admin(SBA) + Nacos + Arthas 搭建你的在线性能分析和问题定位工具-客户端改造篇核心改造说明arthas-springboot-starter改造SpringCloud服务使用实战演示以上服务端&客户端的整合完成,整体代码待后续开放… - 进入arthas控制台 这里一定要注意这个ip和port的配置,是arthas tunnel server的端口配置,不是sba服务应用的端口,否则会连接不上
Springboot Admin(SBA) + Nacos + Arthas 搭建你的在线性能分析和问题定位工具-客户端改造篇核心改造说明arthas-springboot-starter改造SpringCloud服务使用实战演示以上服务端&客户端的整合完成,整体代码待后续开放… - 选中刚刚注册上来的arthas 点击连接,即可进入arthas控制台,尽情享用 补充:
Springboot Admin(SBA) + Nacos + Arthas 搭建你的在线性能分析和问题定位工具-客户端改造篇核心改造说明arthas-springboot-starter改造SpringCloud服务使用实战演示以上服务端&客户端的整合完成,整体代码待后续开放…
- 刷新按钮可以动态刷新已注册上来的arthas agent.
- 想要停止服务,暂时只能在arthas控制台使用
命令停止
stop