文章目录
写在前面
本文参考自 Spring-Boot 官方文档,介绍了 actuator 常用特性,关于具体的配置可参考官方文档。
在官方文档是如何定义 Spring Boot Actuator 的? 生产就绪 的特性。
Spring Boot 包含许多附加功能,可以帮助您在将应用程序推向生产环境时对其进行监视和管理。您可以选择使用 HTTP 端点或
JMX来管理和监视应用程序。审计、健康状况和指标收集也可以自动应用到您的应用程序中。
1. 启用
启用 actuator 非常简单,基于 Maven 的项目,只需要导入以下依赖:
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
</dependencies>
根据 spring-boot-starter-actuator 的 pom 文件,跟踪依赖关系,我们发现 actuator 的主要代码在 spring-boot-actuator, 自动配置相关的在spring-boot-actuator-autoconfigure 包下,可以尝试浏览包结构,以获取概要信息。
2. 端点
端点提供了我们与actuator所监视的应用程序交互的能力。Spring Boot 本身已经内置了许多端点,例如,health 端点。当然,我们也可以添加自己的端点。
可以启用或禁用每个端点。这将控制是否创建端点及其bean存在于应用程序上下文中。要实现远程访问,还必须通过
JMX或HTTP暴露端点。大多数应用程序选择 HTTP,其中端点的ID和前缀/actuator被映射到一个URL。例如,默认情况下,健康端点映射到/actuator/health。
查看 @Endpoint 注解,该注解的文档说明指出该注解是为运行的应用提供 actuator端点。端点可以通过 JMX和 HTTP 技术对外暴露。所以我们很容易在该注解类所处的包结构下,发现 web 以及 jmx 包。
大多数 @Endpoint 类会声明一个或多个
@ReadOperation,@WriteOperation,
@DeleteOperation注解的方法,这些方法将适应暴露的技术自动执行。
2.1 实现自定义端点
如何 实现自定义端点 呢?最好的样例就是来自源码,我们可以查看HealthEndpoint 端点。
@Endpoint(id = "health")
public class HealthEndpoint {
private final HealthIndicator healthIndicator;
/**
* Create a new {@link HealthEndpoint} instance that will use the given
* {@code healthIndicator} to generate its response.
* @param healthIndicator the health indicator
*/
public HealthEndpoint(HealthIndicator healthIndicator) {
Assert.notNull(healthIndicator, "HealthIndicator must not be null");
this.healthIndicator = healthIndicator;
}
@ReadOperation
public Health health() {
return this.healthIndicator.health();
}
/**
* Return the {@link Health} of a particular component or {@code null} if such
* component does not exist.
* @param component the name of a particular {@link HealthIndicator}
* @return the {@link Health} for the component or {@code null}
*/
@ReadOperation
public Health healthForComponent(@Selector String component) {
HealthIndicator indicator = getNestedHealthIndicator(this.healthIndicator, component);
return (indicator != null) ? indicator.health() : null;
}
/**
* Return the {@link Health} of a particular {@code instance} managed by the specified
* {@code component} or {@code null} if that particular component is not a
* {@link CompositeHealthIndicator} or if such instance does not exist.
* @param component the name of a particular {@link CompositeHealthIndicator}
* @param instance the name of an instance managed by that component
* @return the {@link Health} for the component instance of {@code null}
*/
@ReadOperation
public Health healthForComponentInstance(@Selector String component, @Selector String instance) {
HealthIndicator indicator = getNestedHealthIndicator(this.healthIndicator, component);
HealthIndicator nestedIndicator = getNestedHealthIndicator(indicator, instance);
return (nestedIndicator != null) ? nestedIndicator.health() : null;
}
private HealthIndicator getNestedHealthIndicator(HealthIndicator healthIndicator, String name) {
if (healthIndicator instanceof CompositeHealthIndicator) {
return ((CompositeHealthIndicator) healthIndicator).getRegistry().get(name);
}
return null;
}
}
我们需要注意的是 该类需要被声明为 Bean ( Intellij 自动提示的)。观察上诉类,我们需要关心的仅仅是方法的注解,查看注解文档,实现自己的端点:
@Endpoint(id = "appInfo")
public class AppInfoEndpoint {
/**
* app 描述信息
*/
private String desc;
/**
* app 作者信息
*/
private Author author;
public AppInfoEndpoint(String desc, Author author){
this.desc = desc;
this.author = author;
}
/**
* 读取描述: HTTP GET请求:http://localhost:8089/actuator/appInfo
*/
@ReadOperation
public String getDesc(){
return this.desc;
}
/**
* 读取作者信息:HTTP GET请求:http://localhost:8089/actuator/appInfo/1
*/
@ReadOperation
public Author getAuthor(@Selector Integer type ){
if(type.intValue() == 1){
return author;
}
return null;
}
/**
* 修改作者姓名,并返回旧的名称:HTTP POST请求:http://localhost:8089/actuator/appInfo/DUO
*/
@WriteOperation
public String updateAuthor(@Selector String name){
String oldName = author.getName();
this.author.setName(name);
return oldName;
}
}
声明 Bean :
@Bean
public AppInfoEndpoint appInfoEndpoint(){
Author author = new Author();
author.setName("duofei");
author.setAge(25);
author.setEmail("662@.com");
return new AppInfoEndpoint("我仅仅是一个测试程序", author);
}
在配置文件中对外暴露该端点:
management:
endpoints:
web:
exposure:
include: appInfo,health
2.2 实现安全的端点
如果存在Spring Security,则默认情况下使用Spring Security的内容协商策略保护端点。例如,如果希望为HTTP 端点配置自定义安全性,只允许具有特定角色的用户访问它们,Spring Boot 提供了一些方便的RequestMatcher对象,可以将它们与Spring security结合使用。
导入spring-boot-starter-security:
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-security</artifactId>
</dependency>
这时运行示例,我们能在控制台获取生成的密码,在访问时,需要这样请求:
curl -X GET http://user:180ac8e3-d614-47ca-984b-d22a21769fd0@localhost:8089/actuator/appInfo/1
2.3 跨域支持
CORS 支持在默认情况下是禁用的,并且只在 management.endpoints.web.cors.allowed-origins 设置了值后启用。下面的配置允许从example.com 域发起 GET和 POST 请求:
management.endpoints.web.cors.allowed-origins=https://example.com
management.endpoints.web.cors.allowed-methods=GET,POST
3.基于 HTTP 的监控和管理
如果开发web应用程序,Spring Boot actuator 将自动配置所有通过 HTTP 公开的已启用端点。默认约定是使用带有 /actuator 作为URL路径前缀。
3.1 自定义管理端点路径
有时,为管理端点定制前缀是有用的。例如,您的应用程序可能已经将/actuator 用于其他目的。
management.endpoints.web.base-path=/manage
上诉我们对端点的访问由/actuator/appInfo 变为了 /manage/appInfo。
如果希望将端点映射到不同的路径,可以使用 management.endpoints.web.path-mapping 属性。
management.endpoints.web.base-path=/
management.endpoints.web.path-mapping.health=healthcheck
/actuator/health 映射为 /healthcheck。
3.2 自定义管理端口
通过使用不同的HTTP端口来公开端点:
management.server.port=8081
3.3 禁用 HTTP 端点
如果,并不想暴露任何基于 HTTP 的端点,可以设置管理端口号为 -1。
management.server.port=-1
或者
management.endpoints.web.exposure.exclude=*
4. 日志记录器
Spring Boot 执行器包括在运行时查看和配置应用程序日志级别的功能。您可以查看整个列表或单个日志记录器的配置,它由显式配置的日志级别和日志框架提供给它的有效日志级别组成。这些级别可以是:
TRACEDEBUGINFOWARNERRORFATALOFFnull
null 表示没有显式配置。
为了配置日志记录器,使用 POST 请求访问资源 URL (/actuator/loggers):
{
"configuredLevel": "DEBUG"
}
重置日志记录期的级别,仅仅需要为 configuredLevel 传递一个 null。
更具体的可以分析
LoggersEndpoint类。
5. HTTP 跟踪
可以通过在应用程序的配置中提供 HttpTraceRepository类型的bean来启用HTTP跟踪。为了方便起见,Spring Boot提供了一个InMemoryHttpTraceRepository,它默认存储最后100个请求-响应交换的跟踪。与其他跟踪解决方案相比,InMemoryHttpTraceRepository 是有限的,我们建议仅在开发环境中使用它。对于生产环境,建议使用可用于生产的跟踪或可观察性解决方案,如 Zipkin 或 Spring Cloud Sleuth。或者,创建自己的HttpTraceRepository 来满足您的需求。
httptrace 端点可用于获取关于存储在 HttpTraceRepository 中的请求-响应交换的信息。
以上提到的所有端点都需要通过配置文件对外暴露,配置文件默认只暴露了 health, info 。