Spring Boot 官网文档简单翻译 Part V

Part V. Spring Boot Actuator: Production-ready features

文档说明:

  • 文档对应的版本为 2.1.0.M3
  • 这不是文档的完整中文翻译,也有可能跟原文文字不一一对应,只是我阅读文档时候做的简单笔记
  • 如果对应的章节没有任何中文,有可能是文档内容比较少,建议直接看原文,或者是我不感兴趣的部分
  • 目录标题没有做翻译,首先标题一般一眼就能看懂什么意思,不做翻译还能保证原文意思,其次也方便对应到原文位置

Spring Boot 很多特性来帮助你监控和管理应用。当发布到生产,你可以选择通过 HTTP endpoints 或者 JMX 来管理和监控你的应用。安全审计,健康检查和统计收集在你的应用都可以使用。

51. Enabling Production-ready Features

spring-boot-actuator 模块提供了所有 Spring Boot’s production-ready features。

Actuator 的定义:它是行业术语,指的是一个用来移动和控制某些东西的机械设备。

添加 starter

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

52. Endpoints

Actuator endpoints 让你的监控和应用做交互。Spring Boot 提供了很多内建的 endpoints,并允许你创建自己的 endpoints。例如 health endpoints 提供了应用的基本健康信息。

每个 endpoint 都可以设置启动或者禁用。为了可以远程访问,endpoint 可以通过 JMX 或者 HTTP 暴露接口出来。大部分应用都选择了 HTTP,endpoint 的 ID 都会带有 /actuator 前缀。例如 health endpoint 的映射就是 /actuator/health。

technology-agnostic endpoints table

Spring Boot Actuator Web API Documentation

52.1 Enabling Endpoints

默除了 shutdown 之外的所有 endpoints 默认都会启用,可通过 management.endpoint.<id>.enabled 属性来配置,例如启用 shutdow endpoints

management.endpoint.shutdown.enabled=true

如果只想启用某几个 endpoints,可以先禁用所有的 endpoints,再单独启用指定的 endpoints,例如只启用 info endpoint:

management.endpoints.enabled-by-default=false
management.endpoint.info.enabled=true

52.2 Exposing Endpoints

endpoints 可能包含敏感信息,所以暴露对应的接口时需小心谨慎。

the default exposure for the built-in endpoints table

通过 include 和 exclude 的属性可以配置 endpoints 的接口是否暴露出来,还可以支持通配符

management.endpoints.web.exposure.include=*
management.endpoints.web.exposure.exclude=env,beans

52.3 Securing HTTP Endpoints

如果你只允许某种角色的用户才可以访问 endpoints,可通过 Spring Security 来实现。例如:

@Configuration
public class ActuatorSecurity extends WebSecurityConfigurerAdapter {
    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http.requestMatcher(EndpointRequest.toAnyEndpoint()).authorizeRequests()
            .anyRequest().hasRole("ENDPOINT_ADMIN")
            .and()
            .httpBasic();
    }
}

上面例子通过 EndpointRequest.toAnyEndpoint() 来匹配所有的 endpoints 的请求。

如果你部署的应用有防火墙控制,那么可以不在应用做安全控制。

52.4 Configuring Endpoints

Endpoints 会自动缓存那些不需要任何参数的读操作请求的响应内容,我们可以配置它的缓存有效时间

management.endpoint.beans.cache.time-to-live=10s

如果是带有认证信息的 HTTP 请求,认证信息会认为是输入参数,所以所有响应内容都不会缓存。

52.5 Hypermedia for Actuator Web Endpoints

增加了 "discovery page" 来连接到所有的 endpoints,一般是 /actuator

52.6 CORS Support

跨域默认是不启用的,配置项如下:

management.endpoints.web.cors.allowed-origins=http://example.com
management.endpoints.web.cors.allowed-methods=GET,POST

52.7 Implementing Custom Endpoints

52.7.1 Receiving Input

52.7.2 Custom Web Endpoints

@Endpoint, @WebEndpoint, @EndpointWebExtension 都会通过 HTTP 自动被开放出来接口,HHTP 服务可以是 Jersey,Spring MVC 或者 Spring WebFlux。

