专栏首页转行程序员Spring Boot 从入门到实践系列教程(5)- SpringBoot执行器

Spring Boot 从入门到实践系列教程(5)- SpringBoot执行器

真的勇士,敢于直面惨淡的warning、敢于正视淋漓的error。

1概述

在本文中,我们将介绍Spring Boot Actuator。我们将首先介绍基础知识,然后详细讨论Spring Boot 1.x与2.x中可用的内容。

我们将学习如何在Spring Boot 1.x中使用,配置和扩展此监视工具。然后,我们将讨论如何使用Boot 2.x和WebFlux利用反应式编程模型来做同样的事情。

Spring Boot Actuator自2014年4月开始推出,同时还推出了第一个Spring Boot版本。

随着Spring Boot 2的发布,Actuator已经过重新设计,并添加了新的令人兴奋的终端。

本指南分为3个主要部分:

  • 什么是执行器?
  • Spring Boot 1.x执行器
  • Spring Boot 2.x执行器

2什么是执行器

从本质上讲,Actuator为我们的应用程序带来了生产就绪功能。

通过这种依赖关系监控我们的应用程序,收集指标,了解流量或数据库的状态变得微不足道。

这个库的主要好处是我们可以获得生产级工具,而无需自己实际实现这些功能。

Actuator主要用于公开有关正在运行的应用程序的运行信息 - 运行状况,指标,信息,转储,env等。它使用HTTP端点或JMX bean来使我们能够与它进行交互。

一旦这个依赖关系在类路径上,就可以开箱即用几个端点。与大多数Spring模块一样,我们可以通过多种方式轻松配置或扩展它。

2.1。入门

要启用Spring Boot Actuator,我们只需要将spring-boot-actuator依赖项添加到我们的包管理器中。在Maven:

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-actuator</artifactId>
</dependency>

请注意,无论Boot版本如何,这都保持有效,因为Spring Boot Bill of Materials(BOM)中指定了版本。

3Spring Boot 1.x执行器

在1.x中,执行器遵循R / W模型,这意味着我们可以从中读取或写入它。例如,我们可以检索指标或应用程序的运行状况。或者,我们可以优雅地终止我们的应用程序或更改我们的日志配置。

为了使其工作,Actuator要求Spring MVC通过HTTP公开其端点。没有其他技术支持。

3.1。端点

在1.x中,Actuator带来了自己的安全模型。它利用了Spring Security构造,但需要独立于应用程序的其余部分进行配置。

此外,大多数端点都是敏感的 - 这意味着它们不是完全公开的,换句话说,大多数信息都会被省略 - 而少数端点不是eg / info

以下是Boot提供的一些最常见的端点:

  • / health - 显示应用程序运行状况信息(通过未经身份验证的连接访问时的简单“状态”或经过身份验证时的完整消息详细信息); 它默认不敏感
  • / info -显示任意应用程序信息; 默认情况下不敏感
  • / metrics -显示当前应用程序的“指标”信息; 它默认也很敏感
  • / trace -显示跟踪信息(默认情况下是最后几个HTTP请求)

我们可以在官方文档中找到现有端点的完整列表。

3.2。配置现有端点

可以使用以下格式使用属性自定义每个端点:端点。[端点名称]。[要定制的属性]

有三个属性:

  • id -通过HTTP访问此端点
  • enabled - 如果为true,则可以访问,否则不能访问
  • 敏感 - 如果是,则需要授权通过HTTP显示关键信息

例如,添加以下属性将自定义/ beans端点

endpoints.beans.id=springbeansendpoints.beans.sensitive=falseendpoints.beans.enabled=true

3.3。/ health Endpoint

/健康端点被用来检查正在运行的应用程序的运行状况或状态。它通常由监控软件执行,以提醒我们运行的实例是否因其他原因而关闭或变得不健康。例如,我们的数据库连接问题,磁盘空间不足......

