Spring Boot Actuator 提供了 一些接口,向外部提供本应用程序的监控信息。
接口分为三大类:
使用Spring Boot Actuator需要引入jar包
org.springframework.boot
spring-boot-starter-actuator
启动项目会看到一些映射
2018-11-16 10:09:27.968 INFO [main]org.springframework.boot.actuate.endpoint.mvc.EndpointHandlerMapping.register:543 -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-16 10:09:27.968 INFO [main]org.springframework.boot.actuate.endpoint.mvc.EndpointHandlerMapping.register:543 -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-16 10:09:27.968 INFO [main]org.springframework.boot.actuate.endpoint.mvc.EndpointHandlerMapping.register:543 -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-16 10:09:27.968 INFO [main]org.springframework.boot.actuate.endpoint.mvc.EndpointHandlerMapping.register:543 -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-16 10:09:27.968 INFO [main]org.springframework.boot.actuate.endpoint.mvc.EndpointHandlerMapping.register:543 -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-16 10:09:27.968 INFO [main]org.springframework.boot.actuate.endpoint.mvc.EndpointHandlerMapping.register:543 -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-16 10:09:27.968 INFO [main]org.springframework.boot.actuate.endpoint.mvc.EndpointHandlerMapping.register:543 -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)
2018-11-16 10:09:27.968 INFO [main]org.springframework.boot.actuate.endpoint.mvc.EndpointHandlerMapping.register:543 -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-16 10:09:27.968 INFO [main]org.springframework.boot.actuate.endpoint.mvc.EndpointHandlerMapping.register:543 -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-16 10:09:27.968 INFO [main]org.springframework.boot.actuate.endpoint.mvc.EndpointHandlerMapping.register:543 -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-16 10:09:27.968 INFO [main]org.springframework.boot.actuate.endpoint.mvc.EndpointHandlerMapping.register:543 -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-16 10:09:27.983 INFO [main]org.springframework.boot.actuate.endpoint.mvc.EndpointHandlerMapping.register:543 -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-16 10:09:27.983 INFO [main]org.springframework.boot.actuate.endpoint.mvc.EndpointHandlerMapping.register:543 -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-16 10:09:27.983 INFO [main]org.springframework.boot.actuate.endpoint.mvc.EndpointHandlerMapping.register:543 -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-16 10:09:27.983 INFO [main]org.springframework.boot.actuate.endpoint.mvc.EndpointHandlerMapping.register:543 -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-16 10:09:27.983 INFO [main]org.springframework.boot.actuate.endpoint.mvc.EndpointHandlerMapping.register:543 -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-16 10:09:27.983 INFO [main]org.springframework.boot.actuate.endpoint.mvc.EndpointHandlerMapping.register:543 -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-16 10:09:28.399 INFO [main]org.springframework.jmx.export.annotation.AnnotationMBeanExporter.afterSingletonsInstantiated:431 -Registering beans for JMX exposure on startup
访问这些接口就能获取到各项监控指标
HTTP 方法 | 路径 | 描述 |
---|---|---|
应用配置类 |
||
GET | /autoconfig | 该端点用来获取应用的自动化配置报告,其中包括所有自动化配置的候选项。同时还列出了每个候选项自动化配置的各个先决条件是否满足。所以,该端点可以帮助我们方便的找到一些自动化配置为什么没有生效的具体原因。该报告内容将自动化配置内容分为两部分:
|
GET | /configprops | 描述配置属性(包含默认值)
|
GET | /beans | 描述应用程序上下文里全部的Bean,以及它们的关系
|
GET | /env | 获取应用所有可用的环境属性报告。包括:环境变量、JVM属性、应用的配置配置、命令行中的参数 |
GET | /env/{name} | 根据名称获取特定的环境属性值 /env 接口还能用来获取单个属性的值,只需要在请求时在 /env 后加上属性名即可。 |
GET | /info | 该端点用来返回一些应用自定义的信息。默认情况下,该端点只会返回一个空的json内容。 我们可以在 |
GET | /mappings | 描述全部的URI路径,以及它们和控制器(包含Actuator端点)的映射关系 罗列出应用程序发布的全部接口
|
度量指标类(提供的报告内容则是动态变化的) |
||
GET | /metrics | 报告各种应用程序度量信息,比如内存用量、HTTP请求计数、线程信息、垃圾回收信息等。
对于 |
GET | /metrics/{name} | 报告指定名称的应用程序度量值 |
GET | /health | 报告应用程序的健康指标,这些值由HealthIndicator的实现类提供 |
GET | /dump | 获取线程活动的快照。它使用java.lang.management.ThreadMXBean 的dumpAllThreads 方法来返回所有含有同步信息的活动线程详情。 |
GET | /trace | 提供基本的HTTP请求跟踪信息(时间戳、HTTP头等)。 默认情况下,跟踪信息的存储采用 |
操作控制类(操作控制类接口默认是关闭的,如果要使用它们的话,需要通过属性来配置开启。) |
||
POST | /shutdown | 关闭应用程序,要求endpoints.shutdown.enabled设置为true |
但是在实际操作的时候报错,访问/beans告诉我没权限,spring boot 1.5.8
解决办法开启HTTP basic认证
添加依赖
org.springframework.boot
spring-boot-starter-security
application.yml 添加用户名和密码
security:
user:
name: admin #鉴权账号
password: 123456 #鉴权密码
basic:
enabled: true
path: /admin 鉴权路径
management:
port: 8089 #actuator暴露接口使用的端口,为了和api接口使用的端口进行分离
context-path: /admin #actuator暴露接口的前缀
security:
enabled: true #actuator是否需要安全保证
roles: SUPERUSER
这样在启动访问localhost:8089/admin/beans就会出现窗口让输入账号密码然后就可以看到监控信息了
[{"context":"application:8088:management","parent":"application:8088","beans":[{"bean":"embeddedServletContainerFactory","aliases":[],"scope":"singleton","type":"org.springframework.boot.context.embedded.tomcat.TomcatEmbeddedServletContainerFactory","resource":"null","dependencies":[]},{"bean":"endpointWebMvcChildContextConfiguration","aliases":
各个接口示例
/autoconfig示例
positiveMatches
中返回的是条件匹配成功的自动化配置negativeMatches
中返回的是条件匹配不成功的自动化配置{
"positiveMatches":{
"DruidDataSourceAutoConfigure":[
{
"condition":"OnClassCondition",
"message":"@ConditionalOnClass found required class 'com.alibaba.druid.pool.DruidDataSource'; @ConditionalOnMissingClass did not find unwanted class"
}
]
},
"negativeMatches":{
"DruidFilterConfiguration#commonsLogFilter":{
"notMatched":[
{
"condition":"OnPropertyCondition",
"message":"@ConditionalOnProperty (spring.datasource.druid.filter.commons-log.enabled) did not find property 'enabled'"
}
],
"matched":[
]
}
}
/beans示例
[
{
"context":"application:8088",
"parent":null,
"beans":[
{
"bean":"redisConfig",
"aliases":[
],
"scope":"singleton",
"type":"com.sid.common.RedisConfig$$EnhancerBySpringCGLIB$$51a9e057",
"resource":"file [D:/gitrep/springboot/target/classes/com/sid/common/RedisConfig.class]",
"dependencies":[
]
}
}
]
/configprops示例
prefix
属性代表了属性的配置前缀properties
代表了各个属性的名称和值{"spring.redis-org.springframework.boot.autoconfigure.data.redis.RedisProperties":{
"prefix":"spring.redis",
"properties":{
"sentinel":null,
"cluster":null,
"database":0,
"password":"******",
"port":6379,
"host":"192.168.2.240",
"pool":{
"maxIdle":70,
"minIdle":0,
"maxActive":70,
"maxWait":3000
},
"ssl":false,
"url":null,
"timeout":0
}
}
}
/env示例
{
"profiles":[
],
"server.ports":{
"local.management.port":8089,
"local.server.port":8088
},
"servletContextInitParams":{
},
"systemProperties":Object{...},
"systemEnvironment":Object{...},
"applicationConfig: [classpath:/application.yml]":Object{...}
}
/mappings示例
bean
属性标识了该映射关系的请求处理器method
属性标识了该映射关系的具体处理类和处理函数{
"/webjars/**":{
"bean":"resourceHandlerMapping"
},
"/**":{
"bean":"resourceHandlerMapping"
},
"/**/favicon.ico":{
"bean":"faviconHandlerMapping"
},
"{[/user/add]}":{
"bean":"requestMappingHandlerMapping",
"method":"public com.sid.model.User com.sid.controller.UserController.addUser(com.sid.model.User)"
},
"{[/user/delete]}":{
"bean":"requestMappingHandlerMapping",
"method":"public int com.sid.controller.UserController.deleteUser(java.lang.String)"
},
"{[/user/selectAll]}":{
"bean":"requestMappingHandlerMapping",
"method":"public com.github.pagehelper.PageInfo com.sid.controller.UserController.selectAll(int,int)"
},
"{[/error]}":{
"bean":"requestMappingHandlerMapping",
"method":"public org.springframework.http.ResponseEntity> org.springframework.boot.autoconfigure.web.BasicErrorController.error(javax.servlet.http.HttpServletRequest)"
},
"{[/error],produces=[text/html]}":{
"bean":"requestMappingHandlerMapping",
"method":"public org.springframework.web.servlet.ModelAndView org.springframework.boot.autoconfigure.web.BasicErrorController.errorHtml(javax.servlet.http.HttpServletRequest,javax.servlet.http.HttpServletResponse)"
}
}
/info示例
/metrics示例
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
,它代表了对静态资源的访问。这两类度量指标非常有用,我们不仅可以使用它默认的统计指标,还可以在程序中轻松的增加自定义统计值
{
"mem":705295,
"mem.free":494933,
"processors":4,
"instance.uptime":1944236,
"uptime":1950389,
"systemload.average":-1,
"heap.committed":634880,
"heap.init":262144,
"heap.used":139946,
"heap":3702784,
"nonheap.committed":71936,
"nonheap.init":2496,
"nonheap.used":70417,
"nonheap":0,
"threads.peak":62,
"threads.daemon":45,
"threads.totalStarted":85,
"threads":48,
"classes":9363,
"classes.loaded":9364,
"classes.unloaded":1,
"gc.ps_scavenge.count":8,
"gc.ps_scavenge.time":129,
"gc.ps_marksweep.count":2,
"gc.ps_marksweep.time":106,
"httpsessions.max":-1,
"httpsessions.active":0,
"gauge.response.user.selectAll":302,
"counter.status.500.user.selectAll":1
}
对 /metrics 接口提供的信息进行简单分类如下表:
分类 | 前缀 | 报告内容 |
---|---|---|
垃圾收集器 | gc.* | 已经发生过的垃圾收集次数,以及垃圾收集所耗费的时间,适用于标记-清理垃圾收集器和并行垃圾收集器(数据源自java.lang.management. GarbageCollectorMXBean) |
内存 | mem.* | 分配给应用程序的内存数量和空闲的内存数量(数据源自java.lang. Runtime) |
堆 | heap.* | 当前内存用量(数据源自java.lang.management.MemoryUsage) |
类加载器 | classes.* | JVM类加载器加载与卸载的类的数量(数据源自java.lang. management.ClassLoadingMXBean) |
系统 | processors、instance.uptime、uptime、systemload.average | 系统信息,例如处理器数量(数据源自java.lang.Runtime)、运行时间(数据源自java.lang.management.RuntimeMXBean)、平均负载(数据源自java.lang.management.OperatingSystemMXBean) |
线程池 | thread.* | 线程、守护线程的数量,以及JVM启动后的线程数量峰值(数据源自 java.lang .management.ThreadMXBean) |
数据源 | datasource.* | 数据源连接的数量(源自数据源的元数据,仅当Spring应用程序上下文里存在 DataSource Bean 的时候才会有这个信息) |
Tomcat 会话 | httpsessions.* | Tomcat的活跃会话数和最大会话数(数据源自嵌入式Tomcat的Bean,仅在使用嵌入式Tomcat服务器运行应用程序时才有这个信息) |
HTTP | counter.status.、gauge.response. | 多种应用程序服务HTTP请求的度量值与计数器 |
这里的一些度量值,比如数据源和Tomcat会话,仅在应用程序中运行特定组件时才有数据。
HTTP的计数器和度量值说明:counter.status 后的值是HTTP状态码,随后是所请求的路径。
比如:"counter.status.500.user.selectAll":1 表明/user/selectAll接口返回 500状态码的次数为1。
HTTP响应的度量值说明:gauge.response,后是对应的路径。
度量值是以毫秒为单位的时间,表示最近处理该路径请求的耗时。
比如:"gauge.response.user.selectAll":302 表明/user/selectAll接口最近一次请求耗时302毫秒。
这里还有几个特殊的值需要注意。root路径指向的是根路径或/。
star-star代表了那些Spring 认为是静态资源的路径,包括图片、JavaScript和样式表,其中还包含了那些找不到的资源。
这就是经常会看到 counter.status.404.star-star,这是返回了HTTP 404 (NOT FOUND) 状态的请求数。
/health示例
{
"status":"UP",
"diskSpace":{
"status":"UP",
"total":154151153664,
"free":147728592896,
"threshold":10485760
},
"redis":{
"status":"UP",
"version":"3.2.10"
},
"db":{
"status":"UP",
"database":"MySQL",
"hello":1
}
}
/dump示例
{
"threadName":"http-nio-8088-Acceptor-0",
"threadId":80,
"blockedTime":-1,
"blockedCount":10,
"waitedTime":-1,
"waitedCount":0,
"lockName":null,
"lockOwnerId":-1,
"lockOwnerName":null,
"inNative":true,
"suspended":false,
"threadState":"RUNNABLE",
"stackTrace":[
{
"methodName":"accept0",
"fileName":"ServerSocketChannelImpl.java",
"lineNumber":-2,
"className":"sun.nio.ch.ServerSocketChannelImpl",
"nativeMethod":true
},
{
"methodName":"accept",
"fileName":"ServerSocketChannelImpl.java",
"lineNumber":422,
"className":"sun.nio.ch.ServerSocketChannelImpl",
"nativeMethod":false
},
{
"methodName":"accept",
"fileName":"ServerSocketChannelImpl.java",
"lineNumber":250,
"className":"sun.nio.ch.ServerSocketChannelImpl",
"nativeMethod":false
},
{
"methodName":"run",
"fileName":"NioEndpoint.java",
"lineNumber":455,
"className":"org.apache.tomcat.util.net.NioEndpoint$Acceptor",
"nativeMethod":false
},
{
"methodName":"run",
"fileName":"Thread.java",
"lineNumber":748,
"className":"java.lang.Thread",
"nativeMethod":false
}
],
"lockedMonitors":[
{
"className":"java.lang.Object",
"identityHashCode":1089871804,
"lockedStackDepth":2,
"lockedStackFrame":{
"methodName":"accept",
"fileName":"ServerSocketChannelImpl.java",
"lineNumber":250,
"className":"sun.nio.ch.ServerSocketChannelImpl",
"nativeMethod":false
}
}
],
"lockedSynchronizers":[
],
"lockInfo":null
}
/trace示例
{
"timestamp":1542336977009,
"info":{
"method":"POST",
"path":"/sid/user/selectAll",
"headers":{
"request":{
"cache-control":"no-cache",
"postman-token":"5c8f7b21-0d94-47f7-a3bd-93d3c2585792",
"user-agent":"PostmanRuntime/7.4.0",
"accept":"*/*",
"host":"localhost:8088",
"accept-encoding":"gzip, deflate",
"content-type":"multipart/form-data; boundary=--------------------------397337630825961403061295",
"content-length":"271",
"connection":"keep-alive"
},
"response":{
"X-Application-Context":"application:8088",
"status":"500"
}
},
"timeTaken":"260"
}
}