Web Endpoint Request Predicates

为 Web 暴露的 endpoints 上的每个操作会自动生成请求谓词。

Path

The default base path is /actuator.
/actuator/endpoint_id
可通过 @Selector 来定制

HTTP method

Operation HTTP method
@ReadOperation GET
@WriteOperation POST
@DeleteOperation DELETE

Consumes

@WriteOperation ==> application/vnd.spring-boot.actuator.v2+json, application/json
others ==> empty

Produces

Web Endpoint Response Status

@ReadOperation: 200 / 404
@WriteOperation / @DeleteOperation: 200 / 204

Web Endpoint Range Requests

An HTTP range request can be used to request part of an HTTP resource.

Web Endpoint Security

52.7.3 Servlet endpoints

一个 Servlet 可以通过 @ServletEndpoint 来实现 endpoint。

52.7.4 Controller endpoints

@ControllerEndpoint and @RestControllerEndpoint

52.8 Health Information

配置项 management.endpoint.health.show-details 控制了 /health endpoint 可以展示的信息,这个配置项的值可以是 never / when-authorized / always。

应用健康信息是从 HealthIndicatorRegistry 类(默认所有的 HealthIndicator 实例都会注册到 ApplicationContex)收集的。

52.8.1 Auto-configured HealthIndicators

自动装配的 HealthIndicators 有:

  • CassandraHealthIndicator
  • DiskSpaceHealthIndicator
  • DataSourceHealthIndicator
  • ElasticsearchHealthIndicator
  • InfluxDbHealthIndicator
  • JmsHealthIndicator
  • MailHealthIndicator
  • MongoHealthIndicator
  • Neo4jHealthIndicator
  • RabbitHealthIndicator
  • RedisHealthIndicator
  • SolrHealthIndicator

可通过 management.health.defaults.enabled 配置项来禁用

52.8.2 Writing Custom HealthIndicators

实现 HealthIndicator 接口

import org.springframework.boot.actuate.health.Health;
import org.springframework.boot.actuate.health.HealthIndicator;
import org.springframework.stereotype.Component;
@Component
public class MyHealthIndicator 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();
    }
}

HealthIndicator 的 ID 属性是根据 bean 的名称然后减去 "HealthIndicator" 后缀,上面例子的 bean 名称为 myHealthIndicator,所以其 ID 值为 my。

添加自定义的状态类型。
例如添加新的状态类型 FATAL

management.health.status.order=FATAL, DOWN, OUT_OF_SERVICE, UNKNOWN, UP
management.health.status.http-mapping.FATAL=503

HTTP 状态码可以映射到这节讨论的状态类型,更多信息可参看 HealthStatusHttpMapper 类。

52.8.3 Reactive Health Indicators

实现 ReactiveHealthIndicator 接口

@Component
public class MyReactiveHealthIndicator implements ReactiveHealthIndicator {
    @Override
    public Mono<Health> health() {
        //perform some specific health check that returns a Mono<Health>
        return doHealthCheck() 
            .onErrorResume(ex -> Mono.just(new Health.Builder().down(ex).build())));
    }
}

抽象类 AbstractReactiveHealthIndicator 提供了处理错误的默认实现。

52.8.4 Auto-configured ReactiveHealthIndicators

自动装配的 ReactiveHealthIndicators 有:

  • CassandraReactiveHealthIndicator
  • MongoReactiveHealthIndicator
  • RedisReactiveHealthIndicator

52.9 Application Information

应用信息是从所有注入到 ApplicationContex 的 InfoContributor bean 收集的,你也可以实现自己的 InfoContributor。

52.9.1 Auto-configured InfoContributors

自动装配的 InfoContributors 有:

  • EnvironmentInfoContributor
  • GitInfoContributor
  • BuildInfoContributor
    通过 management.info.defaults.enabled 配置项可禁用

52.9.2 Custom Application Information

通过 info.* 配置项可以定制 info endpoint 展示的信息:

info.app.encoding=UTF-8
info.app.java.source=1.8
info.app.java.target=1.8

52.9.3 Git Commit Information

info endpoint 还可以展示你 git 代码的状态信息。
GitProperties

52.9.4 Build Information

BuildProperties 和 META-INF/build-info.properties

52.9.5 Writing Custom InfoContributors

实现 InfoContributor 接口

import java.util.Collections;
import org.springframework.boot.actuate.info.Info;
import org.springframework.boot.actuate.info.InfoContributor;
import org.springframework.stereotype.Component;
@Component
public class ExampleInfoContributor implements InfoContributor {
    @Override
    public void contribute(Info.Builder builder) {
        builder.withDetail("example",
        Collections.singletonMap("key", "value"));
    }
}

53. Monitoring and Management over HTTP

53.1 Customizing the Management Endpoint Paths

/actuator/{id} ==> /manage/{id}

management.endpoints.web.base-path=/manage

/actuator/health ==> /healthcheck

management.endpoints.web.base-path=/
management.endpoints.web.path-mapping.health=healthcheck

53.2 Customizing the Management Server Port

management.server.port=8081

53.3 Configuring Management-specific SSL

配置了自定义的端口,Management 服务还可以被配置成自己的 SSL,通过 management.server.ssl.* 属性。

server.port=8443
server.ssl.enabled=true
server.ssl.key-store=classpath:store.jks
server.ssl.key-password=secret
management.server.port=8080
management.server.ssl.enabled=false

53.4 Customizing the Management Server Address

如果想配置允许 localhost 的请求:

management.server.port=8081
management.server.address=127.0.0.1

53.5 Disabling HTTP Endpoints

management.server.port=-1
# or 
management.endpoints.web.exposure.exclude=*

54. Monitoring and Management over JMX

54.1 Customizing MBean Names

MBean 的名称通常是由 endpoint 的 id 来生成的,例如 health endpoint 的的接口为

org.springframework.boot:type=Endpoint,name=Health

如果你的应用包含多个 ApplicationContex,MBean 的名称可能会有冲突的场景。设置 spring.jmx.unique-names 属性为 true 可以应用这种场景。
还可以配置 JMX 的 domain

spring.jmx.unique-names=true
management.endpoints.jmx.domain=com.example.myapp

54.2 Disabling JMX Endpoints

management.endpoints.jmx.exposure.exclude=*

54.3 Using Jolokia for JMX over HTTP

Online: Jolokia 是一个用来访问远程 JMX MBeans 的崭新方法,与 JSR-160 连接器不同的是,它使用基于 HTTP 的 JSON 格式作为通讯协议,提供 JMX 批量操作等。

添加对应依赖

<dependency>
    <groupId>org.jolokia</groupId>
    <artifactId>jolokia-core</artifactId>
</dependency>

Customizing Jolokia

配置项: management.endpoint.jolokia.config.*

Disabling Jolokia

management.endpoint.jolokia.enabled=false

55. Loggers

Spring Boot Actuator 有查看和配置你应用在运行时的日志级别的能力。日记级别有:

  • TRACE
  • DEBUG
  • INFO
  • WARN
  • ERROR
  • FATAL
  • OFF
  • null
    null 表明没有显示的配置。

55.1 Configure a Logger

POST 一个请求来配置日记级别:

{
    "configuredLevel": "DEBUG"
}

重置日记级别可以 POST null 值过去。

56. Metrics

Spring Boot Actuator 提供了 Micrometer 的依赖管理和自动装配,Micrometer 是支持大量监控系统的应用监控门面,包括:

  • Atlas
  • Datadog
  • Ganglia
  • Graphite
  • Influx
  • JMX
  • New Relic
  • Prometheus
  • SignalFx
  • Simple (in-memory)

56.1 Getting started

禁用一个指定的 registry,例如禁用 Datadog:

# 禁用一个指定的 registry
management.metrics.export.datadog.enabled=false

# 禁用所有 registry 的自动装配
management.metrics.use-global-registry=false

56.2 Supported monitoring systems

56.2.1 Atlas