默认情况下,仅显示健康信息以通过HTTP进行未经授权的访问

{
    "status" : "UP"
}

此健康信息是从实现我们的应用程序上下文中配置的HealthIndicator接口的所有bean中收集的。

HealthIndicator返回的一些信息本质上是敏感的 - 但我们可以配置endpoints.health.sensitive = false来公开更详细的信息,如磁盘空间,消息代理连接,自定义检查等。

我们还可以实现自己的自定义运行状况指示器 - 它可以收集特定于应用程序的任何类型的自定义运行状况数据,并通过/ health端点自动公开它:

@Component
public class HealthCheck implements HealthIndicator {
  
    @Override
    public Health health() {
        int errorCode = check(); // perform some specific health check
        if (errorCode != 0) {
            return Health.down()
              .withDetail("Error Code", errorCode).build();
        }
        return Health.up().build();
    }
     
    public int check() {
        // Our logic to check health
        return 0;
    }
}

输出:

{
    "status" : "DOWN",
    "myHealthCheck" : {
        "status" : "DOWN",
        "Error Code" : 1
     },
     "diskSpace" : {
         "status" : "UP",
         "free" : 209047318528,
         "threshold" : 10485760
     }
}

3.4。/ info端点

我们还可以自定义/ info端点显示的数据- 例如:

info.app.name=Spring Sample Application
info.app.description=This is my first spring boot application
info.app.version=1.0.0

输出:

{
    "app" : {
        "version" : "1.0.0",
        "description" : "This is my first spring boot application",
        "name" : "Spring Sample Application"
    }
}

3.5。/ metrics端点

metrics端点发布有关OS,JVM以及应用程序级别度量的信息。一旦启用,我们就会获得内存,堆,处理器,线程,加载的类,卸载的类,线程池以及一些HTTP指标等信息。

以下是此端点的输出开箱即用的内容:

{    "mem" : 193024,    "mem.free" : 87693,    "processors" : 4,    "instance.uptime" : 305027,    "uptime" : 307077,    "systemload.average" : 0.11,    "heap.committed" : 193024,    "heap.init" : 124928,    "heap.used" : 105330,    "heap" : 1764352,    "threads.peak" : 22,    "threads.daemon" : 19,    "threads" : 22,    "classes" : 5819,    "classes.loaded" : 5819,    "classes.unloaded" : 0,    "gc.ps_scavenge.count" : 7,    "gc.ps_scavenge.time" : 54,    "gc.ps_marksweep.count" : 1,    "gc.ps_marksweep.time" : 44,    "httpsessions.max" : -1,    "httpsessions.active" : 0,    "counter.status.200.root" : 1,    "gauge.response.root" : 37.0}

为了收集自定义指标,我们支持“指标”,即数据的单值快照和“计数器”,即递增/递减指标。

让我们在/ metrics端点中实现我们自己的自定义指标。例如,我们将自定义登录流程以记录成功和失败的登录尝试:

@Service
public class LoginServiceImpl {
 
    private final CounterService counterService;
     
    public LoginServiceImpl(CounterService counterService) {
        this.counterService = counterService;
    }
     
    public boolean login(String userName, char[] password) {
        boolean success;
        if (userName.equals("admin") && "secret".toCharArray().equals(password)) {
            counterService.increment("counter.login.success");
            success = true;
        }
        else {
            counterService.increment("counter.login.failure");
            success = false;
        }
        return success;
    }
}

输出:

{
    ...
    "counter.login.success" : 105,
    "counter.login.failure" : 12,
    ...
}

3.6。创建新端点

除了使用Spring Boot提供的现有端点之外,我们还可以创建一个全新的端点。

首先,我们需要让新端点实现Endpoint <T>接口:

@Component
public class CustomEndpoint implements Endpoint<List<String>> {
     
    @Override
    public String getId() {
        return "customEndpoint";
    }
 
