本文介绍Spring Boot2 Actuator,首先介绍基础概念,接着学习如何使用、配置、扩展这个监控工具。
Actuator提供产品级的功能特性,使得监控应用、收集指标和流量、数据库状态变得非常简单。该库的主要优势是能够获得产品级工具,无需自己实际实现。主要用于暴露正在运行系统的操作信息,包括健康状态、指标信息、系统及环境信息等。可以使用HTTP或JMX方式进行通信交互。
只要加入依赖,默认提供几个健康端点可用,对于大多数Spring模块,有多种方式很容易进行配置或扩展。
要启用Actuator,仅需加入下面依赖包:
<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-actuator</artifactId> </dependency>注:无论Spring boot版本是什么,这都是有效的。但本文主要聚焦2.x版本。
2.x版本Actouator在之前的基础上,简化模型,扩展其功能并加入更好的缺省能力。 首先该版本与技术无关,与系统合并安全功能简化模型。最后,在各种变化中,重要的是要记住,其中一些是破坏的。这包括HTTP请求和响应以及Java api。 此外,最新版本现在支持CRUD模型,而不是旧的读/写模型。
当前主要版本与底层技术无关,而1.x版本依赖MVC,即Servlet API。2.x版本定义自己的模型,可插拔、可扩展,无需依赖MVC。因此使用新的模型,既可以使用MVC,也可以使用WebFlux作为底层web技术。而且还可以实现适配层支持未来技术。最后要说的是,仍然支持JMX暴露的端点,且无需额外代码。
与之前版本不同的是,废弃了大多数Actuator端点,仅保留两个缺省的端点:/health 和 /info 。 如果想启用所有端点,可以设置 management.endpoints.web.exposure.include=*.,当然也可以列出仅启用部分的端点列表。
Actuator 现在与正常应用共享安全规则配置,因此其安全模型也非常简单。调整Actuator安全规则,仅增加/actuator/** :
@Bean public SecurityWebFilterChain securityWebFilterChain( ServerHttpSecurity http) { return http.authorizeExchange() .pathMatchers("/actuator/**").permitAll() .anyExchange().authenticated() .and().build(); }另外,Actuator的缺省端点是在 /actuator路径下。和前面版本一样,可以调整该路径,使用新的属性:management.endpoints.web.base-path 。
下面看看常用端点,大多数之前版本都有。但还是有变动,增加、删除和重构了一些端点。
端点描述/auditevents列出所有安全审计相关的事件,如用户登录、登出。同时也可以根据用户的字段进行过滤。/beans返回所有BeanFactory中有效bean,与/auditevents不同,其不支持过滤。/conditions之前是/autoconfig,返回自动配置中条件配置信息/configprops返回所有@ConfigurationProperties配置bean列表/env列出当前环境属性,另外也可以返回单个属性信息/flyway提供Flyway 数据库迁移信息/health返回应用的健康指标信息/heapdump返回应用使用的JVM中堆内存快照/info返回通用信息,包括自定义属性信息/liquibase提供Liquibase数据库迁移信息/logfile返回应用日志/loggers可以查询或修改应用日志级别/metrics应用的度量指标信息,包括通用及自定义的度量指标/prometheus和上面端点一样,返回所有度量指标信息,但兼容Prometheus server(开源监控系统)格式/scheduledtasks返回应用中所有的调度任务细节/sessions列出 HTTP sessions,如果我们使用Spring Session/shutdown执行应用程序优雅退出动作/threaddump返回底层JVM线程信息快照Spring Boot 增加了一个总入口点可以获得所有有效actuator,利用总入口点可以获得Actuator入口及其相应url。
缺省总入口点访问地址为 /actuator,如果发送GET请求,返回所有不同的Actuator:
如果你自定义管理基础路径,那么应该使用你定义的路径作为url。举例,如果你设置management.endpoints.web.base-path=/mgmt,那么应该发送 /mgmt入口点请求。有趣的是,当设置基础路径为 / 时则禁用Actuator入口点,这是为了防止和其他映射冲突。
和之前版本一样,可以很容易增加自定义指标。与其他API不同,创建自定义健康入口点的抽象没变,但增加了新的接口ReactiveHealthIndicator实现响应式健康检查。 下面看一个响应式健康检查示例:
@Component public class DownstreamServiceHealthIndicator implements ReactiveHealthIndicator { @Override public Mono<Health> health() { return checkDownstreamServiceHealth().onErrorResume( ex -> Mono.just(new Health.Builder().down(ex).build()) ); } private Mono<Health> checkDownstreamServiceHealth() { // we could use WebClient to check health reactively return Mono.just(new Health.Builder().up().build()); } }健康指标有一个很方便特性是可以聚集作为层次结构的一部分。因此对于前面的示例,可以将所有下流服务作为子分类,该分类可以作为嵌入服务。这块内容后续文章会更详细讲解。
Spring Boot2.2 可以组织多个健康指标为组,对组成员使用相同指标进行配置。举例,创建分组 costom分组,application.properties配置如下:
management.endpoint.health.group.custom.include=diskSpace,ping上面配置定义了custom组,包括diskSpace,ping健康指标。现在如果访问/actuator/health端点,响应中包括了我们增加的分组:
{"status":"UP","groups":["custom"]}使用健康分组,可以看到多个健康指标的组合结果。在这种情况,如果发送/actuator/health/custom请求:
{"status":"UP"}现在可以增加配置显示分组内指标的详细信息:
management.endpoint.health.group.custom.show-components=always management.endpoint.health.group.custom.show-details=always现在访问/actuator/health/custom端点,返回内容包括:
{ "status": "UP", "components": { "diskSpace": { "status": "UP", "details": { "total": 214748360704, "free": 112445571072, "threshold": 10485760, "exists": true } }, "ping": { "status": "UP" } } }也可以设置为仅针对授权用户才展示详细信息:
management.endpoint.health.group.custom.show-components=when_authorized management.endpoint.health.group.custom.show-details=when_authorized我们还增加自定义状态映射。举例,代替200响应码返回207状态码:
management.endpoint.health.group.custom.status.http-mapping.up=207该配置告诉Spring Boot,如果custom分组状态是UP则返回207状态码。
Spring Boot2.0开始使用Micrometer实现内置度量,我们期望有较大改变。如果应用程序使用度量服务,则GaugeService或CounterService它们将不再可用。而是可以和Micrometer直接进行交互,Spring Boot2.0自动配置了MeterRegistry Bean。
另外,Micrometer现在是Actuator依赖的一部分,因此无需增加额外的依赖。访问/metrics可以看到新的响应内容:
{ "names": [ "hikaricp.connections", "hikaricp.connections.acquire", "hikaricp.connections.active", "hikaricp.connections.creation", "hikaricp.connections.idle", "hikaricp.connections.max", "hikaricp.connections.min", "hikaricp.connections.pending", "hikaricp.connections.timeout", "hikaricp.connections.usage", "jdbc.connections.active", "jdbc.connections.idle", "jdbc.connections.max", "jdbc.connections.min", "jvm.buffer.count", "jvm.buffer.memory.used", "jvm.buffer.total.capacity", "jvm.classes.loaded", "jvm.classes.unloaded", "jvm.gc.live.data.size", "jvm.gc.max.data.size", "jvm.gc.memory.allocated", "jvm.gc.memory.promoted", "jvm.gc.pause", "jvm.memory.committed", "jvm.memory.max", "jvm.memory.used", "jvm.threads.daemon", "jvm.threads.live", "jvm.threads.peak", "jvm.threads.states", "logback.events", "process.cpu.usage", "process.start.time", "process.uptime", "system.cpu.count", "system.cpu.usage", // ... ] }如果需要查看特定度量的实际值,可以浏览对应度量指标,如:/actuator/metrics/jvm.gc.pause :
{ "name": "jvm.gc.pause", "description": "Time spent in GC pause", "baseUnit": "seconds", "measurements": [ { "statistic": "COUNT", "value": 2 }, { "statistic": "TOTAL_TIME", "value": 0.172 }, { "statistic": "MAX", "value": 0 } ], "availableTags": [ { "tag": "cause", "values": [ "G1 Evacuation Pause", "Metadata GC Threshold" ] }, { "tag": "action", "values": [ "end of minor GC" ] } ] }如我们所看到的,显示的度量更加全面了。不仅包括不同的值,还包括一些相关的元数据。
前面提到可以创建自定义端点。Spring Boot2重新设计了该实现,支持技术无关模型。下面我们创建一个Actuator端点,用于查询、启用、禁用应用中的特征标志。
@Component @Endpoint(id = "features") public class FeaturesEndpoint { private Map<String, Feature> features = new ConcurrentHashMap<>(); public FeaturesEndpoint(){ features.put("name", Feature.of(true)); // 增加示例内容 } @ReadOperation public Map<String, Feature> features() { return features; } @ReadOperation public Feature feature(@Selector String name) { return features.get(name); } @WriteOperation public void configureFeature(@Selector String name, Feature feature) { features.put(name, feature); } @DeleteOperation public void deleteFeature(@Selector String name) { features.remove(name); } public static class Feature implements Serializable { private Boolean enabled; public Feature(Boolean enabled) { this.enabled = enabled; } public static Feature of(Boolean flag){ return new Feature(true); } public Boolean getEnabled(){ return enabled; } } }定义端点需要定义bean,在上面的示例中我们在bean上使用@Component、@Endpoint两个注解。@Endpoint注解中的参数定义请求路由/actuator/features。定义好bean后,开始定义操作:
@ReadOperation – 映射 HTTP GET@WriteOperation – 映射 HTTP POST@DeleteOperation – 映射 HTTP DELETE当我们启动应用时,Spring Boot会自动注册该bean。这里需要指出的是:
定义端点并不依赖MVC,不再需要实现特定接口(1.x版本需要)可以通过@Endpoint注解第二个参数启用或禁用带端点;如:@Endpoint(id = “features”, enableByDefault = false)可以使用@DeleteOperation注解定义DELETE操作我们可以通过/actuator/features、/actuator/features/{name}进行验证结果。
为了使用http方式访问Actuator端点,需要启用并暴露它们。缺省情况下除了/shutdown端点都启用,但仅 /health 和 /info 两个端点缺省被暴露。增加下面配置可以暴露所有端点:
management.endpoints.web.exposure.include=*显示启用特定端点:
management.endpoint.shutdown.enabled=true暴露所有启用端点除了某个:
management.endpoints.web.exposure.include=* management.endpoints.web.exposure.exclude=loggers本文详细介绍了Spring Boot2 Actuator,包括2.x版本新的变化、常用配置以及如何自定义扩展指标。