Metrics 默认使用 Atlas 来运行,配置 Atlas 服务地址:

management.metrics.export.atlas.uri=http://atlas.example.com:7101/api/v1/publish

56.2.2 Datadog

Datadog registry 会定时推送数据到 datadoghq,需要显示配置 Datadog 的 API key

management.metrics.export.datadog.api-key=YOUR_KEY

# 修改推送时间的间隔
management.metrics.export.datadog.step=30s

56.2.3 Ganglia

By default, metrics are exported to Ganglia running on your local machine.

management.metrics.export.ganglia.host=ganglia.example.com
management.metrics.export.ganglia.port=9649

56.2.4 Graphite

By default, metrics are exported to Graphite running on your local machine.

management.metrics.export.graphite.host=graphite.example.com
management.metrics.export.graphite.port=9004

56.2.5 Influx

By default, Influx are exported to Graphite running on your local machine.

management.metrics.export.influx.uri=http://influx.example.com:8086

56.2.6 JMX

Micrometer 对 JMX 提供了分层级的映射。

management.metrics.export.jmx.domain=com.example.app.metrics

HierarchicalNameMapper 类

56.2.7 New Relic

New Relic registry pushes metrics to New Relic periodically.

management.metrics.export.newrelic.api-key=YOUR_KEY
management.metrics.export.newrelic.account-id=YOUR_ACCOUNT_ID
management.metrics.export.newrelic.step=30s

56.2.8 Prometheus

56.2.9 SignalFx

SignalFx registry pushes metrics to SignalFx periodically.

management.metrics.export.signalfx.access-token=YOUR_ACCESS_TOKEN
management.metrics.export.signalfx.step=30s

56.2.10 Simple

56.2.11 StatsD

56.2.12 Wavefront

56.3 Supported Metrics

Spring Boot 会记录下面的指标:

  • JVM metrics, report utilization of:
  • Various memory and buffer pools
  • Statistics related to garbage collection
  • Threads utilization
  • Number of classes loaded/unloaded
  • CPU metrics
  • File descriptor metrics
  • Logback metrics: record the number of events logged to Logback at each level
  • Uptime metrics: report a gauge for uptime and a fixed gauge representing the application’s absolute start time
  • Tomcat metrics
  • Spring Integration metrics

56.3.1 Spring MVC Metrics

management.metrics.web.server.auto-time-requests=true

如果为 false,可添加 @Timed 注解

@RestController
@Timed (1)
public class MyController {
    @GetMapping("/api/people")
    @Timed(extraTags = { "region", "us-east-1" }) (2)
    @Timed(value = "all.people", longTask = true) (3)
    public List<Person> listPeople() { ... }
}

(1). 该 controller 的所有方法都启用 timings
(2). 单独对某个方法启用 timings
(3). 对某个方法启用 longTask 的 timer

Spring MVC 默认可以记录的信息有:

  • method:GET or POST
  • uri: such as /api/person/{id}
  • status: the response’s HTTP status code
  • exception:

56.3.2 Spring WebFlux Metrics

和 Spring MVC Metrics 内容很相似

56.3.3 HTTP Client Metrics

Spring Boot Actuator 会记录 RestTemplate 和 WebClient 的行为。

记录的信息有:

  • method:GET or POST
  • uri: such as /api/person/{id}
  • status: the response’s HTTP status code
  • clientName: the host portion of the URI

56.3.4 Cache Metrics

56.3.5 DataSource Metrics

会记录连接池的当前数量,最大值和最小值。

56.3.6 Hibernate Metrics

56.3.7 RabbitMQ Metrics

56.4 Registering custom metrics

在你的组件注入 MeterRegistry

class Dictionary {

    private final List<String> words = new CopyOnWriteArrayList<>();
    
    Dictionary(MeterRegistry registry) {
        registry.gaugeCollectionSize("dictionary.size", Tags.empty(), this.words);
    }
    
    // …
}

56.5 Customizing individual metrics

56.5.1 Common tags

56.5.2 Per-meter properties

56.6 Metrics endpoint