    @Override
    public boolean isEnabled() {
        return true;
    }
 
    @Override
    public boolean isSensitive() {
        return true;
    }
 
    @Override
    public List<String> invoke() {
        // Custom logic to build the output
        List<String> messages = new ArrayList<String>();
        messages.add("This is message 1");
        messages.add("This is message 2");
        return messages;
    }
}

为了访问这个新端点,它的id用于映射它,即我们可以运行它命中/ customEndpoint

输出:

[ "This is message 1", "This is message 2" ]

3.7。进一步定制

出于安全考虑,我们可能会选择通过非标准端口公开执行器端点 - 可以轻松地使用management.port属性来配置它。

另外,正如我们已经提到的,在1.x. Actuator基于Spring Security配置自己的安全模型,但独立于应用程序的其余部分。 因此,我们可以更改management.address属性以限制可以通过网络访问端点的位置:

#port used to expose actuator
management.port=8081 
 
#CIDR allowed to hit actuator
management.address=127.0.0.1 
 
#Whether security should be enabled or disabled altogether
management.security.enabled=false

此外,除/ info之外的所有内置端点默认都是敏感的。如果应用程序使用的是Spring Security,我们可以通过在application.properties文件中定义默认安全属性(用户名,密码和角色)来保护这些端点:

security.user.name=admin
security.user.password=secret
management.security.role=SUPERUSER

4Spring Boot 2.x执行器

2.x执行器保持其基本意图,但简化其模型,扩展其功能并包含更好的默认值。

首先,这个版本变得技术无关。此外,它通过将其与应用程序合并来简化其安全模型。

最后,在各种变化中,重要的是要记住其中一些变化正在破碎。这包括HTTP请求/响应以及Java API。

此外,最新版本现在支持CRUD模型,而不是旧的RW(读/写)模型。

4.1。技术支持

凭借其第二个主要版本,Actuator现在与技术无关,而在1.x中,它与MVC相关联,因此与Servlet API相关联。

在2.x中,Actuator定义了它的模型,可插拔和可扩展,而不依赖于MVC。

因此,通过这个新模型,我们可以利用MVC和WebFlux作为底层Web技术。

此外,可以通过实施正确的适配器来添加即将到来的技术。

最后,JMX仍然支持在没有任何其他代码的情况下公开端点。

4.2。重要变化

与以前的版本不同,Actuator禁用了大多数端点。

因此,默认情况下只有两个可用/ health/ info

我们是否想要启用所有这些,我们可以设置management.endpoints.web.exposure.include = *。或者,我们可以列出应该启用的端点。

Actuator现在与常规App安全规则共享安全配置。因此,安全模型被大大简化。

因此,要调整Actuator安全规则,我们可以为/ actuator / **添加一个条目:

@Bean
public SecurityWebFilterChain securityWebFilterChain(
  ServerHttpSecurity http) {
    return http.authorizeExchange()
      .pathMatchers("/actuator/**").permitAll()
      .anyExchange().authenticated()
      .and().build();
}

我们可以找到有关全新Actuator官方文档的更多详细信息。

此外,默认情况下,所有执行器端点现在都位于/执行器路径下

与前一版本相同,我们可以使用新属性management.endpoints.web.base-path调整此路径。

4.3。预定义的端点

我们来看看一些可用的端点,其中大部分已经在1.x中可用。

