一、概述
指标监控应用
二、配置
Maven依赖
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.3.12.RELEASE</version>
<relativePath/>
</parent>
<groupId>com.example</groupId>
<artifactId>spring-cloud-actuator</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>spring-cloud-actuator</name>
<packaging>pom</packaging>
<description>spring-cloud-actuator</description>
<!-- 统一管理jar包版本 -->
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<maven.compiler.source>1.8</maven.compiler.source>
<maven.compiler.target>1.8</maven.compiler.target>
<junit.version>4.12</junit.version>
<log4j.version>1.2.17</log4j.version>
<lombok.version>1.16.18</lombok.version>
<mysql.version>5.1.47</mysql.version>
<druid.version>1.1.16</druid.version>
<mybatis.spring.boot.version>1.3.0</mybatis.spring.boot.version>
<spring-cloud.version>Hoxton.SR10</spring-cloud.version>
<spring-cloud-alibaba.version>2.2.5.RELEASE</spring-cloud-alibaba.version>
</properties>
<!-- 子模块继承之后,提供作用:锁定版本+子modlue不用写groupId和version -->
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-dependencies</artifactId>
<version>2.3.12.RELEASE</version>
<type>pom</type>
<scope>import</scope>
</dependency>
<!-- spring-cloud 依赖 -->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-dependencies</artifactId>
<version>${spring-cloud.version}</version>
<type>pom</type>
<scope>import</scope>
</dependency>
<!-- spring-cloud-alibaba 依赖 -->
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-alibaba-dependencies</artifactId>
<version>${spring-cloud-alibaba.version}</version>
<type>pom</type>
<scope>import</scope>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>${mysql.version}</version>
</dependency>
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid</artifactId>
<version>${druid.version}</version>
</dependency>
<dependency>
<groupId>org.mybatis.spring.boot</groupId>
<artifactId>mybatis-spring-boot-starter</artifactId>
<version>${mybatis.spring.boot.version}</version>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>${junit.version}</version>
</dependency>
<dependency>
<groupId>log4j</groupId>
<artifactId>log4j</artifactId>
<version>${log4j.version}</version>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>${lombok.version}</version>
<optional>true</optional>
</dependency>
</dependencies>
</dependencyManagement>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<configuration>
<!--<fork>true</fork>-->
<addResources>true</addResources>
</configuration>
</plugin>
</plugins>
</build>
</project>
子模块添加Actuator依赖
被监控的客户端
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>com.example</groupId>
<artifactId>spring-cloud-actuator</artifactId>
<version>0.0.1-SNAPSHOT</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<groupId>com.example</groupId>
<artifactId>spring-cloud-order</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>spring-cloud-order</name>
<description>spring-cloud-order</description>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<maven.compiler.source>1.8</maven.compiler.source>
<maven.compiler.target>1.8</maven.compiler.target>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
<!-- 集成 客户端 -->
<dependency>
<groupId>de.codecentric</groupId>
<artifactId>spring-boot-admin-starter-client</artifactId>
<version>2.3.1</version>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>
配置文件
在application.properties 中需要配置actuator的信息,如:
#监控服务端的地址
spring.boot.admin.client.url=http://${actuator-server-ip:port}
#使用IP进行注册,默认是false
#spring.boot.admin.client.instance.prefer-ip=true
###暴露所有的端点
management.endpoints.web.exposure.include=*
##是否启用endpoints监控,默认是true
#management.endpoints.enabled-by-default=true
##修改默认base-path
#management.endpoints.web.base-path= /hefan
management.info.env.enabled=true
#显示健康状态的详细指标
management.endpoint.health.show-details=always
#用于查看远程日志文件,必须把日志文件存储在文件中
logging.file.path=C:\hefan.log
#优化的关闭应用服务
#management.endpoint.shutdown.enabled=true
#需要设置web服务器的关闭方式(默认是立即关闭,需要改成优雅关闭)
server.shutdown=graceful
这里将actuator的所有endpoints都开放出来了,这是一种很危险的配置,但是,开放出来的理由有
- 如果是内网环境,可以开放出来,但不要开放到外网环境;
- 如果使用了Spring Security,可以根据用户权限配置,需要将所有endpoints开放出来;
- 如果想简单使用filter对endpoints做控制,可以全部开放出来,本篇就是使用filter对actuator/*做简单的控制,actuator.filter.switch的配置就是为了对filter做开关。
三、Actuator的使用
Actuator开放的端点
Actuator只需要加载依赖和配置即可使用,启动时候会提示你Actuator暴漏了哪些接口,如:
...WebMvcEndpointHandlerMapping] Mapped "{[/actuator/super],methods=[POST],consumes=[application/vnd.spring-boot.actuator.v2+json || application/json],produces=[application/vnd.spring-boot.actuator.v2+json || application/json]}"
...WebMvcEndpointHandlerMapping] Mapped "{[/actuator/super],methods=[GET],produces=[application/vnd.spring-boot.actuator.v2+json || application/json]}"
...WebMvcEndpointHandlerMapping] Mapped "{[/actuator/super/{arg0}],methods=[GET],produces=[application/vnd.spring-boot.actuator.v2+json || application/json]}"
...WebMvcEndpointHandlerMapping] Mapped "{[/actuator/auditevents],methods=[GET],produces=[application/vnd.spring-boot.actuator.v2+json || application/json]}"
...WebMvcEndpointHandlerMapping] Mapped "{[/actuator/beans],methods=[GET],produces=[application/vnd.spring-boot.actuator.v2+json || application/json]}"
...WebMvcEndpointHandlerMapping] Mapped "{[/actuator/health],methods=[GET],produces=[application/vnd.spring-boot.actuator.v2+json || application/json]}"
...WebMvcEndpointHandlerMapping] Mapped "{[/actuator/conditions],methods=[GET],produces=[application/vnd.spring-boot.actuator.v2+json || application/json]}"
...WebMvcEndpointHandlerMapping] Mapped "{[/actuator/configprops],methods=[GET],produces=[application/vnd.spring-boot.actuator.v2+json || application/json]}"
...WebMvcEndpointHandlerMapping] Mapped "{[/actuator/env],methods=[GET],produces=[application/vnd.spring-boot.actuator.v2+json || application/json]}"
...WebMvcEndpointHandlerMapping] Mapped "{[/actuator/env/{toMatch}],methods=[GET],produces=[application/vnd.spring-boot.actuator.v2+json || application/json]}"
...WebMvcEndpointHandlerMapping] Mapped "{[/actuator/info],methods=[GET],produces=[application/vnd.spring-boot.actuator.v2+json || application/json]}"
...WebMvcEndpointHandlerMapping] Mapped "{[/actuator/logfile],methods=[GET],produces=[application/octet-stream]}"
...WebMvcEndpointHandlerMapping] Mapped "{[/actuator/loggers],methods=[GET],produces=[application/vnd.spring-boot.actuator.v2+json || application/json]}"
...WebMvcEndpointHandlerMapping] Mapped "{[/actuator/loggers/{name}],methods=[POST],consumes=[application/vnd.spring-boot.actuator.v2+json || application/json]}"
...WebMvcEndpointHandlerMapping] Mapped "{[/actuator/loggers/{name}],methods=[GET],produces=[application/vnd.spring-boot.actuator.v2+json || application/json]}"
...WebMvcEndpointHandlerMapping] Mapped "{[/actuator/heapdump],methods=[GET],produces=[application/octet-stream]}"
...WebMvcEndpointHandlerMapping] Mapped "{[/actuator/threaddump],methods=[GET],produces=[application/vnd.spring-boot.actuator.v2+json || application/json]}"
...WebMvcEndpointHandlerMapping] Mapped "{[/actuator/metrics],methods=[GET],produces=[application/vnd.spring-boot.actuator.v2+json || application/json]}"
...WebMvcEndpointHandlerMapping] Mapped "{[/actuator/metrics/{requiredMetricName}],methods=[GET],produces=[application/vnd.spring-boot.actuator.v2+json || application/json]}"
...WebMvcEndpointHandlerMapping] Mapped "{[/actuator/scheduledtasks],methods=[GET],produces=[application/vnd.spring-boot.actuator.v2+json || application/json]}"
...WebMvcEndpointHandlerMapping] Mapped "{[/actuator/httptrace],methods=[GET],produces=[application/vnd.spring-boot.actuator.v2+json || application/json]}"
...WebMvcEndpointHandlerMapping] Mapped "{[/actuator/mappings],methods=[GET],produces=[application/vnd.spring-boot.actuator.v2+json || application/json]}"
...WebMvcEndpointHandlerMapping] Mapped "{[/actuator],methods=[GET],produces=[application/vnd.spring-boot.actuator.v2+json || application/json]}"
这里面的/actuator/super是我自定义的,下面会说明,其他的都是actuator自己的endpoint。
大致有这些:
其中:默认打开的端点只有health健康检查和info应用基本信息。
如何打开所有端点:management.endpoints.web.exposure.include=*
Actuator路径
Actuator开放的端口都可以直接访问的,根据提示的get/post请求即可: - get请求返回的都是json,有的可以带路径筛选; - post请求是json数据。返回也是json。
下面请求下127.0.0.1:8080/actuator:
{
"_links": {
"self": {
"href": "http://localhost:8085/actuator",
"templated": false
},
"beans": {
"href": "http://localhost:8085/actuator/beans",
"templated": false
},
"caches-cache": {
"href": "http://localhost:8085/actuator/caches/{cache}",
"templated": true
},
"caches": {
"href": "http://localhost:8085/actuator/caches",
"templated": false
},
"health": {
"href": "http://localhost:8085/actuator/health",
"templated": false
},
"health-path": {
"href": "http://localhost:8085/actuator/health/{*path}",
"templated": true
},
"info": {
"href": "http://localhost:8085/actuator/info",
"templated": false
},
"conditions": {
"href": "http://localhost:8085/actuator/conditions",
"templated": false
},
"configprops": {
"href": "http://localhost:8085/actuator/configprops",
"templated": false
},
"env": {
"href": "http://localhost:8085/actuator/env",
"templated": false
},
"env-toMatch": {
"href": "http://localhost:8085/actuator/env/{toMatch}",
"templated": true
},
"loggers": {
"href": "http://localhost:8085/actuator/loggers",
"templated": false
},
"loggers-name": {
"href": "http://localhost:8085/actuator/loggers/{name}",
"templated": true
},
"heapdump": {
"href": "http://localhost:8085/actuator/heapdump",
"templated": false
},
"threaddump": {
"href": "http://localhost:8085/actuator/threaddump",
"templated": false
},
"metrics-requiredMetricName": {
"href": "http://localhost:8085/actuator/metrics/{requiredMetricName}",
"templated": true
},
"metrics": {
"href": "http://localhost:8085/actuator/metrics",
"templated": false
},
"scheduledtasks": {
"href": "http://localhost:8085/actuator/scheduledtasks",
"templated": false
},
"mappings": {
"href": "http://localhost:8085/actuator/mappings",
"templated": false
}
}
}
重点:actuator 对应后面的一级如health就是所谓的断点。
health :应用健康信息,指标是看项目集成了哪些框架的,如监控数据库连接,监控磁盘,监控redis,如一个指标为false,则整体健康检查状态为down
info:应用基本信息,我们自己定制的指标,自己扩展用的
beans:注入的bean信息
caches:缓存信息
conditions:自动配置类信息
configprops:配置类当中的信息
env:环境变量
loggers:日志界别相关,可以切换日志级别
heapdump:分析jvm内存信息
threaddump:线程的信息
metrics:各种指标信息,线程、内存、连接等等,可以查看。
scheduledtasks:任务调度
mappings:映射信息,请求的映射接口都在这里
Spring Boot Admin
Spring Boot Admin 是一个监控工具,旨在以一种美观且易于访问的方式可视化 Spring Boot Actuator 提供的信息。它主要由两大部分组成:
- 服务器:提供一个用户界面来展示和与 Spring Boot Actuator 进行交互。
- 客户端:用于在服务器上注册,并允许访问 Actuator 端点。
Spring Boot Admin(简称 SBA)由两部分组成:SBA Server 和 SBA Client
SBA Server: 包括 Admin 用户界面并独立运行于被监控应用
SBA Client: 提供一种方式将被监控应用注册到 SBA Server
SBA 分为服务端和客户端原理:因为 SBA 需要做集中化的监控(比如应用的集群,多个服务或者微服务等),而不是每个应用都需要有一个 UI。同时被监控的应用应该是和监控平台是分离的,并且需要考虑其他语言和其他平台的集成
除此之外,SBA Client 不仅只可以注册到 SBA Server ,还可以注册到 Spring Cloud Discovery(微服务),Python Applications Using Pyctuator(其他语言)等平台
配置服务器
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>com.example</groupId>
<artifactId>spring-cloud-actuator</artifactId>
<version>0.0.1-SNAPSHOT</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<groupId>com.example</groupId>
<artifactId>spring-cloud-server</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>spring-cloud-server</name>
<description>spring-cloud-server</description>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<maven.compiler.source>1.8</maven.compiler.source>
<maven.compiler.target>1.8</maven.compiler.target>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>de.codecentric</groupId>
<artifactId>spring-boot-admin-starter-server</artifactId>
<version>2.3.1</version>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>
添加配置
spring.application.name=spring-cloud-server
server.port=8086
通过 @EnableAdminServer 注解启用 SBA Server,自动下载
@SpringBootApplication
@EnableAdminServer
public class SpringCloudServerApplication {
public static void main(String[] args) {
SpringApplication.run(SpringCloudServerApplication.class, args);
}
}
实例不同颜色不同状态
绿色:表示实例监控
灰色:表示监控server连接client获取健康信息超时(默认超过10秒就是灰色)
红色:能看到具体错误信息
安全防护
Maven依赖
<!-- 安全控制 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-security</artifactId>
</dependency>
添加防护配置类
参考官网地址:docs.spring-boot-admin.com/current/sec…
放开所有端点控制权限
package com.example.springcloudserver.config;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
@Configuration
public class SecurityPermitAllConfig extends WebSecurityConfigurerAdapter {
/**
* http 请求处理方法
* @param http
* @throws Exception
*/
@Override
protected void configure(HttpSecurity http) throws Exception {
http.authorizeRequests().anyRequest().permitAll().and().cors().disable();
}
}
添加控制
这个配置类如何来控制可以自行修改
package com.example.springcloudserver.config;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.env.Environment;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.util.StringUtils;
@Configuration
@EnableWebSecurity
public class ActuatorSecurityConfig extends WebSecurityConfigurerAdapter {
@Autowired
Environment env;
@Override
protected void configure(HttpSecurity security) throws Exception {
String contextPath = env.getProperty("management.endpoints.web.base-path");
if(StringUtils.isEmpty(contextPath)) {
contextPath = "";
}
security.csrf().disable();
security.authorizeRequests()
.antMatchers("/**"+contextPath+"/**")
.authenticated()
.anyRequest()
.permitAll()
.and()
.httpBasic();
}
}
配置账号密码
#配置监控账号密码
#服务端账号密码
spring.security.user.name= admin
spring.security.user.password=123456
#客户端也需要账号密码,不设置,服务端监控不到
spring.boot.admin.client.username= admin
spring.boot.admin.client.password= 123456
通过注册中心集成客户端
服务端配置
Maven依赖
服务端配置
<!-- 注册中心配置-->
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-nacos-config</artifactId>
</dependency>
<!-- 添加服务发现依赖-->
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
</dependency>
添加配置
服务端配置
#添加注册中心
spring.cloud.nacos.server-addr=127.0.0.1:8848
spring.cloud.nacos.discovery.username=nacos
spring.cloud.nacos.discovery.password=nacos
客户端配置
Maven依赖
<!-- 注册中心配置-->
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-nacos-config</artifactId>
</dependency>
<!-- 添加服务发现依赖-->
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
</dependency>
添加配置
server:
port: 8085
spring:
application:
name: spring-cloud-order
cloud:
nacos:
discovery:
server-addr: 127.0.0.1:8848
config:
server-addr: 127.0.0.1:8848
group: DEFAULT_GROUP
namespace: public
启动服务
客户端控制台疯狂输出日志,标识检测成功
#指定服务端监控地址
spring.boot.admin.client.url..., type=properties
2024-08-18 20:22:29.090 INFO 9900 --- [0.1_8848-public] c.a.n.client.config.impl.ClientWorker : [fixed-127.0.0.1_8848-public] [polling-resp] config changed. dataId=spring-cloud-order.properties, group=DEFAULT_GROUP, tenant=public
2024-08-18 20:22:29.090 INFO 9900 --- [0.1_8848-public] c.a.n.client.config.impl.ClientWorker : get changedGroupKeys:[spring-cloud-order.properties+DEFAULT_GROUP+public]
2024-08-18 20:22:29.092 INFO 9900 --- [0.1_8848-public] c.a.n.client.config.impl.ClientWorker : [fixed-127.0.0.1_8848-public] [data-received] dataId=spring-cloud-order.properties, group=DEFAULT_GROUP, tenant=public, md5=b30660b12a05d1b0e5d93c5c7977cac3, content=#需要设置web服务器的关闭方式(默认是立即关闭,需要改成优雅关闭)
server.shutdown=graceful
集成邮件通知
admin集成POM依赖
<!-- 集成邮箱 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-mail</artifactId>
</dependency>
配置文件
#邮件通知
spring.mail.host= 服务地址
spring.mail.username= 账号
spring.mail.password= 授权码
spring.boot.admin.notify.mail.to= 接收人
spring.boot.admin.notify.mail.from= 发件人
启动即可
定制
定制health端点
实现抽象类,其中的doHealthCheck是检查端点是否健康的方法,在这里可以实现自定义。
@Component
public class CustomHealthIndicator extends AbstractHealthIndicator {
@Override
protected void doHealthCheck(Health.Builder builder) throws Exception {
boolean res = check();
if (res) {
builder.up();
} else {
builder.down();
}
}
private boolean check() {
return true;
}
}
访问 localhost:8080/actuator/health 效果如下:
自定义info端点
默认的info端点没有任何信息。
方式一:通过yml配置文件的方式实现
info:
app-name: test
version: 3.0.0
mavenversion: @project.artifactId@ # @@可以获取pom配置文件的属性值
效果:localhost:8080/actuator/info‘
方式二:编写代码的方式实现
@Component
public class CustomInfo implements InfoContributor {
@Override
public void contribute(Info.Builder builder) {
builder.withDetail("k1", "v1")
.withDetail("hello", "world")
.withDetails(Collections.singletonMap("kkk", "vvv"));
}
}
效果
配置文件和编写代码的方式可以同时使用,最终会汇集所有的信息。
自定义metrics端点
默认的metrics端点提供了jvm、数据库连接信息、cpu、进程相关的一些信息。
counter ****counter ****立即升级
计数器,一个简单的Meter,可以用来记录请求次数、支付订单次数等增长类的统计。
//定制metrics counter指标
Metrics.counter("count","tags").increment();
查看metrics端点,发现自定义的counter指标也出现了。
访问接口counter会增加,实现计数器的效果。
查看指标的具体数据,在http://localhost:8080/actuator/metrics/ 后面跟上对应的指标即可。
Timer
定时器指标,用来记录一些代码执行的时间计算。
Guage
一般用来记录有浮动值的数据,例如积压的消息,任务,集合、数组等等。
Summary
可以记录命中率的一些doble值。
自定义Endpoint
官网描述戳这里:Spring Boot Actuator: Production-ready Features
@Component
@Endpoint(id = "wjPoint")
public class CustomPoint {
Map<String,Object> map = new HashMap();
{
Map<String,String> m1 = new HashMap<>();
m1.put("k1","v1");
m1.put("k2","v2");
Map<String,String> m2 = new HashMap<>();
m2.put("k3","v3");
m2.put("k4","v4");
map.put("m1",m1);
map.put("m2",m2);
}
@ReadOperation
public Map getOperation(){
return map;
}
}
其他线控
1.JConsole jvm自带,使用控制台命令 JConsole打开即可。
2.jvisualvm jvm自带,使用控制台命令 jvisualvm 打开即可,可以使用该工具导入dump文件,分析哪些对象占用堆是最大的。当服务器出现OOM就可以使用这个分析。