微服务的特点决定了功能模块的部署是分布式的,大部分功能模块都是运行在不同的机器上,彼此通过服务调用进行交互,前后台的业务流会经过很多个微服务的处理和传递;在这种情况下,服务的健康监控就变的尤为重要,使用SpringBoot Actuator可以方便我们对于服务进行监控治理。
在这种框架下,微服务的监控显得尤为重要。本文主要结合Spring Boot Actuator,跟大家一起分享微服务Spring Boot Actuator的常见用法,方便我们在日常中对我们的微服务进行监控治理。
Spring Boot使用“习惯优于配置的理念”,采用包扫描和自动化配置的机制来加载依赖jar中的Spring bean,不需要任何Xml配置,就可以实现Spring的所有配置。虽然这样做能让我们的代码变得非常简洁,但是整个应用的实例创建和依赖关系等信息都被离散到了各个配置类的注解上,这使得我们分析整个应用中资源和实例的各种关系变得非常的困难。
生产系统中,往往需要对系统实际运行的情况(例如cpu、io、disk、db、业务功能等指标)进行监控运维。在SpringBoot项目中Actuator模块提供了众多HTTP接口端点(Endpoint),来提供应用程序运行时的内部状态信息。
Actuator模块提供了一个监控和管理生产环境的模块,可以使用http、jmx、ssh、telnet等来管理和监控应用。包括应用的审计(Auditing)、健康(health)状态信息、数据采集(metrics gathering)统计等监控运维的功能。同时,提供了可以扩展 Actuator端点(Endpoint)自定义监控指标。这些指标都是以JSON接口数据的方式呈现。
添加springboot actuator依赖,即可开始使用springboot actuator:
org.springframework.boot
spring-boot-starter-actuator
为了保证actuator暴露的监控接口的安全性,需要添加安全控制的依赖spring-boot-start-security依赖,访问应用监控端点时,都需要输入验证信息。Security依赖,可以选择不加,不进行安全管理,但不建议这么做。所需依赖如下:
org.springframework.boot
spring-boot-starter-security
关于security的使用我们在此不进行展开,可在application文件中配置相应的访问密码:
spring:
security:
user:
name: admin
password: admin
在下面的内容中为了方便,我们暂时不引入security。
经过以上步骤的操作,启动SpringBoot项目,actuator便自动集成配置了,可通过:http://localhost:8080/actuator 访问,结果如下:
{
"_links": {
"self": {
"href": "http://localhost:8080/actuator",
"templated": false
},
"health": {
"href": "http://localhost:8080/actuator/health",
"templated": false
},
"health-component": {
"href": "http://localhost:8080/actuator/health/{component}",
"templated": true
},
"health-component-instance": {
"href": "http://localhost:8080/actuator/health/{component}/{instance}",
"templated": true
},
"info": {
"href": "http://localhost:8080/actuator/info",
"templated": false
}
}
}
默认支持的链接有:
/actuator
/actuator/health
/health/{component}/{instance}
/health/{component}
/actuator/info
可以在application配置文件中配置开启更多的监控信息:
management:
endpoints:
web:
exposure:
include: '*'
# base-path: /monitor
endpoint:
health:
show-details: always
shutdown:
enabled: true
监控信息如果需要跨越调用,可通过CORS配置来支持,默认处于禁用状态。设置management.endpoints.web.cors.allowed-origins属性后开启。
比如允许来自https://www.choupangxia.com 域的GET和POST调用:
management:
endpoints:
web:
cors:
allowed-origins: https://www.choupangxia.com
allowed-methods: GET,POST
Spring Boot Actuator提供了非常丰富的监控接口,可以通过这些接口了解应用程序运行时的内部状况。Actuator也支持用户自定义添加端点,可以根据实际应用,定义一些比较关心的指标,在运行期进行监控。
HTTP | 路径 | 描述 |
---|---|---|
GET | /auditevents | 显示当前应用程序的审计事件信息 |
GET | /beans | 显示一个应用中所有Spring Beans的完整列表 |
GET | /conditions | 显示配置类和自动配置类(configuration and auto-configuration classes)的状态及它们被应用或未被应用的原因。 |
GET | /configprops | 显示一个所有@ConfigurationProperties的集合列表 |
GET | /env | 显示来自Spring的ConfigurableEnvironment的属性。 |
GET | /flyway | 显示数据库迁移路径,如果有的话。 |
GET | /health | 显示应用的健康信息(当使用一个未认证连接访问时显示一个简单的’status’,使用认证连接访问则显示全部信息详情) |
GET | /info | 显示任意的应用信息 |
GET | /liquibase | 展示任何Liquibase数据库迁移路径,如果有的话 |
GET | /metrics | 展示当前应用的metrics信息 |
GET | /mappings | 显示一个所有@RequestMapping路径的集合列表 |
GET | /scheduledtasks | 显示应用程序中的计划任务 |
GET | /sessions | 允许从Spring会话支持的会话存储中检索和删除(retrieval and deletion)用户会话。使用Spring Session对反应性Web应用程序的支持时不可用。 |
POST | /shutdown | 允许应用以优雅的方式关闭(默认情况下不启用) |
GET | /threaddump | 执行一个线程dump |
GET | /auditevents | 显示当前应用程序的审计事件信息 |
GET | /beans | 显示一个应用中所有Spring Beans的完整列表 |
GET | /conditions | 显示配置类和自动配置类(configuration and auto-configuration classes)的状态及它们被应用或未被应用的原因。 |
GET | /configprops | 显示一个所有@ConfigurationProperties的集合列表 |
GET | /env | 显示来自Spring的ConfigurableEnvironment的属性。 |
GET | /flyway | 显示数据库迁移路径,如果有的话。 |
GET | /health | 显示应用的健康信息(当使用一个未认证连接访问时显示一个简单的’status’,使用认证连接访问则显示全部信息详情) |
GET | /info | 显示任意的应用信息 |
GET | /liquibase | 展示任何Liquibase数据库迁移路径,如果有的话 |
GET | /metrics | 展示当前应用的metrics信息 |
GET | /mappings | 显示一个所有@RequestMapping路径的集合列表 |
GET | /scheduledtasks | 显示应用程序中的计划任务 |
GET | /sessions | 允许从Spring会话支持的会话存储中检索和删除(retrieval and deletion)用户会话。使用Spring Session对反应性Web应用程序的支持时不可用。 |
POST | /shutdown | 允许应用以优雅的方式关闭(默认情况下不启用) |
GET | /threaddump | 执行一个线程dump |
如果使用web应用(Spring MVC, Spring WebFlux, 或者 Jersey),还可以使用以下接口:
HTTP | 路径 | 描述 |
---|---|---|
GET | /heapdump | 返回一个GZip压缩的hprof堆dump文件 |
GET | /jolokia | 通过HTTP暴露JMX beans(当Jolokia在类路径上时,WebFlux不可用) |
GET | /logfile | 返回日志文件内容(如果设置了logging.file或logging.path属性的话),支持使用HTTP Range头接收日志文件内容的部分信息 |
GET | /prometheus | 以可以被Prometheus服务器抓取的格式显示metrics信息 |
health主要用来检查应用的运行状态,这是使用频次最高的监控点。通常使用此接口显示应用实例的运行状态,以及应用不“健康”的原因,比如数据库连接、磁盘空间不够等。
默认情况下health的状态是开放的,访问:http://localhost:8080/actuator/health 即可看到应用的状态。
{
"status" : "UP"
}
设置状态码顺序:setStatusOrder(Status.DOWN,Status.OUT_OF_SERVICE, Status.UP, Status.UNKNOWN)。过滤掉不能识别的状态码。如果无任何状态码,整个SpringBoot应用的状态是UNKNOWN。将所有收集到的状态码排序。返回有序状态码序列中的第一个状态码,作为整个SpringBoot应用的状态。
Health通过合并几个健康指数检查应用的健康情况。SpringBoot Actuator会自动配置以下内容:
名称 | 描述 |
---|---|
CassandraHealthIndicator | 检查Cassandra数据库是否已启动。 |
CouchbaseHealthIndicator | 检查Couchbase群集是否已启动。 |
DiskSpaceHealthIndicator | 检查磁盘空间不足。 |
DataSourceHealthIndicator | 检查是否可以建立连接DataSource。 |
ElasticsearchHealthIndicator | 检查Elasticsearch集群是否已启动。 |
InfluxDbHealthIndicator | 检查InfluxDB服务器是否已启动。 |
JmsHealthIndicator | 检查JMS代理是否启动。 |
MailHealthIndicator | 检查邮件服务器是否已启动。 |
MongoHealthIndicator | 检查Mongo数据库是否已启动。 |
Neo4jHealthIndicator | 检查Neo4j服务器是否已启动。 |
RabbitHealthIndicator | 检查Rabbit服务器是否已启动。 |
RedisHealthIndicator | 检查Redis服务器是否启动。 |
SolrHealthIndicator | 检查Solr服务器是否已启动。 |
可以通过设置 management.health.defaults.enabled属性来全部禁用。
原生端点分为三大类:
/conditions:该端点用来获取应用的自动化配置报告,其中包括所有自动化配置的候选项。同时还列出了每个候选项自动化配置的各个先决条件是否满足。该端点可以帮助我们方便的找到一些自动化配置为什么没有生效的具体原因。
该报告内容将自动化配置内容分为两部分:positiveMatches中返回的是条件匹配成功的自动化配置和negativeMatches中返回的是条件匹配不成功的自动化配置。
部分代码如下:
"contexts": {
"application": {
"positiveMatches": {
"MsgAutoConfiguration": [
{
"condition": "OnClassCondition",
"message": "@ConditionalOnClass found required class 'com.secbro2.msg.MsgService'"
}
],
"MsgAutoConfiguration#msgService": [
{
"condition": "OnPropertyCondition",
"message": "@ConditionalOnProperty (msg.enabled=true) matched"
},
{
"condition": "OnBeanCondition",
"message": "@ConditionalOnMissingBean (types: com.secbro2.msg.MsgService; SearchStrategy: all) did not find any beans"
}
],
/info:就是在配置文件中配置的以info开头的信息,如配置为:
info:
app:
name: spring-boot-actuator
version: 1.0.0
返回结果:
{
"app":{
"name":"spring-boot-actuator",
"version":"1.0.0"
}
}
info中配置的参数也可以通过符号*@*包围的属性值来自pom.xml文件中的元素节点。如下:
info:
build:
artifact: @project.artifactId@
name: @project.name@
description: @project.description@
ersion: @project.version@
返回结果:
{
"build": {
"artifact": "spring-learn",
"name": "spring-learn",
"description": "Demo project for Spring Boot",
"ersion": "0.0.1-SNAPSHOT"
}
}
/beans:该端点用来获取应用上下文中创建的所有Bean。
{
"contexts": {
"application": {
"beans": {
"endpointCachingOperationInvokerAdvisor": {
"aliases": [],
"scope": "singleton",
"type": "org.springframework.boot.actuate.endpoint.invoker.cache.CachingOperationInvokerAdvisor",
"resource": "class path resource [org/springframework/boot/actuate/autoconfigure/endpoint/EndpointAutoConfiguration.class]",
"dependencies": ["environment"]
},
"defaultServletHandlerMapping": {
"aliases": [],
"scope": "singleton",
"type": "org.springframework.web.servlet.HandlerMapping",
"resource": "class path resource [org/springframework/boot/autoconfigure/web/servlet/WebMvcAutoConfiguration$EnableWebMvcConfiguration.class]",
"dependencies": []
},
},
"parentId": null
}
}
}
接口展现了bean的别名、类型、是否单例、类的地址、依赖等信息。
/configprops:该端点用来获取应用中配置的属性信息报告。
{
"spring.transaction-org.springframework.boot.autoconfigure.transaction.TransactionProperties": {
"prefix": "spring.transaction",
"properties": {}
}
}
上面展示了TransactionProperties属性的配置信息。
/mappings:该端点用来返回所有SpringMVC的控制器映射关系报告。
{
"handler": "Actuator web endpoint 'beans'",
"predicate": "{GET /actuator/beans, produces [application/vnd.spring-boot.actuator.v2+json || application/json]}",
"details": {
"handlerMethod": {
"className": "org.springframework.boot.actuate.endpoint.web.servlet.AbstractWebMvcEndpointHandlerMapping.OperationHandler",
"name": "handle",
"descriptor": "(Ljavax/servlet/http/HttpServletRequest;Ljava/util/Map;)Ljava/lang/Object;"
},
"requestMappingConditions": {
"consumes": [],
"headers": [],
"methods": ["GET"],
"params": [],
"patterns": ["/actuator/beans"],
"produces": [{
"mediaType": "application/vnd.spring-boot.actuator.v2+json",
"negated": false
}, {
"mediaType": "application/json",
"negated": false
}]
}
}
}
/env:该端点与/configprops不同,它用来获取应用所有可用的环境属性报告。包括:环境变量、JVM属性、应用的配置配置、命令行中的参数。
应用配置类提供的指标为静态报告,而度量指标类端点提供的报告内容则是动态变化的,提供了应用程序在运行过程中的一些快照信息,比如:内存使用情况、HTTP请求统计、外部资源指标等。这些端点对于构建微服务架构中的监控系统非常有帮助。
/metrics:该端点用来返回当前应用的各类重要度量指标,比如:内存信息、线程信息、垃圾回收信息等。
{
"names": [
"jvm.memory.max",
"jvm.threads.states",
"http.server.requests",
"process.files.max",
"jvm.gc.memory.promoted",
"system.load.average.1m",
"jvm.memory.used",
"jvm.gc.max.data.size",
"jvm.gc.pause",
"jvm.memory.committed",
"system.cpu.count",
"logback.events",
"tomcat.global.sent",
"jvm.buffer.memory.used",
"tomcat.sessions.created",
"jvm.threads.daemon",
"system.cpu.usage",
"jvm.gc.memory.allocated",
"tomcat.global.request.max",
"tomcat.global.request",
"tomcat.sessions.expired",
"jvm.threads.live",
"jvm.threads.peak",
"tomcat.global.received",
"process.uptime",
"tomcat.sessions.rejected",
"process.cpu.usage",
"tomcat.threads.config.max",
"jvm.classes.loaded",
"jvm.classes.unloaded",
"tomcat.global.error",
"tomcat.sessions.active.current",
"tomcat.sessions.alive.max",
"jvm.gc.live.data.size",
"tomcat.threads.current",
"process.files.open",
"jvm.buffer.count",
"jvm.buffer.total.capacity",
"tomcat.sessions.active.max",
"tomcat.threads.busy",
"process.start.time"
]
}
从上面的示例中有这些重要的度量值:
系统信息:包括处理器数量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。
/threaddump:会生成当前线程活动的快照。方便我们在日常定位问题的时候查看线程的情况。主要展示了线程名、线程ID、线程的状态、是否等待锁资源等信息。
{
"threads": [{
"threadName": "Reference Handler",
"threadId": 2,
"blockedTime": -1,
"blockedCount": 2,
"waitedTime": -1,
"waitedCount": 0,
"lockName": null,
"lockOwnerId": -1,
"lockOwnerName": null,
"daemon": true,
"inNative": false,
"suspended": false,
"threadState": "RUNNABLE",
"priority": 10,
"stackTrace": [{
"classLoaderName": null,
"moduleName": "java.base",
"moduleVersion": "11.0.4",
"methodName": "waitForReferencePendingList",
"fileName": "Reference.java",
"lineNumber": -2,
"className": "java.lang.ref.Reference",
"nativeMethod": true
}
...
"lockedMonitors": [],
"lockedSynchronizers": [{
"className": "java.util.concurrent.locks.ReentrantLock$NonfairSync",
"identityHashCode": 2060076420
}],
"lockInfo": null
...
{
"threadName": "DestroyJavaVM",
"threadId": 42,
"blockedTime": -1,
"blockedCount": 0,
"waitedTime": -1,
"waitedCount": 0,
"lockName": null,
"lockOwnerId": -1,
"lockOwnerName": null,
"daemon": false,
"inNative": false,
"suspended": false,
"threadState": "RUNNABLE",
"priority": 5,
"stackTrace": [],
"lockedMonitors": [],
"lockedSynchronizers": [],
"lockInfo": null
}]
}
/trace:该端点用来返回基本的HTTP跟踪信息。默认情况下,跟踪信息的存储采用。
/shutdown:配置文件中配置开启此功能:
management.endpoint.shutdown.enabled=true
使用 curl 模拟 post 请求此接口:
curl -X POST "http://localhost:8080/actuator/shutdown"
显示结果为:
{
"message": "Shutting down, bye..."
}