尽管如此,已添加了一些端点,一些已删除,一些已重组:

  • / auditevents -列出与安全审计相关的事件,例如用户登录/注销。此外,我们可以按主要或类型等字段进行过滤
  • / beans -在我们的BeanFactory中使用所有可用的bean 。与/ auditevents不同,它不支持过滤
  • / conditions -以前称为/ autoconfig,构建有关自动配置的条件报告
  • / configprops -允许我们获取所有@ConfigurationProperties bean
  • / env -返回当前环境属性。此外,我们可以检索单个属性
  • / flyway -提供有关我们的Flyway数据库迁移的详细信息
  • / health -总结了我们的应用程序的健康状态
  • / heapdump -从我们的应用程序使用的JVM构建并返回堆转储
  • / info -返回一般信息。它可能是自定义数据,构建信息或有关最新提交的详细信息
  • / liquibase - b ehaves like / flyway但是对于Liquibase
  • / logfile -返回普通的应用程序日志
  • / loggers -使我们能够查询和修改应用程序的日志记录级别
  • / metrics -详细说明我们的应用程序的指标。这可能包括通用指标和自定义指标
  • / prometheus -返回与前一个相同的指标,但格式化为与Prometheus服务器一起使用
  • / scheduledtasks -提供有关应用程序中每个计划任务的详细信息
  • / sessions -列出我们正在使用Spring Session的HTTP会话
  • / shutdown -正常关闭应用程序
  • / threaddump -转储底层JVM的线程信息

4.4。健康指标

与以前的版本一样,我们可以轻松添加自定义指标。与其他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());
    }
}

健康指标的一个便利功能是我们可以将它们聚合为层次结构的一部分。因此,按照前面的示例,我们可以将所有下游服务分组到下游服务类别下。只要每个嵌套服务都可以访问,此类别就是健康的。

复合运行状况检查通过CompositeHealthIndicator存在于1.x中此外,在2.x中,我们可以将CompositeReactiveHealthIndicator用于其反应对应物。

与Spring Boot 1.x不同,端点。<ID>。敏感标志已被删除。要隐藏完整的健康报告,我们可以利用新的management.endpoint.health.show-详细信息。默认情况下,此标志为false。

4.5。Spring Boot 2中的度量标准

在Spring Boot 2.0中,内部指标被Micrometer支持取代。因此,我们可以期待突破性变化。如果我们的应用程序使用GaugeService或CounterService等度量服务,它们将不再可用。

相反,我们希望直接与Micrometer交互。在Spring Boot 2.0中,我们将为我们自动配置一个MeterRegistry类型的bean 。

此外,Micrometer现在是Actuator依赖的一部分。因此,只要Actuator依赖项在类路径中,我们就应该好好去。

此外,我们将从/ metrics端点获得一个全新的响应

{
  "names": [
    "jvm.gc.pause",
    "jvm.buffer.memory.used",
    "jvm.memory.used",
    "jvm.buffer.count",
    // ...
  ]
}

正如我们在前面的例子中所观察到的那样,我们在1.x中没有实际的指标。

要获取特定指标的实际值,我们现在可以导航到所需的指标,即/actuator/metrics/jvm.gc.pause并获得详细响应

{
  "name": "jvm.gc.pause",
  "measurements": [
    {
      "statistic": "Count",
      "value": 3.0
    },
    {
      "statistic": "TotalTime",
      "value": 7.9E7
    },
    {
      "statistic": "Max",
      "value": 7.9E7
    }
  ],
  "availableTags": [
    {
      "tag": "cause",
      "values": [
        "Metadata GC Threshold",
        "Allocation Failure"
      ]
    },
    {
      "tag": "action",
      "values": [
        "end of minor GC",
        "end of major GC"
      ]
    }
  ]
}

我们可以看到,现在的指标要彻底得多。不仅包括不同的值,还包括一些相关的元数据。

4.6。自定义/ info端点

/信息端点保持不变。和以前一样,我们可以使用Maven或Gradle各自的依赖项添加git细节:

<dependency>
    <groupId>pl.project13.maven</groupId>
    <artifactId>git-commit-id-plugin</artifactId>
</dependency>

同样,我们还可以使用Maven或Gradle插件包含构建信息,包括名称,组和版本:

<plugin>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-maven-plugin</artifactId>
    <executions>
        <execution>
            <goals>
                <goal>build-info</goal>
            </goals>
        </execution>
    </executions>
</plugin>

4.7。创建自定义端点

