一 点睛
在Spring Boot的众多Starter POMs中有一个特殊的模块,它不同于其他模块那样大多用于开发业务功能或是连接一些其他外部资源。
它完全是一个用于暴露自身信息的模块,所以很明显,它的主要作用是用于监控与管理,它就是:spring-boot-starter-actuator。
spring-boot-starter-actuator模块的实现对于实施微服务的中小团队来说,可以有效地减少监控系统在采集应用指标时的开发量。
当然,它也并不是万能的,有时候我们也需要对其做一些简单的扩展来帮助我们实现自身系统个性化的监控需求。
下面,我们将详解的介绍一些关于spring-boot-starter-actuator模块的内容,包括它的原生提供的端点以及一些常用的扩展和配置方式。
二 初识Actuator
1 新增依赖
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<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>
</dependencies>
2 启动程序,观察控制台输出,我们会发现,多了很多端点的定义,这些端点并非我们自己在程序中创建,而是由spring-boot-starter-actuator模块根据应用依赖和配置自动创建出来的监控和管理端点。通过这些端点,我们可以实时的获取应用的各项监控指标
2018-11-03 21:02:05.003 INFO 93344 --- [ main] s.w.s.m.m.a.RequestMappingHandlerMapping : Mapped "{[/hello]}" onto public java.lang.String com.didispace.web.HelloController.index()
2018-11-03 21:02:05.009 INFO 93344 --- [ main] s.w.s.m.m.a.RequestMappingHandlerMapping : Mapped "{[/error]}" onto public org.springframework.http.ResponseEntity<java.util.Map<java.lang.String, java.lang.Object>> org.springframework.boot.autoconfigure.web.BasicErrorController.error(javax.servlet.http.HttpServletRequest)
2018-11-03 21:02:05.010 INFO 93344 --- [ main] s.w.s.m.m.a.RequestMappingHandlerMapping : Mapped "{[/error],produces=[text/html]}" onto public org.springframework.web.servlet.ModelAndView org.springframework.boot.autoconfigure.web.BasicErrorController.errorHtml(javax.servlet.http.HttpServletRequest,javax.servlet.http.HttpServletResponse)
2018-11-03 21:02:05.063 INFO 93344 --- [ main] o.s.w.s.handler.SimpleUrlHandlerMapping : Mapped URL path [/webjars/**] onto handler of type [class org.springframework.web.servlet.resource.ResourceHttpRequestHandler]
2018-11-03 21:02:05.064 INFO 93344 --- [ main] o.s.w.s.handler.SimpleUrlHandlerMapping : Mapped URL path [/**] onto handler of type [class org.springframework.web.servlet.resource.ResourceHttpRequestHandler]
2018-11-03 21:02:05.167 INFO 93344 --- [ main] o.s.w.s.handler.SimpleUrlHandlerMapping : Mapped URL path [/**/favicon.ico] onto handler of type [class org.springframework.web.servlet.resource.ResourceHttpRequestHandler]
2018-11-03 21:02:05.689 INFO 93344 --- [ main] o.s.b.a.e.mvc.EndpointHandlerMapping : Mapped "{[/heapdump || /heapdump.json],methods=[GET],produces=[application/octet-stream]}" onto public void org.springframework.boot.actuate.endpoint.mvc.HeapdumpMvcEndpoint.invoke(boolean,javax.servlet.http.HttpServletRequest,javax.servlet.http.HttpServletResponse) throws java.io.IOException,javax.servlet.ServletException
2018-11-03 21:02:05.690 INFO 93344 --- [ main] o.s.b.a.e.mvc.EndpointHandlerMapping : Mapped "{[/trace || /trace.json],methods=[GET],produces=[application/vnd.spring-boot.actuator.v1+json || application/json]}" onto public java.lang.Object org.springframework.boot.actuate.endpoint.mvc.EndpointMvcAdapter.invoke()
2018-11-03 21:02:05.691 INFO 93344 --- [ main] o.s.b.a.e.mvc.EndpointHandlerMapping : Mapped "{[/metrics/{name:.*}],methods=[GET],produces=[application/vnd.spring-boot.actuator.v1+json || application/json]}" onto public java.lang.Object org.springframework.boot.actuate.endpoint.mvc.MetricsMvcEndpoint.value(java.lang.String)
2018-11-03 21:02:05.692 INFO 93344 --- [ main] o.s.b.a.e.mvc.EndpointHandlerMapping : Mapped "{[/metrics || /metrics.json],methods=[GET],produces=[application/vnd.spring-boot.actuator.v1+json || application/json]}" onto public java.lang.Object org.springframework.boot.actuate.endpoint.mvc.EndpointMvcAdapter.invoke()
2018-11-03 21:02:05.694 INFO 93344 --- [ main] o.s.b.a.e.mvc.EndpointHandlerMapping : Mapped "{[/configprops || /configprops.json],methods=[GET],produces=[application/vnd.spring-boot.actuator.v1+json || application/json]}" onto public java.lang.Object org.springframework.boot.actuate.endpoint.mvc.EndpointMvcAdapter.invoke()
2018-11-03 21:02:05.699 INFO 93344 --- [ main] o.s.b.a.e.mvc.EndpointHandlerMapping : Mapped "{[/health || /health.json],methods=[GET],produces=[application/vnd.spring-boot.actuator.v1+json || application/json]}" onto public java.lang.Object org.springframework.boot.actuate.endpoint.mvc.HealthMvcEndpoint.invoke(javax.servlet.http.HttpServletRequest,java.security.Principal)
2018-11-03 21:02:05.703 INFO 93344 --- [ main] o.s.b.a.e.mvc.EndpointHandlerMapping : Mapped "{[/env/{name:.*}],methods=[GET],produces=[application/vnd.spring-boot.actuator.v1+json || application/json]}" onto public java.lang.Object org.springframework.boot.actuate.endpoint.mvc.EnvironmentMvcEndpoint.value(java.lang.String)
2018-11-03 21:02:05.704 INFO 93344 --- [ main] o.s.b.a.e.mvc.EndpointHandlerMapping : Mapped "{[/env || /env.json],methods=[GET],produces=[application/vnd.spring-boot.actuator.v1+json || application/json]}" onto public java.lang.Object org.springframework.boot.actuate.endpoint.mvc.EndpointMvcAdapter.invoke()
2018-11-03 21:02:05.707 INFO 93344 --- [ main] o.s.b.a.e.mvc.EndpointHandlerMapping : Mapped "{[/dump || /dump.json],methods=[GET],produces=[application/vnd.spring-boot.actuator.v1+json || application/json]}" onto public java.lang.Object org.springframework.boot.actuate.endpoint.mvc.EndpointMvcAdapter.invoke()
2018-11-03 21:02:05.712 INFO 93344 --- [ main] o.s.b.a.e.mvc.EndpointHandlerMapping : Mapped "{[/autoconfig || /autoconfig.json],methods=[GET],produces=[application/vnd.spring-boot.actuator.v1+json || application/json]}" onto public java.lang.Object org.springframework.boot.actuate.endpoint.mvc.EndpointMvcAdapter.invoke()
2018-11-03 21:02:05.713 INFO 93344 --- [ main] o.s.b.a.e.mvc.EndpointHandlerMapping : Mapped "{[/info || /info.json],methods=[GET],produces=[application/vnd.spring-boot.actuator.v1+json || application/json]}" onto public java.lang.Object org.springframework.boot.actuate.endpoint.mvc.EndpointMvcAdapter.invoke()
2018-11-03 21:02:05.714 INFO 93344 --- [ main] o.s.b.a.e.mvc.EndpointHandlerMapping : Mapped "{[/mappings || /mappings.json],methods=[GET],produces=[application/vnd.spring-boot.actuator.v1+json || application/json]}" onto public java.lang.Object org.springframework.boot.actuate.endpoint.mvc.EndpointMvcAdapter.invoke()
2018-11-03 21:02:05.715 INFO 93344 --- [ main] o.s.b.a.e.mvc.EndpointHandlerMapping : Mapped "{[/beans || /beans.json],methods=[GET],produces=[application/vnd.spring-boot.actuator.v1+json || application/json]}" onto public java.lang.Object org.springframework.boot.actuate.endpoint.mvc.EndpointMvcAdapter.invoke()
2018-11-03 21:02:05.717 INFO 93344 --- [ main] o.s.b.a.e.mvc.EndpointHandlerMapping : Mapped "{[/loggers/{name:.*}],methods=[GET],produces=[application/vnd.spring-boot.actuator.v1+json || application/json]}" onto public java.lang.Object org.springframework.boot.actuate.endpoint.mvc.LoggersMvcEndpoint.get(java.lang.String)
2018-11-03 21:02:05.718 INFO 93344 --- [ main] o.s.b.a.e.mvc.EndpointHandlerMapping : Mapped "{[/loggers/{name:.*}],methods=[POST],consumes=[application/vnd.spring-boot.actuator.v1+json || application/json],produces=[application/vnd.spring-boot.actuator.v1+json || application/json]}" onto public java.lang.Object org.springframework.boot.actuate.endpoint.mvc.LoggersMvcEndpoint.set(java.lang.String,java.util.Map<java.lang.String, java.lang.String>)
2018-11-03 21:02:05.718 INFO 93344 --- [ main] o.s.b.a.e.mvc.EndpointHandlerMapping : Mapped "{[/loggers || /loggers.json],methods=[GET],produces=[application/vnd.spring-boot.actuator.v1+json || application/json]}" onto public java.lang.Object org.springframework.boot.actuate.endpoint.mvc.EndpointMvcAdapter.invoke()
2018-11-03 21:02:05.719 INFO 93344 --- [ main] o.s.b.a.e.mvc.EndpointHandlerMapping : Mapped "{[/auditevents || /auditevents.json],methods=[GET],produces=[application/vnd.spring-boot.actuator.v1+json || application/json]}" onto public org.springframework.http.ResponseEntity<?> org.springframework.boot.actuate.endpoint.mvc.AuditEventsMvcEndpoint.findByPrincipalAndAfterAndType(java.lang.String,java.util.Date,java.lang.String)
2018-11-03 21:02:05.865 INFO 93344 --- [ main] o.s.j.e.a.AnnotationMBeanExporter : Registering beans for JMX exposure on startup
2018-11-03 21:02:05.875 INFO 93344 --- [ main] o.s.c.support.DefaultLifecycleProcessor : Starting beans in phase 0
2018-11-03 21:02:06.124 INFO 93344 --- [ main] s.b.c.e.t.TomcatEmbeddedServletContainer : Tomcat started on port(s): 8080 (http)
2018-11-03 21:02:06.129 INFO 93344 --- [ main] com.didispace.Application : Started Application in 6.755 seconds (JVM running for 7.603)
3 访问/health端点,我们可以获得如下返回的应用健康信息:
{
"status": "UP"
}
三 原生端点
spring-boot-starter-actuator模块中已经实现的一些原生端点。如果根据端点的作用来说,我们可以原生端点分为三大类:
-
应用配置类:获取应用程序中加载的应用配置、环境变量、自动化配置报告等与Spring Boot应用密切相关的配置类信息。
-
度量指标类:获取应用程序运行过程中用于监控的度量指标,比如:内存信息、线程池信息、HTTP请求统计等。
-
操作控制类:提供了对应用的关闭等操作类功能。
四 应用配置类
1 介绍
由于Spring Boot为了改善传统Spring应用繁杂的配置内容,采用了包扫描和自动化配置的机制来加载原本集中于xml文件中的各项内容。
虽然这样的做法,让我们的代码变得非常简洁,但是整个应用的实例创建和依赖关系等信息都被离散到了各个配置类的注解上,这使得我们分析整个应用中资源和实例的各种关系变得非常的困难。
而这类端点就可以帮助我们轻松的获取一系列关于Spring 应用配置内容的详细报告,比如:自动化配置的报告、Bean创建的报告、环境属性的报告等。
2 自动化配置报告
/autoconfig:该端点用来获取应用的自动化配置报告,其中包括所有自动化配置的候选项。同时还列出了每个候选项自动化配置的各个先决条件是否满足。
所以,该端点可以帮助我们方便的找到一些自动化配置为什么没有生效的具体原因。
该报告内容将自动化配置内容分为两部分:
-
positiveMatches中返回的是条件匹配成功的自动化配置
-
negativeMatches中返回的是条件匹配不成功的自动化配置
要实现该功能,需要在application.properties中配置下面选项
management.security.enabled=false
访问/autoconfig端点,输出结果如下
{
"positiveMatches": { // 条件匹配成功的
"EndpointWebMvcAutoConfiguration": [
{
"condition": "OnClassCondition",
"message": "@ConditionalOnClass classes found: javax.servlet.Servlet,org.springframework.web.servlet.DispatcherServlet"
},
{
"condition": "OnWebApplicationCondition",
"message": "found web application StandardServletEnvironment"
}
],
...
},
"negativeMatches": { // 条件不匹配成功的
"HealthIndicatorAutoConfiguration.DataSourcesHealthIndicatorConfiguration": [
{
"condition": "OnClassCondition",
"message": "required @ConditionalOnClass classes not found: org.springframework.jdbc.core.JdbcTemplate"
}
],
...
}
}
从如上示例中我们可以看到,每个自动化配置候选项中都有一系列的条件,比如上面没有成功匹配的HealthIndicatorAutoConfiguration.DataSourcesHealthIndicatorConfiguration配置,它的先决条件就是需要在工程中包含org.springframework.jdbc.core.JdbcTemplate类,由于我们没有引入相关的依赖,它就不会执行自动化配置内容。所以,当我们发现有一些期望的配置没有生效时,就可以通过该端点来查看没有生效的具体原因。
3 Bean创建的报告
/beans:该端点用来获取应用上下文中创建的所有Bean。
访问/beans端点,输出结果如下
[
{
"context": "hello:dev:8881",
"parent": null,
"beans": [
{
"bean": "org.springframework.boot.autoconfigure.web.DispatcherServletAutoConfiguration$DispatcherServletConfiguration",
"scope": "singleton",
"type": "org.springframework.boot.autoconfigure.web.DispatcherServletAutoConfiguration$DispatcherServletConfiguration$$EnhancerBySpringCGLIB$$3440282b",
"resource": "null",
"dependencies": [
"serverProperties",
"spring.mvc.CONFIGURATION_PROPERTIES",
"multipartConfigElement"
]
},
{
"bean": "dispatcherServlet",
"scope": "singleton",
"type": "org.springframework.web.servlet.DispatcherServlet",
"resource": "class path resource [org/springframework/boot/autoconfigure/web/DispatcherServletAutoConfiguration$DispatcherServletConfiguration.class]",
"dependencies": []
}
]
}
]
如上示例中,我们可以看到在每个bean中都包含了下面这几个信息:
- bean:Bean的名称
- scope:Bean的作用域
- type:Bean的Java类型
- reource:class文件的具体路径
- dependencies:依赖的Bean名称
4 端点配置属性信息报告
/configprops:该端点用来获取应用中配置的属性信息报告。
在application.properties中配置下面内容:
management.security.enabled=false
从下面该端点返回示例的片段中,我们看到返回了关于该端点的配置信息:
prefix属性代表了属性的配置前缀
properties代表了各个属性的名称和值。
所以,我们可以通过该报告来看到各个属性的配置信息
访问/configprops端点,可得到下面配置信息,其中的enabled就是我们在application.properties中配置的
"managementServerProperties": {
"prefix": "management",
"properties": {
"security": {
"enabled": false,
"roles": [
"ACTUATOR"
],
"sessions": "STATELESS"
},
"address": null,
"port": null,
"addApplicationContextHeader": true,
"contextPath": "",
"ssl": null
}
},
5 环境属性报告
/env:该端点用来获取应用所有可用的环境属性报告。
包括:环境变量、JVM属性、应用的配置配置、命令行中的参数。
{
"profiles": [
"dev"
],
"server.ports": {
"local.server.port": 8881
},
"servletContextInitParams": {
},
"systemProperties": {
"idea.version": "2016.1.3",
"java.runtime.name": "Java(TM) SE Runtime Environment",
"sun.boot.library.path": "C:\\Program Files\\Java\\jdk1.8.0_91\\jre\\bin",
"java.vm.version": "25.91-b15",
"java.vm.vendor": "Oracle Corporation",
...
},
"systemEnvironment": {
"configsetroot": "C:\\WINDOWS\\ConfigSetRoot",
"RABBITMQ_BASE": "E:\\tools\\rabbitmq",
...
},
"applicationConfig: [classpath:/application-dev.properties]": {
"server.port": "8881"
},
"applicationConfig: [classpath:/application.properties]": {
"server.port": "8885",
"spring.profiles.active": "dev",
"info.app.name": "spring-boot-hello",
"info.app.version": "v1.0.0",
"spring.application.name": "hello"
}
}
从上面该端点返回的示例片段中,我们可以看到它不仅返回了应用的配置属性,还返回了系统属性、环境变量等丰富的配置信息,其中也包括了应用还没有使用的配置。所以它可以帮助我们方便地看到当前应用可以加载的配置信息,并配合@ConfigurationProperties注解将它们引入到我们的应用程序中来进行使用。
另外,为了配置属性的安全,对于一些类似密码等敏感信息,该端点都会进行隐私保护,但是我们需要让属性名中包含:password、secret、key这些关键词,这样该端点在返回它们的时候会使用*来替代实际的属性值。
6 控制器映射关系报告
/mappings:该端点用来返回所有Spring MVC的控制器映射关系报告。
从下面的示例片段中,我们可以看该报告的信息与我们在启用Spring MVC的Web应用时输出的日志信息类似,其中bean属性标识了该映射关系的请求处理器,method属性标识了该映射关系的具体处理类和处理函数。
{
"/webjars/**": {
"bean": "resourceHandlerMapping"
},
"/**": {
"bean": "resourceHandlerMapping"
},
"/**/favicon.ico": {
"bean": "faviconHandlerMapping"
},
"{[/hello]}": {
"bean": "requestMappingHandlerMapping",
"method": "public java.lang.String com.didispace.web.HelloController.index()"
},
"{[/mappings || /mappings.json],methods=[GET],produces=[application/json]}": {
"bean": "endpointHandlerMapping",
"method": "public java.lang.Object org.springframework.boot.actuate.endpoint.mvc.EndpointMvcAdapter.invoke()"
},
...
}
7 应用自定义的信息
/info:该端点用来返回一些应用自定义的信息。
默认情况下,该端点只会返回一个空的json内容。
我们可以在application.properties配置文件中通过info前缀来设置一些属性,比如下面这样:
info.app.name=spring-boot-hello
info.app.version=v1.0.0
再访问/info端点,我们可以得到下面的返回报告,其中就包含了上面我们在应用自定义的两个参数。
{
"app": {
"name": "spring-boot-hello",
"version": "v1.0.0"
}
}
五 度量指标类
上面我们所介绍的应用配置类端点所提供的信息报告在应用启动的时候都已经基本确定了其返回内容,可以说是一个静态报告。而度量指标类端点提供的报告内容则是动态变化的,这些端点提供了应用程序在运行过程中的一些快照信息,比如:内存使用情况、HTTP请求统计、外部资源指标等。这些端点对于我们构建微服务架构中的监控系统非常有帮助,由于Spring Boot应用自身实现了这些端点,所以我们可以很方便地利用它们来收集我们想要的信息,以制定出各种自动化策略。下面,我们就来分别看看这些强大的端点功能。
1 /metrics端点
该端点用来返回当前应用的各类重要度量指标,比如:内存信息、线程信息、垃圾回收信息等。
该端点返回信息如下:
{
"mem": 294491,
"mem.free": 129170,
"processors": 4,
"instance.uptime": 294273,
"uptime": 302459,
"systemload.average": -1,
"heap.committed": 245760,
"heap.init": 262144,
"heap.used": 116589,
"heap": 3708416,
"nonheap.committed": 49984,
"nonheap.init": 2496,
"nonheap.used": 48732,
"nonheap": 0,
"threads.peak": 25,
"threads.daemon": 21,
"threads.totalStarted": 28,
"threads": 23,
"classes": 5988,
"classes.loaded": 5988,
"classes.unloaded": 0,
"gc.ps_scavenge.count": 5,
"gc.ps_scavenge.time": 56,
"gc.ps_marksweep.count": 1,
"gc.ps_marksweep.time": 38,
"httpsessions.max": -1,
"httpsessions.active": 0,
"gauge.response.info": 173,
"gauge.response.hello": 5,
"counter.status.200.info": 1
"counter.status.200.hello": 11,
}
从上面的示例中,我们看到有这些重要的度量值:
-
系统信息:包括处理器数量processors、运行时间uptime和instance.uptime、系统平均负载systemload.average。
-
mem.*:内存概要信息,包括分配给应用的总内存数量以及当前空闲的内存数量。这些信息来自java.lang.Runtime。
-
heap.*:堆内存使用情况。这些信息来自java.lang.management.MemoryMXBean接口中getHeapMemoryUsage方法获取的java.lang.management.MemoryUsage。
-
nonheap.*:非堆内存使用情况。这些信息来自java.lang.management.MemoryMXBean接口中getNonHeapMemoryUsage方法获取的java.lang.management.MemoryUsage。
-
threads.*:线程使用情况,包括线程数、守护线程数(daemon)、线程峰值(peak)等,这些数据均来自java.lang.management.ThreadMXBean。
-
classes.*:应用加载和卸载的类统计。这些数据均来自java.lang.management.ClassLoadingMXBean。
-
gc.*:垃圾收集器的详细信息,包括垃圾回收次数gc.ps_scavenge.count、垃圾回收消耗时间gc.ps_scavenge.time、标记-清除算法的次数gc.ps_marksweep.count、标记-清除算法的消耗时间gc.ps_marksweep.time。这些数据均来自java.lang.management.GarbageCollectorMXBean。
-
httpsessions.*:Tomcat容器的会话使用情况。包括最大会话数httpsessions.max和活跃会话数httpsessions.active。该度量指标信息仅在引入了嵌入式Tomcat作为应用容器的时候才会提供。
-
gauge.*:HTTP请求的性能指标之一,它主要用来反映一个绝对数值。比如上面示例中的gauge.response.hello: 5,它表示上一次hello请求的延迟时间为5毫秒。
-
counter.*:HTTP请求的性能指标之一,它主要作为计数器来使用,记录了增加量和减少量。如上示例中counter.status.200.hello: 11,它代表了hello请求返回200状态的次数为11。
对于gauge.*和counter.*的统计,这里有一个特殊的内容请求star-star,它代表了对静态资源的访问。
这两类度量指标非常有用,我们不仅可以使用它默认的统计指标,还可以在程序中轻松的增加自定义统计值。
只需要通过注入org.springframework.boot.actuate.metrics.CounterService和org.springframework.boot.actuate.metrics.GaugeService来实现自定义的统计指标信息。
比如:我们可以像下面这样自定义实现对hello接口的访问次数统计。
package com.didispace.web;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.actuate.metrics.CounterService;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
@RestController
public class HelloController {
@Autowired
private CounterService counterService;
@RequestMapping("/hello1")
public String index() {
return "Hello World";
}
@RequestMapping("/hello")
public String greet() {
counterService.increment("didispace.hello.count");
return "";
}
}
我们访问localhost:8080/hello两次,访问不存在的localhost:8080/so两次,然后再访问/metrics端点,可以得到如下信息片段
{
"counter.status.200.metrics": 1,
"counter.status.404.star-star": 2,
"counter.didispace.hello.count": 2,
"counter.status.200.hello": 2
}
/metrics端点可以提供应用运行状态的完整度量指标报告,这项功能非常的实用,但是对于监控系统中的各项监控功能,它们的监控内容、数据收集频率都有所不同,如果我们每次都通过全量获取报告的方式来收集,略显粗暴。所以,我们还可以通过/metrics/{name}接口来更细粒度的获取度量信息,比如我们可以通过访问/metrics/mem.free来获取当前可用内存数量。
2 /health端点
它用来获取应用的各类健康指标信息。
在spring-boot-starter-actuator模块中自带实现了一些常用资源的健康指标检测器。这些检测器都通过HealthIndicator接口实现,并且会根据依赖关系的引入实现自动化装配,比如用于检测磁盘的DiskSpaceHealthIndicator、检测DataSource连接是否可用的DataSourceHealthIndicator等。
默认情况下,访问/health端点,返回结果如下:
{
"status": "UP",
"diskSpace": {
"status": "UP",
"total": 209715195904,
"free": 43650252800,
"threshold": 10485760
}
}
有时候,我们可能还会用到一些Spring Boot的Starter POMs中还没有封装的产品来进行开发。
比如:当使用RocketMQ作为消息代理时,由于没有自动化配置的检测器,所以我们需要自己来实现一个用来采集健康信息的检测器。
我们可以在Spring Boot的应用中,为org.springframework.boot.actuate.health.HealthIndicator接口实现一个对RocketMQ的检测器类:
@Component
public class RocketMQHealthIndicator implements HealthIndicator {
@Override
public Health health() {
int errorCode = check();
if (errorCode != 0) {
return Health.down().withDetail("Error Code", errorCode).build();
}
return Health.up().build();
}
private int check() {
return 0;
}
}
通过重写health()函数来实现健康检查,返回的Heath对象中,共有两项内容,一个是状态信息,除了该示例中的UP与DOWN之外,还有UNKNOWN和OUT_OF_SERVICE,可以根据需要来实现返回;还有一个详细信息,采用Map的方式存储,在这里通过withDetail函数,注入了一个Error Code信息,我们也可以填入一下其他信息,比如,检测对象的IP地址、端口等。
重新启动应用,并访问/health接口,我们在返回的JSON字符串中,将会包含了如下信息:
{
"status": "UP",
"rocketMQ": {
"status": "UP"
},
"diskSpace": {
"status": "UP",
"total": 209715195904,
"free": 43650244608,
"threshold": 10485760
}
}
3 /dump端点
该端点用来暴露程序运行中的线程信息。
它使用java.lang.management.ThreadMXBean的dumpAllThreads方法来返回所有含有同步信息的活动线程详情。
4 /trace端点
该端点用来返回基本的HTTP跟踪信息。
默认情况下,跟踪信息的存储采用org.springframework.boot.actuate.trace.InMemoryTraceRepository实现的内存方式,始终保留最近的100条请求记录。
它记录的内容格式如下:
[
{
"timestamp": 1541300642111,
"info": {
"method": "GET",
"path": "/dump",
"headers": {
"request": {
"content-type": "application/json",
"cache-control": "no-cache",
"postman-token": "0e1b73cf-b0a2-41a0-8975-7f54bf5bfb13",
"user-agent": "PostmanRuntime/7.3.0",
"accept": "*/*",
"host": "localhost:8080",
"accept-encoding": "gzip, deflate",
"connection": "keep-alive"
},
"response": {
"X-Application-Context": "application",
"Content-Type": "application/vnd.spring-boot.actuator.v1+json;charset=UTF-8",
"Transfer-Encoding": "chunked",
"Date": "Sun, 04 Nov 2018 03:04:02 GMT",
"status": "200"
}
},
"timeTaken": "64"
}
},
{
"timestamp": 1541300464745,
"info": {
"method": "GET",
"path": "/health",
"headers": {
"request": {
"content-type": "application/json",
"cache-control": "no-cache",
"postman-token": "143db673-3fc7-4c1f-b644-eaa40c79d4d5",
"user-agent": "PostmanRuntime/7.3.0",
"accept": "*/*",
"host": "localhost:8080",
"accept-encoding": "gzip, deflate",
"connection": "keep-alive"
},
"response": {
"X-Application-Context": "application",
"Content-Type": "application/vnd.spring-boot.actuator.v1+json;charset=UTF-8",
"Transfer-Encoding": "chunked",
"Date": "Sun, 04 Nov 2018 03:01:04 GMT",
"status": "200"
}
},
"timeTaken": "137"
}
}
]
六 参考
http://blog.didispace.com/spring-boot-actuator-1/