pom.xml
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
ActuatorApplication
package com.example.actuator;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
@SpringBootApplication
public class ActuatorApplication {
public static void main(String[] args) {
SpringApplication.run(ActuatorApplication.class, args);
}
}
application.properties
server.port=8080
# 配置项目访问路径,配置后若访问actuator,需 /demo/acturator
#server.servlet.context-path=/demo
# 配置后,http://localhost:8080/actuator -> http://localhost:8080/manage 访问
#management.endpoints.web.base-path=/manage
# 自定义管理服务器端口
#management.server.port=8081
# 当配置为使用自定义端口时,还可以使用各种management.server.ssl.*属性为管理服务器配置自己的 SSL
#server.ssl.enabled=true
#server.ssl.key-store=classpath:store.jks
#server.ssl.key-password=secret
#management.server.ssl.enabled=false
# 默认所有配置改为可用
management.endpoints.enabled-by-default=true
# 开启某个的访问
management.endpoint.beans.enabled=true
# http://localhost:8080/actuator/health 显示详情
# com.example.actuator.config.CustomHealthIndicator 可自定义监控指标,并可进行监控
management.endpoint.health.show-details=always
# 开启web的访问
management.endpoints.web.exposure.include=*
# 配置跨域
management.endpoints.web.cors.allowed-origins=http://localhost:8080
management.endpoints.web.cors.allowed-methods=GET,POST
# 自定义应用信息,http://localhost:8080/actuator/info
info.app.name=MyService
info.app.description=My awesome service
info.app.version=1.0.0
# 数据信息从maven获取
info.build.artifact=@project.artifactId@
info.build.name=@project.name@
info.build.description=@project.description@
info.build.version=@project.version@
CustomHealthIndicator
package com.example.actuator.config;
import org.springframework.boot.actuate.health.AbstractHealthIndicator;
import org.springframework.boot.actuate.health.Health;
import org.springframework.stereotype.Component;
/**
* 自定义的健康指标 : http://localhost:8080/actuator/health 访问时即可看到
* 类名 : xxHealthIndicator -> xx即为健康指标的名称
*/
@Component
public class CustomHealthIndicator extends AbstractHealthIndicator {
@Override
protected void doHealthCheck(Health.Builder builder) throws Exception {
if (true) {
builder.up()
.withDetail("app", "Alive and Kicking")
.withDetail("error", "Nothing! I'm good.");
} else {
builder.down()
.withDetail("app", "Not Alive");
}
}
}
Custom2HealthIndicator
package com.example.actuator.config;
import org.springframework.boot.actuate.health.Health;
import org.springframework.boot.actuate.health.HealthIndicator;
import org.springframework.stereotype.Component;
/**
* 自定义的健康指标 : http://localhost:8080/actuator/health 访问时即可看到
* 类名 : xxHealthIndicator -> xx即为健康指标的名称
*/
@Component
public class Custom2HealthIndicator implements HealthIndicator {
@Override
public Health health() {
int errorCode = 0; // perform some specific health check
if (errorCode != 0) {
return Health.down().withDetail("Error Code", errorCode).build();
}
return Health.up().build();
}
}
CustomEndpoint
package com.example.actuator.config;
import org.springframework.boot.actuate.endpoint.annotation.Endpoint;
import org.springframework.boot.actuate.endpoint.annotation.ReadOperation;
import org.springframework.boot.actuate.endpoint.annotation.Selector;
import org.springframework.context.annotation.Configuration;
import java.lang.management.ManagementFactory;
import java.lang.management.MemoryMXBean;
import java.lang.management.MemoryUsage;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
/**
* 自定义全新端点
* @EndPoint中的id不能使用驼峰法,需要以-分割
* @Spring Boot会去扫描@EndPoint注解下的@ReadOperation, @WriteOperation, @DeleteOperation注解,分别对应生成Get/Post/Delete的Mapping。注解中有个produces参数,可以指定media type, 如:application/json等
*
* 访问地址:
* http://localhost:8080/actuator/custom-endpoint
* http://localhost:8080/actuator/custom-endpoint/{unitType}
*
*/
@Endpoint(id = "custom-endpoint")
@Configuration
public class CustomEndpoint {
/**
* 计算单位换算类型
*/
private static final Map<String, Long> UNIT_TYPE = new HashMap<>();
static {
UNIT_TYPE.put("K", 1024L);
UNIT_TYPE.put("M", 1024 * 1024L);
UNIT_TYPE.put("G", 1024 * 1024 * 1024L);
}
@ReadOperation
public Map<String, Object> endpoint() {
Map<String, Object> map = new HashMap<>();
MemoryMXBean memorymbean = ManagementFactory.getMemoryMXBean();
map.put("堆内存", memorymbean.getHeapMemoryUsage());
map.put("方法区内存", memorymbean.getNonHeapMemoryUsage());
List<String> inputArgs = ManagementFactory.getRuntimeMXBean().getInputArguments();
map.put("运行时设置的JVM参数", inputArgs);
// 总的内存量
long totle = Runtime.getRuntime().totalMemory();
// 空闲的内存量
long free = Runtime.getRuntime().freeMemory();
// 最大的内存量
long max = Runtime.getRuntime().maxMemory();
Map<String, Long> params = new HashMap<>();
params.put("totalMemory", totle);
params.put("freeMemory", free);
params.put("maxMemory", max);
map.put("运行时内存情况", params);
return map;
}
/**
* @Selector 会将路径上的参数作为变量传递给操作方法
* init约等于xms的值,max约等于xmx的值。used是已经被使用的内存大小,committed是当前可使用的内存大小(包括已使用的),committed >= used。committed不足时jvm向系统申请,若超过max则发生OutOfMemoryError错误
*/
@ReadOperation
public Map<String, Object> select(@Selector String unitType) {
long conversion = UNIT_TYPE.getOrDefault(unitType.toUpperCase(), 1L);
Map<String, Object> map = new HashMap<>();
// 堆内存
MemoryMXBean memorymbean = ManagementFactory.getMemoryMXBean();
// 方法区内存
MemoryUsage heapMemoryUsage = memorymbean.getHeapMemoryUsage();
long heapInit = heapMemoryUsage.getInit() / conversion;
long heapCommitted = heapMemoryUsage.getCommitted() / conversion;
long heapUsed = heapMemoryUsage.getUsed() / conversion;
long heapMax = heapMemoryUsage.getMax() / conversion;
Map<String, Long> heapMap = new HashMap<>();
heapMap.put("init", heapInit);
heapMap.put("committed", heapCommitted);
heapMap.put("used", heapUsed);
heapMap.put("max", heapMax);
map.put("堆内存", heapMap);
MemoryUsage nonHeapMemoryUsage = memorymbean.getNonHeapMemoryUsage();
long noHeapInit = nonHeapMemoryUsage.getInit() / conversion;
long noHeapCommitted = nonHeapMemoryUsage.getCommitted() / conversion;
long noHeapUsed = nonHeapMemoryUsage.getUsed() / conversion;
long noHeapMax = nonHeapMemoryUsage.getMax() / conversion;
Map<String, Long> noHeapMap = new HashMap<>();
noHeapMap.put("init", noHeapInit);
noHeapMap.put("committed", noHeapCommitted);
noHeapMap.put("used", noHeapUsed);
noHeapMap.put("max", noHeapMax);
map.put("方法区内存", noHeapMap);
List<String> inputArgs = ManagementFactory.getRuntimeMXBean().getInputArguments();
map.put("运行时设置的JVM参数", inputArgs);
// 总的内存量
long totle = Runtime.getRuntime().totalMemory();
// 空闲的内存量
long free = Runtime.getRuntime().freeMemory();
// 最大的内存量
long max = Runtime.getRuntime().maxMemory();
Map<String, Long> params = new HashMap<>();
params.put("totalMemory", totle / conversion);
params.put("freeMemory", free / conversion);
params.put("maxMemory", max / conversion);
map.put("运行时内存情况", params);
return map;
}
}