正如我们之前指出的,我们可以创建自定义端点。但是,Spring Boot 2重新设计了实现此目的的方式,以支持新技术无关的范例。

让我们创建一个Actuator端点来查询,启用和禁用我们应用程序中的功能标志:

@Component
@Endpoint(id = "features")
public class FeaturesEndpoint {
 
    private Map<String, Feature> features = new ConcurrentHashMap<>();
 
    @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 {
        private Boolean enabled;
 
        // [...] getters and setters 
    }
 
}

要获得端点,我们需要一个bean。在我们的示例中,我们正在使用@Component。另外,我们需要用@Endpoint来装饰这个bean 。

我们的端点的路径由@Endpointid参数决定,在我们的例子中,它将请求路由到/ actuator / features。

准备好之后,我们可以开始使用以下命

  • @ReadOperation -它将映射到HTTP GET
  • @WriteOperation - 它将映射到HTTP POST
  • @DeleteOperation - 它将映射到HTTP DELETE

当我们在应用程序中使用前一个端点运行应用程序时,Spring Boot将注册它。

验证这一点的一种快速方法是检查日志:

[...].WebFluxEndpointHandlerMapping: Mapped "{[/actuator/features/{name}],
  methods=[GET],
  produces=[application/vnd.spring-boot.actuator.v2+json || application/json]}"
[...].WebFluxEndpointHandlerMapping : Mapped "{[/actuator/features],
  methods=[GET],
  produces=[application/vnd.spring-boot.actuator.v2+json || application/json]}"
[...].WebFluxEndpointHandlerMapping : Mapped "{[/actuator/features/{name}],
  methods=[POST],
  consumes=[application/vnd.spring-boot.actuator.v2+json || application/json]}"
[...].WebFluxEndpointHandlerMapping : Mapped "{[/actuator/features/{name}],
  methods=[DELETE]}"[...]

在之前的日志中,我们可以看到WebFlux如何公开我们的新端点。我们是否会切换到MVC,它只需委托该技术而无需更改任何代码。

此外,我们还有一些重要的考虑因素要记住这种新方法:

  • MVC没有依赖关系
  • 作为方法之前存在的所有元数据(敏感,启用...)不再存在。但是,我们可以使用@Endpoint启用或禁用端点(id =“features”,enableByDefault = false)
  • 与1.x不同,不再需要扩展给定的接口
  • 与旧的Read / Write模型相比,现在我们可以使用@DeleteOperation定义DELETE操作

4.8。扩展现有端点

让我们假设我们想要确保我们的应用程序的生产实例永远不是SNAPSHOT版本。我们决定通过更改返回此信息的Actuator端点的HTTP状态代码(即/ info)来完成此操作。如果我们的应用程序恰好是SNAPSHOT。我们将获得不同的HTTP状态代码。

我们可以使用@EndpointExtension注释或其更具体的特化@EndpointWebExtension@EndpointJmxExtension 轻松扩展预定义端点的行为

@Component
@EndpointWebExtension(endpoint = InfoEndpoint.class)
public class InfoWebEndpointExtension {
 
    private InfoEndpoint delegate;
 
    // standard constructor
 
    @ReadOperation
    public WebEndpointResponse<Map> info() {
        Map<String, Object> info = this.delegate.info();
        Integer status = getStatus(info);
        return new WebEndpointResponse<>(info, status);
    }
 
    private Integer getStatus(Map<String, Object> info) {
        // return 5xx if this is a snapshot
        return 200;
    }
}

4.9。启用所有端点

为了使用HTTP访问执行器端点,我们需要启用和公开它们。默认情况下,启用所有端点但/ shutdown。只有 /健康/信息端点默认情况下暴露出来。

我们需要添加以下配置来公开所有端点:

management.endpoints.web.exposure.include=*

要显式启用特定端点(例如 / shutdown), 我们使用:

management.endpoint.shutdown.enabled=true