/actuator/metrics 列出了所有可用的指标名称。你可以选择某个指标深入查看,例如 /actuator/metrics/jvm.memory.max 。
还可以在 URL 后面添加任意数量的 tag=KEY:VALUE 查询参数,例如 /actuator/metrics/jvm.memory.max?tag=area:nonheap 。

57. Auditing

实现 AbstractAuthenticationAuditListener 和 AbstractAuthorizationAuditListener 接口来定制自己的安全事件。

你还可以在自己的业务事件使用审计服务,直接在你的组件注入 AuditEventRepository,或者通过 ApplicationEventPublisher 来发布一个 AuditApplicationEvent。

58. HTTP Tracing

Tracing 对于所有 HTTP 请求都是自动启用的,你可以查看 httptrace endpoint 获得关于最近 100 次请求和响应的信息。

58.1 Custom HTTP tracing

添加 trace 的内容的配置项:HttpExchangeTracer
或者注册你自己的 HttpExchangeTracer 实现。

InMemoryHttpTraceRepository 存储了最近 100 次的请求和响应信息,如要实现存储更多的请求信息,可通过实现自己的 HttpTraceRepository 来替换。

59. Process Monitoring

在 spring-boot 模块,你可以找到有两个类会创建一些监控进程监控的文件:

  • ApplicationPidFileWriter: 在应用目录创建 application.pid,记录了应用的 PID。
  • WebServerPortFileWriter: 在应用目录创建一个或多个 application.port 文件,记录了应用在使用的端口号。
    这两个特性默认是没有启用的。

59.1 Extending Configuration

启用记录进程监控信息文件的特性,在 META-INF/spring.factories 添加配置:

org.springframework.context.ApplicationListener=org.springframework.boot.context.ApplicationPidFileWriter,org.springframework.boot.web.context.WebServerPortFileWriter

59.2 Programmatically

通过 SpringApplication.addListeners(…) 亦可实现。

60. Cloud Foundry Support

Spring Boot Actuator 还提供了关于云平台的支持,/cloudfoundryapplication 提供了一个可安全访问所有 @Endpoint bean 的路由。

访问 /cloudfoundryapplication 需要携带一个有效的 UAA token。

60.1 Disabling Extended Cloud Foundry Actuator Support

application.properties

management.cloudfoundry.enabled=false

60.2 Cloud Foundry Self-signed Certificates

/cloudfoundryapplication endpoints 的安全认证默认都是通过 SSL,如果你使用 self-signed 的证书,需要如下配置:

management.cloudfoundry.skip-ssl-validation=true

60.3 Custom context path

如果 server.servlet.context-path=/app,那么你的 Cloud Foundry endpoints 就是 /app/cloudfoundryapplication/*。
如果你希望 Cloud Foundry endpoints 不受服务器的 context-path 影响,需要显示添加一些配置。例如下面 Tomcat 的例子:

@Bean
public TomcatServletWebServerFactory servletWebServerFactory() {
    return new TomcatServletWebServerFactory() {

        @Override
        protected void prepareContext(Host host,
                ServletContextInitializer[] initializers) {
            super.prepareContext(host, initializers);
            StandardContext child = new StandardContext();
            child.addLifecycleListener(new Tomcat.FixContextListener());
            child.setPath("/cloudfoundryapplication");
            ServletContainerInitializer initializer = getServletContextInitializer(
                    getContextPath());
            child.addServletContainerInitializer(initializer, Collections.emptySet());
            child.setCrossContext(true);
            host.addChild(child);
        }

    };
}

private ServletContainerInitializer getServletContextInitializer(String contextPath) {
    return (c, context) -> {
        Servlet servlet = new GenericServlet() {

            @Override
            public void service(ServletRequest req, ServletResponse res)
                    throws ServletException, IOException {
                ServletContext context = req.getServletContext()
                        .getContext(contextPath);
                context.getRequestDispatcher("/cloudfoundryapplication").forward(req,
                        res);
            }

        };
        context.addServlet("cloudfoundry", servlet).addMapping("/*");
    };
}

61. What to Read Next

推荐阅读更多精彩内容