要公开除一个以外的所有已启用端点(例如/ loggers),我们使用:

management.endpoints.web.exposure.include=*
management.endpoints.web.exposure.exclude=loggers

5总结

在本文中,我们讨论了Spring Boot Actuator。我们开始定义Actuator的含义以及它对我们的作用。

接下来,我们专注于当前Spring Boot版本的Actuator,1.x。讨论如何使用它,调整它的延伸。

然后,我们在Spring Boot 2中讨论了Actuator。我们专注于什么是新的,我们利用WebFlux来暴露我们的端点。

此外,我们讨论了在这个新迭代中我们可以找到的重要安全性变化。我们讨论了一些流行的端点以及它们如何发生变化。

最后,我们演示了如何定制和扩展Actuator。

本文分享自微信公众号 - 转行程序员(be_coder),作者:转行程序员

原文出处及转载信息见文内详细说明,如有侵权,请联系 yunjia_community@tencent.com 删除。

原始发表时间:2019-06-26

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

我来说两句

0 条评论
登录 后参与评论

相关文章

  • Spring Boot 从入门到实践系列教程(4)- Spring Boot Starters简介

    正文之前先同步一个关于找工作小故事,最近一周帮我以前一个同事推荐工作,顺便了解下行情,我这个同事我感觉还行,技术不说有多好,但是往年绝对不至于简历筛选时被刷掉那...

    王炸
  • Spring Boot 从入门到实践系列教程(1)- 课程目录

    王炸
  • Spring Boot 从入门到实践系列教程(3)- Spring注解

    在本快速教程中,我们将探讨org.springframework.boot.autoconfigure和org.springframework.boot.aut...

    王炸
  • GitHub遭攻击!黑客给出十天限期:不交比特币赎金,就公开用户私有代码

    就在五一假期的最后一天,一些程序员查看自己托管到GitHub上的代码时发现,他们的源代码和Repo都已消失不见,取而代之的是黑客留下的一封勒索信!

    量子位
  • 优秀程序员共有的7种优秀编程习惯

    编程是一个很有趣、容易的事情,但是编写好的程序可能是一项艰巨的任务。在大多数情况下,我们发现自己绞尽脑汁,试图了解我们撰写的意大利面条代码,或者是因为新添加的次...

    奋斗蒙
  • 程序员的大本营被黑客攻击了!10天内不交赎金,就公开用户私有代码

    就在五一假期的最后一天,一些程序员查看自己托管到GitHub上的代码时发现,他们的源代码和Repo都已消失不见,取而代之的是黑客留下的一封勒索信!

    iOSSir
  • 优秀程序员共有的7种优秀编程习惯

    永远记住,你不只是为机器编写代码,而且还为未来的自己编写代码。所以编写可读代码很重要。事实上,编程就像写一首好诗。音调应该是一致的,单词描述性和句子结构良好。

    用户2196435
  • GitHub遭攻击!黑客给出十天限期:不交比特币赎金,就公开用户私有代码

    就在五一假期的最后一天,一些程序员查看自己托管到GitHub上的代码时发现,他们的源代码和Repo都已消失不见,取而代之的是黑客留下的一封勒索信!

    周三不加班
  • 穿越十年后看互联网+:家电行业的金矿在哪里?

    现在市场上炒得火热的智能家居未来出路在何方?做智能家居的创业者应该注意哪些机会?传统家电厂商又到底如何借助互联网进行转型?本文以智能空调为例,用故事的形式,提前...

    华章科技
  • 响铃:员工匿名评价雇主的脉脉,给职场文化带来了哪些改变?

    微信称霸社交甚至移动互联网的年代,从来没有人想到过,一款基于弱关系的职场社交软件可以如此快速地从小众走向现象级。伴随着“商业社交”转型的成功,脉脉的线下广告正在...

    曾响铃

扫码关注云+社区

领取腾讯云代金券