Spring Boot Actuator官方参考文档(2.5.0)翻译(完结)
背景
乔梁大神曾经在他的《持续交付2.0》一书的第5.1.1节:《持续交付架构要求》中明确指出:为了提升交付速度,获得持续交付能力,系统架构在设计时应该考虑如下因素。
(1)为测试而设计(design for test)。如果我们每次写好代码以后,需要花费很大的精力,做很多的准备工作才能对它进行测试的话,那么从写好代码到完成质量验证就需要很长周期,当然无法快速发布。
(2)为部署而设计(design for development)。如果我们开发完新功能,当部署发布是,需要花费很长时间准备,甚至需要停机才能部署,当然就无法快速发布。
(3)为监控而设计(design for monitor)。如果我们的功能上线以后,无法对齐进行监控,除了问题只能通过用户反馈才发现。那么,持续交付的收益就会大幅降低了。
(4)为扩展而设计(design for scale)。这里的扩展性指两个方面,意识支持团队成员规模的扩展,而是支持系统自身的扩展。
(5)为失效而设计(design for failure)。俗话说:“常在河边走,哪能不湿鞋。”快速地部署发布总会遇到问题。因此,在开发软件功能之前,就应该考虑的一个问题是:一旦部署或发布失败,如何优雅且快速地处理。
在这5个设计原则中,为为监控而设计(design for monitor)属于游戏(服务器)开发中最容易被轻视甚至是忽视的原则之一,而在gamedo.core的开发设计过程中,译者本人也一直在思考如何实现系统监控的最佳实践,直到最近算是确定了技术栈,那就是站在巨人的肩上,使用Spring Boot Actuator和MicroMeter。
正是由于gamedo.core最终要选用Spring Boot Actuator作为系统监控的关键技术,因此需要其进行相对深入的研究,这也是本笔记的产生的原因。而本文的所有内容都源于阅读参考文档(Spring Boot版本:2.5.0)以及阅读源码时的随读、随想和随写,为了便于以后查找,章节也完全和参考文档保持一致,并且由于某些章节比较简单,所以就被忽略掉,这可能导致本文的章节不是连续的。
启用产品就绪特性(Enabling Production-ready Features)
Spring Boot的所有产品就绪特性是都是由 spring-boot-actuator
模块提供的,开启该特性的最佳方式就是引入专有的Starter
,也即:spring-boot-starter-actuator
执行器的定义 执行器(actuator)是一个制造业术语,是指用于移动或控制某些物体的机械设备。可以通过执行器的微小变化带来巨大的变化。
对于使用Maven构建的项目,可以添加如下Starter
依赖:
1 | <dependencies> |
对于使用Gradle的项目,使用如下配置:
1 | dependencies { |
端点(Endpoints)
通过端点可以监控应用程序,和应用程序交互。Spring Boot内置了一堆端点,用户也可以自行添加。比如health
端点,它可以提供应用的基本健康信息。
每一个端点都可以被开启、禁用,也可以通过HTTP或JMX的方式暴露给外部。当端点同时开启且被暴露时,它才是可用的。内置的端点也只有在可用状态下才会被Spring Boot自动装配。大多数应用都选择HTTP的方式。端点的ID以及固定前缀/actuator
组合成访问该端点的URL。例如对于health
端点,其访问方式为:/actuator/health
spring-boot-actuator
内置了一大堆开箱即用的端点,详情参考源文档。此外,当应用程序是一个Web应用(Spring MVC、Spring WebFlux或者Jersey),如下内置的额外端点:
端点ID | 描述 |
---|---|
heapdump |
返回一个hprof 堆转储文件,需要HotSpot虚拟机支持 |
jolokia |
通过HTTP暴露JMX bean(需要Jolokia在classpath内,且不适用于WebFlux),需要增加jolokia-core 依赖 |
logfile |
返回日志文件的内容(如果logging.file.name或logging.file.path属性被设置),并且支持使用HTTP Range 头检索部分日志文件的内容 |
prometheus |
将metrics暴露成可以被Prometheus服务器抓取的格式,需要添加micrometer-registry-prometheus 依赖 |
译者提示
- 对于任意端点来说,可以对其进行两种操作:1、开启或关闭端点;2、通过HTTP或者JMX暴露(exposed)它。当某个端点被开启且被暴露时该端点才处于可用状态。而系统内置端点只有在可用时才会被自动装配。
- 产品就绪特性属于Spring Boot的六大特性之一,详情可以参考官方文档Features一节
- 自动装配属于Spring Boot的六大特性之一,简单来说,自动装配就是:如果检测到用户需要某个组件(例如发现引入了某个组件类库),并且用户还没有进行配置,那就启用内部自动装配逻辑,帮用户配置好。例如,如果用户引入了
spring-boot-starter-logging
,接下来不需要进行一大堆的日志配置,直接记录日志。这个术语会在本文档中多次提及。- 端点(Endpoints)和指标(metrics)是本文最重要的两个概念,占据了本文的大部分篇幅。端点的概念不难理解,属于Spring Boot Actuator的核心功能,从系统内部代码层面讲,就是一个个内置的自动装配的以及用户自定义的端点 bean,从外部用户角度讲,就是一个个可以访问的数据集合窗口(可以通过jmx或http)。而指标有时候指的就是众多端点中的
metrics
端点,有时候指的是metrics
端点下的被Spring Boot使用micrometer采集到的指标。理解了这些,实际上就理解整篇文章的精髓。
开启端点(Enabling Endpoints)
默认情况下,除了shutdown
端点,其他所有端点默认处于开启状态。如果要开关某个端点,可以配置:management.endpoint.<端点id>.enabled
,例如开启shutdown
端点的配置为:
1 | management: |
如果希望所有端点默认都是关闭状态,可以将management.endpoints.enabled-by-default
配置为false
,然后将某端点的enabled
属性配置为true
来单独开启。以info
端点举例(只开启info
端点,其他端点都关闭):
1 | management: |
提示
当某个端点被关闭后,对应的端点bean会从Spring容器(application context)中移除。如果仅仅是不想让某个端点被暴露,可以使用include和exclude属性。
暴露端点(Exposing Endpoints)
因为端点可能会包含敏感信息,因此在决定暴露端点前需要仔细考虑。下表展示了内置端点的默认暴露状态(简而言之:JMX下默认全开,HTTP下只有health
开启):
ID | JMX | Web |
---|---|---|
auditevents |
Yes | No |
beans |
Yes | No |
caches |
Yes | No |
conditions |
Yes | No |
configprops |
Yes | No |
env |
Yes | No |
flyway |
Yes | No |
health |
Yes | Yes |
heapdump |
N/A | No |
httptrace |
Yes | No |
info |
Yes | No |
integrationgraph |
Yes | No |
jolokia |
N/A | No |
logfile |
N/A | No |
loggers |
Yes | No |
liquibase |
Yes | No |
metrics |
Yes | No |
mappings |
Yes | No |
prometheus |
N/A | No |
quartz |
Yes | No |
scheduledtasks |
Yes | No |
sessions |
Yes | No |
shutdown |
Yes | No |
startup |
Yes | No |
threaddump |
Yes | No |
如果想调整某个端点的暴露状态,可以使用如下include
和exclude
属性:
属性 | 默认值 |
---|---|
management.endpoints.jmx.exposure.exclude |
|
management.endpoints.jmx.exposure.include |
* |
management.endpoints.web.exposure.exclude |
|
management.endpoints.web.exposure.include |
health |
include
属性列出的是需要开启暴露的端点的id集合,而exclude
属性列出的是关闭暴露的端点的id集合。exclude
的优先级高于include
,且这两个属性都可以配置为一个以端点ID列表。
例如,如果只想通过JMX暴露health
和info
端点,而禁止暴露其他端点,可以使用如下配置:
1 | management: |
*
代表所有端点。例如,如果想通过HTTP的方式暴露除了env
和beans
之外的所有端点,可以使用如下配置:
1 | management: |
提示
*
在YAML中具有特殊含义,因此在include
和exclude
中使用时需要添加双引号- 如果应用程序暴露在外网环境中,强烈建议加固HTTP端点
- 如果想自定义端点的暴露策略,可以注册一个
EndpointFilter
bean
加固HTTP端点(Securing HTTP Endpoints)
信息敏感的URL需要进行安全加固,而对于HTTP方式的端点也应该得到相同待遇的处理。如果使用了Spring Security,端点默认会被Spring Security
的内容协商策略(content-negotiation strategy)加固,例如只允许具有某种角色(role)的用户访问。Spring Boot提供了一些方便使用的RequestMatcher
对象,可以配合Spring Security
使用。
典型的Spring Security
配置如下所示:
1 |
|
上面的例子中,EndpointRequest.toAnyEndpoint()
用来匹配任意端点,然后还会确保用户拥有ENDPOINT_ADMIN
角色。EndpointRequest
中还有其他类似的匹配函数。可以查看API文档(HTML或PDF)获得更多详情。
如果应用程序部署在防火墙后面,可以允许所有端点被访问而无需进行鉴权。此时可以将management.endpoints.web.exposure.include
配置为***
**,如下所示:
1 | management: |
此外,如果使用了Spring Security
,并且想允许未经过身份验证的访问,还需要一些自定义配置,例如:
1 |
|
提示
以上两个例子中的配置仅对端点请求生效。而对于
Spring Boot
来说,当存在用户自定义的SecurityFilterChain
bean时,其安全配置就会自动失效。因此需要配置额外的SecurityFilterChain
来适配应用程序的其他请求
配置端点(Configuring Endpoints)
对于端点中不包含参数的读操作(read operations)请求,端点会自动缓存响应数据(response),如果要修改某端点的缓存时间,可以配置cache.time-to-live
属性,如下配置就是将beans
端点的缓存时间改成10秒:
1 | management: |
提示
management.endpoint.<name>
前缀用于标识要配置的端点
Hypermedia for Actuator Web Endpoints
跨域资源共享支持(CORS Support)
跨域资源共享(CORS)是一个W3C规范,可以协助制定灵活的跨域访问授权策略。如果你在使用Spring MVC或者Spring WebFlux,Web端点可以支持支持中场景。
CORS默认是被关闭的,并且只有management.endpoints.web.cors.allowed-origins
被配置后才会开启,下面配置允许来自于example.com
的GET
和POST
请求:
1 | management: |
提示
到 CorsEndpointProperties查看完整的属性列表
实现自定义端点(Implementing Custom Endpoints)
如果一个@Bean
被@Endpoint
注解,那么任意被注解了@ReadOperation
、@WriteOperation
或者@DeleteOperation
的方法都以JMX方式暴露,而对于Web应用程序,则会以HTTP的方式暴露。当使用Jersey、Spring MVC或者Spring WebFlux时,端点可以通过HTTP暴露。当Jersey和Spring MVC都可用时,Spring MVC优先被使用。
以下例子暴露一个读操作(read operation),该操作返回了一个自定义对象
1 |
|
可以使用@JmxEndpoint
或@WebEndpoint
注解来开启特定方式的端点(JMX或者Web)。
可以使用@EndpointWebExtension
或@EndpointJmxExtension
,这两个注解可以对特定方式的端点进行增强(JMX或者Web)
笔者提示
对于注解了
@Endpoint
的@Bean
,由于既可以通过JMX方式暴露,又可以通过HTTP的方式暴露(后文称这种端点为原生端点)。为了兼容性的需要,不得不放弃某些技术特性。因此Spring设计了@EndpointWebExtension
或@EndpointJmxExtension
(从Spring Boot 2.2.0开始,还增加了@EndpointCloudFoundryExtension
注解),这些注解的作用对原生端点进行技术特级别的扩展。例如对于以HTTP方式暴露的某个端点,可以为响应数据(Response)增加一个状态码(而JMX方式就不需要这个状态码),那么就可以使用@EndpointWebExtension
对原生端点进行二次加工,示例可以参考源码中EnvironmentEndpointWebExtension
的实现
最后,如果需要使用web框架相关的功能,可以实现Servlet
或者使用Spring @Controller
、@RestController
端点,不过代价是通过JMX方式暴露就不可用,并且当使用其他web框架时也不可用。
入参处理(Receiving Input)
通过参数的方式,端点的操作(Operations)来接收输入。当通过web暴露时,这些参数来自于请求的查询参数或者请求body中的JSON对象。当通过JMX暴露时,这些参数从MBean映射而来。默认情况下,参数是必须输入的。不过可以通过添加注解@javax.annotation.Nullable
或@org.springframework.lang.Nullable
使之成为可选参数。
对于web请求body中JSON对象,每个属性值都可以被映射为端点的一个参数,例如请求body中的json结构为:
1 | { |
那么可以开发这么一个包含String name
和int counter
参数的端点与之对应,例如:
1 |
|
提示
- 由于原生端点的兼容性需要,因此端点的入参只能是基本类型,因此不支持将
name
和counter
封装到CustomData
。- 如果想要将输入参数映射到函数的参数上,当编译Java代码时,需要使用
-parameters
参数,而对于Kotlin代码,则需要使用-java-parameters
,如果在Gradle中使用了Spring Boot的插件或者在Maven中使用了spring-boot-starter-parent
这个参数已经被自动开启。(关于-parameters
的更多细节,可以参考StackOverflow的这个解答)
输入类型转换
在必要的情况下,传给端点的参数会被自动转换为端点的参数类型。在调用端点的操作函数(operation method)之前,通过JMX或HTTP请求的参数通过ApplicationConversionService
对象和任意被@EndpointConverter
注解标识的Converter
或GenericConverter
转换。
自定义Web端点(Custom Web Endpoints)
被@Endpoint
、@WebEndpoint
或@EndpointWebExtension
注解的端点会自动通过Jersey、Spring MVC或Spring WebFlux以HTTP的方式暴露。而如果Jersey和Spring MVC都可用,那么Spring MVC会被启用。
Web端点请求谓词(Web Endpoint Request Predicates)
对于每个HTTP端点的任意操作(operation),都会自动生成一个HTTP请求谓词
路径(Path)
请求谓词的路径取决于端点的ID和根路径(指的是以web方式暴露的根路径),默认的根路径是/actuator
。例如,sessions
端点的谓词路径就是/actuator/sessions
可以通过在端点的函数入参上增加@Selector
注解实现路径的自定义解析。这些解析后的请求参数会被以路径变量的方式加入到请求谓词中。当端点的函数被调用时,这些路径变量会被当做入参传入。如果想捕获完整路径上所有剩余元素(每个被“/”分割的字符串都是一个元素),可以在最后一个函数入参上使用@Selector(Match=ALL_REMAINING)
注解,这会把所有的元素转换为String[]
数组。
HTTP方法(HTTP method)
请求谓词中的HTTP方法取决于操作类型,如下表所示:
操作类型 | HTTP方法 |
---|---|
@ReadOperation |
GET |
@WriteOperation |
POST |
@DeleteOperation |
DELETE |
请求媒体类型(Consumes)
对于HTTP POST方式的@WriteOperation
,其请求(Request)的媒体类型(Content-Type)为application/vnd.spring-boot.actuator.v2+json, application/json
,而其他操作类型则为空。
响应媒体类型(Produces)
响应(Response)的媒体类型由@DeleteOperation
、@ReadOperation
和@WriteOperation
注解内的produces
属性决定。这个属性是可选的,如果没有配置,那么媒体类型会被自动设置。
如果操作函数的返回值是void
或者Void
,那么媒体类型为空。如果返回一个org.springframework.core.io.Resource
,那么媒体类型类型为application/octet-stream
(也即二进制流数据)。而其他的所有的操作,媒体类型都是application/vnd.spring-boot.actuator.v2+json, application/json
。
Web端点的响应状态码(Web Endpoint Response Status)
默认的响应状态码取决于操作类型(@DeleteOperation
、@ReadOperation
和@WriteOperation
)和返回值(如果有返回值的话)。
如果一个
@ReadOperation
返回了一个值,那么状态码是200(OK)。否则的话,状态码是404(Not Found)。如果一个
@WriteOpertion
或@DeleteOperation
返回了一个值,那么状态码是200(OK)。否则的话,状态码是204(No Cpmtemt)。如果一个操作被调用了而没有传入必须的参数,或者说参数没有被正确转换,那么操作函数将不会被调用,返回一个400(Bad Request)状态码
Web端点范围请求(Web Endpoint Range Requests)
可以使用HTTP范围请求来获取HTTP资源。当使用Spring MVC或Spring WebFlux时,如果某个操作返回了org.springframework.core.io.Resource
,那么范围请求会被自动支持。
提示
Jersey不支持范围请求
Web端点安全(Web Endpoint Security)
对于web方式的端点或者web相关的端点扩展(web-specific endpoint extension),它们都可以接收java.security.Principal
或 org.springframework.boot.actuate.endpoint.SecurityContext
作为操作函数的参数。前者通常配合@Nullable
使用,为经过身份验证和未经过身份验证的用户提供不同的行为。而后者通常使用isUserInRole(Sring)
进行权限检查
Servlet端点(Servlet Endpoints)
当同时满足如下两个条件后,就可以实现一个Servlet端点:
- 实现一个
Supplier<EndpointServlet>
类 - 同时该类上增加
@ServletEndpoint
注解
Servlet端点可以和Servlet容器更深层地集成,但是牺牲了可移植性。这种方式的应用场景就是可以将已有的Servlet转化为端点。而对于新的端点,仍然尽量使用@Endpoint
或@WebEndpoint
Controller端点(Controller Endpoints)
@ControllerEndpoint
和@RestControllerEndpoint
端点只可以在Spring MVC和Spring WebFlux下使用。当使用Spring MVC或Spring WebFlux的标准注解,例如@RequestMapping
和@GetMapping
时,端点的操作方法都可以被正常映射,并且以端点的ID作为请求路径(path)的前缀。Controller端点提供了和Srping web框架更深的集成度,然而牺牲了可移植性。因此,尽量优先使用@Endpoint
或@WebEndpoint
端点。
健康信息(Health Information)
可以通过健康信息检查应用程序的运行状态。健康信息通常被用来监控应用,并且在系统宕机时进行报警。health
端点暴露的信息详情取决于management.endpoint.health.show-details
和management.endpoint.health.show-components
属性的配置,可以配置的值如下所示:
配置值 | 描述 |
---|---|
never (默认值) |
详情不可见 |
when-authorized |
详情仅对授权用户可见。授权用户可以通过management.endpoint.health.roles 配置 |
always |
详情对所有用户可见 |
当一个用户拥有一个或多个端点角色(endpoint’s roles)时,他被认为是授权的。如果某个端点没有配置角色(这是默认状态),那么所有通过身份认证的用户都任务是被授权的。可以通过management.endpoint.health.roles
配置角色。
提示
如果已经对应用程序进行安全控制( secured your application),而想使用
always
配置,那么需要对安全配置进行设置,是的所有经过身份认证和未经过身份认证的用户都获得访问权限
健康信息是 HealthContributorRegistry
中收集所有健康数据的集合。默认情况下,这些健康数据是Spring上下文(ApplicationContext
)中一个个HealthContributor
实例,Spring Boot已经自动装配了很多HealthContributors
,用户也可以自己实现。
HealthContributor
既可以是一个HealthIndicator
也可以是一个CompositeHealthContributor
,前者提供了实际的健康数据,并包含一个Status
,后者提供了和其他HealthIndicator
组合的能力。最终,所有这些HealthContributor
形成了一个树状结构,来展示整个系统的健康状态。
默认情况下,系统的最终健康状态由Statusaggregator
计算获得。Statusaggregator
的实现类SimpleStatusAggregator
的实现算法:
- 内部维护了一个健康状态的有序列表,排序为:
DOWN
、OUT_OF_SERVICE
、UP
、UNKNOWN
- 对于外部传入的状态集合,首先过滤掉不识别的状态码(也即只保留这4个状态码)
- 算出每个状态在有序列表中的索引,并取出索引值最小的状态,作为最终状态(实际上就是跟进有序列表的顺序进行排序)
- 如果剩下的集合是空的,那么返还一个
UNKNOWN
状态(这种情形只发生所有传入的状态都不属于这4种状态的情况下)
提示
HealthContributorRegistry
可以在运行状态下动态注册和反注册
自动装配的HealthIndicators(Auto-configured HealthIndicators)
Spring Boot已经自动装配了很多HealthIndicator
,可以通过management.health.<key>.enabled
将其开启或关闭
提示
- 详细的
HealthIndicator
列表不再赘述,详情参考源文档- 可以通过设置
management.health.defaults.enabled
关闭所有的HealthIndicator
以下HealthIndicator
也是可用的,但是默认情况下没有被启用:
Key | 名字 | 描述 |
---|---|---|
livenessstate |
LivenessStateHealthIndicator |
暴露应用程序的活性 状态 |
readinessstate |
ReadinessStateHealthIndicator |
暴露应用程序的就绪 状态 |
笔者提示
- 关于
活性
状态,Spring Boot在源码中有详细的解释:当应用程序的内部状态是正确的(CORRECT),那么它被认为是存活的。而失活
状态意味着应用程序内部状态已经出现严重异常(BROKEN)而且无法正常恢复,只能通过重启应用解决该异常。相应地,活性状态有两个状态,分别为:CORRECT
和BROKEN
。- 关于
就绪
状态,Spring Boot在源码中也有详细的解释:当应用程序处于存活(也即活性状态为CORRECT)状态且可以接受流量时,被认为是就绪的(ACCEPTING_TRAFFIC)。而当应用程序无法接受流量时意味着就绪失败(REFUSING_TRAFFIC),基础设施必须停止对其路由。相应地,就行状态也包含两种:ACCEPTING_TRAFFIC
和REFUSING_TRAFFIC
(也就是说就绪状态更倾向于一个web术语)
自定义HealthIndicators(Writing Custom HealthIndicators)
可以通过注册 HealthIndicator
接口的Bean实现自定义的监控数据。该接口类需要实现health()
方法并且返回一个Health
类。该返回值必须包含一个状态,并且可选择性地包含详细信息以供显示。以下代码展示了一个HealthIndicator
实现:
1 |
|
提示
HealthIndicator
接口类的名字去掉HealthIndicator
后缀(如果存在的话)会作为Bean的名字,上述实例中,这个自定义HealthIndicator
的名字是my。
除了Srping Boot内置的Status
之外,返回的Health
内也可以使用自定义的状态。在这种情况下,需要实现一个自定义的StatusAggregator
,或者对management.endpoint.health.status.order
属性进行配置,来替代默认的状态配置。
例如,假如在某个HealthIndicator
内返回了一个自定义状态:FATAL
,为了配置优先级,需要增加如下配置:
1 | management: |
HTTP的响应状态码反映了系统的整体监控状态。默认情况下,OUT_OF_SERVICE
和DOWN
的状态码是503。所有没有配置映射的健康状态(包括UP
),其状态码为200。如果对自定义健康状态的状态码进行了配置,那么DOWN
和OUT_OF_SERVICE
的默认状态码会被禁用。如果仍然想保留这些配置,需要和自定义的状态一起进行显式地定义。下面的例子中,将FATAL
映射为503(service unavailable),并且保留了DOWN
和OUT_OF_SERVICE
的原有的配置
1 | management: |
提示
如果想要更多控制权,可以实现一个自定义的
HttpCodeStatusMapper
Bean
以下表格展示了内置状态的默认映射配置:
状态 | |
---|---|
DOWN |
SERVICE_UNAVAILABLE (503 ) |
OUT_OF_SERVICE |
SERVICE_UNAVAILABLE (503 ) |
UP |
默认没有映射,所以状态码是200 |
UNKNOWN |
默认没有映射,所以状态码是200 |
响应式健康指示器(Reactive Health Indicators)
对于响应式的应用,例如使用了Spring WebFlux,ReactiveHealthContributor
提供了非阻塞的契约来获得应用的健康信息。和传统的HealthContributor
很类似,其健康信息收集自ReactiveHealthContributorRegistry
(默认情况下,所有的 HealthContributor
和ReactiveHealthContributor
实例都在ApplicationContext
中)。在弹性调度器下(elastic scheduler),常规的HealthContributors
并不会调用响应式的API。
提示
在响应式应用中,
ReactiveHealthContributorRegistry
应该在运行时状态下注册或反注册健康指示器(health indicators),如果想注册常规的HealthContributor
,需要使用ReactiveHealthContributor#adapt
对其包装。
如果想通过响应式API提供自定义健康指示器(health indicators),可以注册实现了ReactiveHealthIndicator
接口的Bean到Spring容器中,以下代码展示了一个ReactiveHealthIndicator
的实现
1 |
|
提示
如果想自动处理异常错误,可以继承
AbstractReactiveHealthIndicator
自动装配的ReactiveHealthIndicators(Auto-configured ReactiveHealthIndicators)
Spring提供了一些内置的响应式健康指示器(ReactiveHealthIndicators
),当它们可以可用时(端点被开启且被正常暴露时即为可用),会被自动装配。详情参考源文档第2.8.4节的表格,此处不再赘述
提示
在必要的情况下,响应式的指示器会替代非响应式的指示器。并且任何没有被处理过的
HealthIndicator
也会被自动包装为响应式
健康分组(Health Groups)
处于某些原因,将健康指示器进行分组是很有用的。
可以创建management.endpoint.health.group.<name>
属性来创建一个健康分组。并且使用include
和exclude
属性来配置指示器ID。例如,假如想创建一个仅仅包含数据库指示器的分支,可以配置如下:
1 | management: |
然后可以通过链接:localhost:8080/actuator/health/custom访问该分组
同理,如果想创建一个不包含数据库指示器的分组,可以配置如下:
1 | management: |
默认情况下,如同系统的健康信息一样,分组沿用了相同的StatusAggregator
和HttpCodeStatusMapper
设置。不过这些设置可以在每个分组上单独定义。如果有需要的话,还可以覆盖show-details
和roles
的配置,例如:
1 | management: |
提示
如果想将自定义的
StatusAggregator
和HttpCodeStatusMapper
Bean注册到某个分组上,可以使用注解@Qualifier("groupname")
对其进行限定
数据源健康(DataSource Health)
DataSource
健康指示器用来展示标准数据源(standard data source)类型和路由数据源(routing data source)类型的Bean的健康信息。路由数据源的健康信息也包含了目标数据源(its target data sources)的健康信息。在监控信息端点的HTTP响应中,每一个路由数据源的目标数据源的名字,由路由键值(routing key)来决定。如果想把路由数据源排除,可以将management.health.db.ignore-routing-data-sources
设置为true
Kubernetes探针(Kubernetes Probes)
部署在Kubernetes上的应用程序可以通过容器探针反馈内部状态信息。kubelet可以根据Kubernetes的配置调用这些探针并反馈探针结果。
Spring Boot提供了开箱即用的应用程序可用性状态管理。当应用程序被部署到Kubernetes环境下,Spring Boot Acuator会通过ApplicationAvailability
接口收集“Liveness”和“Readiness”信息,并且在健康指示器:LivenessStateHealthIndicator
和ReadinessStateHealthIndicator
中使用这些信息。这些指示器的信息显示在全局端点("/actuator/health"
)中。也可用通过使用健康分组:"/actuator/health/liveness"
和 "/actuator/health/readiness"
访问这些端点。
可以使用如下端点信息配置Kubernetes:
1 | livenessProbe: |
提示
<actuator-port>
应该被配置为一个可以被访问的端口号。可以将其配置为web服务器的端口,或者通过management.endpoint.health.probes.enabled
配置,使用独立的端口
这些健康分组只有在应用程序运行在Kubernetes环境下时才会自动生效。当然,也可以通过配置management.endpoint.health.probes.enabled
来开启这些功能。
提示
如果应用程序的启动时间比liveness指示器所反映的时间要长,Kubernetes提供了一个
“startupProbe”
探针作为替代方案。不过“startupProbe”
探针并不一定必须配置,因为在所有的启动任务完成之前"readinessProbe"
探针都处于失败状态。可以查看探针在应用程序生命周期中的行为
警告
如果端点(Actuator endpoints)被配置在独立的Spring上下文(a separate management context)中,需要注意的是,这些端点使用的web配置信息(端口、连接池、框架的组件等)也是独立于应用程序的。在这种情况下,即使应用程序已经无法正常工作(例如无法接受新连接),探针可能也会返回正常状态。
使用Kubernetes探针检测外部状态(Checking External State with Kubernetes Probes)
Spring Boot Actuator将“活性”(liveness)和“就绪”(readiness)探针配置为健康分组。这意味着对于这些探针来说,所有的健康分组特性都适用。例如,可以配置如下健康指示器:
1 | management: |
默认情况下,Spring Boot没有将其他的健康指示器添加到这些健康分组中。
“活性”(liveness)探针的健康检测不应该依赖于外部系统(笔者注:例如mongoDB、Redis等),如果应用程序的活性状态处于当宕机状态,Kubernetes会尝试重新启动应用程序来解决这个问题。也就是说如果外部系统出现异常(例如数据库、Web API或外部缓存),那么Kubernetes会重启所有的应用程序,这会导致级联故障(笔者注:雪崩效应)
而对于“就绪”探针来说,开发人员必须谨慎处理外部系统的检测结果。比如Srping Boot就没有包含任何额外的健康检查。如果应用程序的就绪状态处于未就绪(unready)状态,Kubernetes就不会将流量路由到该应用。那么把这些状态加入到“就绪”探针的探测中是理应该的。某些外部系统可能不是应用程序的关键依赖(比如应用程序已经部署了熔断或者降级策略),在这种情况下,这些外部系统就绝不应该被包含到“就绪”探针中。不妙的是,外部系统都是作为通用模块被应用程序所依赖的,这就需要做一个抉择:将其加入到“就绪”探针,当外部系统发生故障时,让应用程序也停止服务(out of service);或者将这些外部系统排除在外,在外部系统发生故障时,从更高层级上处理这些故障,比如使用断路器。(Unfortunately, an external system that is shared by all application instances is common, and you have to make a judgement call: include it in the readiness probe and expect that the application is taken out of service when the external service is down, or leave it out and deal with failures higher up the stack, e.g. using a circuit breaker in the caller.)
提示
If all instances of an application are unready, a Kubernetes Service with
type=ClusterIP
orNodePort
will not accept any incoming connections. There is no HTTP error response (503 etc.) since there is no connection. A Service withtype=LoadBalancer
might or might not accept connections, depending on the provider. A Service that has an explicit Ingress will also respond in a way that depends on the implementation - the ingress service itself will have to decide how to handle the “connection refused” from downstream. HTTP 503 is quite likely in the case of both load balancer and ingress.
此外,如果应用程序使用了Kubernetes的自动伸缩(autoscaling)机制,对于负载均衡后面的程序,探针的表现可能会不同,这要取决于自动伸缩的配置。
应用程序生命周期和探针状态(Application Lifecycle and Probe States)
Kubernetes探针所支持的重要一点就是保持了和应用程序生命周期的一致性。应用程序内存中的内部状态:AvailabilityState
和探针实际上返回的状态可能会有巨大的差异:在生命周期的某些阶段,探针可能是不可用状态。
当应用启动和关闭时,Sprin Boot会发布事件,探针可以监听这些事件,并且暴露AvailabilityState
信息。
下面表格展示了在不同阶段下,AvailabilityState
和HTTP服务器的状态,当Spring Boot应用程序启动时:
启动阶段 | 活性状态 | 就绪状态 | HTTP服务器 | 备注 |
---|---|---|---|---|
Starting | BROKEN |
REFUSING_TRAFFIC |
未启动 | Kubernetes检查“活性”探针,如果耗时过长,就重启应用程序。 |
Started | CORRECT |
REFUSING_TRAFFIC |
拒绝连接 | 应用程序上下文已经刷新,应用程序执行启动任务并且还不能接收流量 |
Ready | CORRECT |
ACCEPTING_TRAFFIC |
接受连接 | 启动任务已经执行完毕,应用程序可以接收流量 |
当Spring Boot应用程序关闭时:
关闭阶段 | 活性状态 | 就绪状态 | HTTP服务器 | 备注 |
---|---|---|---|---|
Running | CORRECT |
ACCEPTING_TRAFFIC |
接受连接 | (此时)已经接受关闭请求 |
Graceful shutdown | CORRECT |
REFUSING_TRAFFIC |
不接受新连接 | 如果启用该特性,将会根据请求优雅地关闭进程 |
Shutdown complete | N/A | N/A | 服务器关闭 | 应用程序上下文被关闭并且应用也被关闭 |
提示
查看 Kubernetes容器生命周期查看关于Kubernetes部署更多的细节
应用程序信息(Application Information)
应用程序信息可以暴露ApplicationContext
内所有的InfoContributor
Bean收集到的信息。Spring Boot内置了很多自动装配的InfoContributor
Bean,并且用户也可以编写自定义的Bean
自动装配InfoContributors(Auto-configured InfoContributors)
在适当的情况下,如下InfoContributor
类型的Bean会被自动装配:
名称 | 描述 |
---|---|
EnvironmentInfoContributor |
暴露Environment 内所有info 开头的属性(笔者注:例如配置在application.yaml内的info.name: myApp ) |
GitInfoContributor |
如果git.properties 文件存,则暴露git相关信息 |
BuildInfoContributor |
如果META-INF/build-info.properties 文件存在,则暴露构建相关信息 |
提示
可以通过配置
management.info.defaults.enabled
关闭上述任意端点
自定义应用程序信息(Custom Application Information)
可以通过在Spring配置文件中设置info.*
配置暴露自定义的数据。所有的Environment
属性下info
开头的键值都会被自动暴露。例如,可以在application.properties
下增加如下配置:
1 | info.app.encoding=UTF-8 |
提示
除了上述硬编码,还可以在构建期间生成属性值
以Maven为例,可以将上述配置重写为:
1
2
3 info.app.encoding=@project.build.sourceEncoding@
info.app.java.source=@java.version@
info.app.java.target=@java.version@
Git提交信息(Git Commit Information)
另外一个有用的info
端点是展示源码所在的git仓库的提交信息。当GitProperties
Bean存在时,这些信息就可以在info
端点下暴露出来。
提示
如果classpath根路径下面存在一个
git.properties
文件,GitProperties
Bean会被自动装配,可以通过“生成git信息”获得更多细节
默认情况下,在属性存在的前提下,端点会暴露出git.branch
、git.commit.id
和git.commit.time
。如果想关闭任意属性,需要在git.properties
中排除掉。如果想展示完整的git信息(也就是说git.properties文件的所有内容),可以配置management.info.git.mode
属性,如下所示:
1 | management: |
如果想从info
端点关闭git提交信息,可以通过将management.info.git.enabled
属性设置为false,如下所示:
1 | management: |
构建信息(Build Information)
如果BuildProperties
Bean存在,还可以暴露构建信息,并且当classpath下存在META-INF/build-info.properties
文件时生效。
提示
Maven和Gradle插件都可以生成
META-INF/build-info.properties
文件,可以通过“Generate build information”或多更多细节
自定义InfoContributors
(Writing Custom InfoContributors)
可以通过注册继承了 InfoContributor
接口的Bean实现自定义的应用信息。如下所示:
1 |
|
如果访问info
端点,将会看到如下的额外信息:
1 | { |
通过HTTP进行监控与管理(Monitoring and Management over HTTP)
如果你正在开发一个Web应用程序,Srping Boot Actuator会自动装配所有已经开启(enabled)的端点,使通过HTTP暴露。默认规则是通过端点的id
附加一个/actuator
前缀作为URL路径。例如,health
端点的路径为/actuator/health
。
提示
自定义端点路径(Customizing the Management Endpoint Paths)
某些情况下,自定义端点路径的前缀是很有必要的。比如,应用程序可能已经使用了/actuator
路径作为其他用途。可以设置management.endpoints.web.base-path
属性来调整端点的前缀,如下所示:
1 | management: |
这会将端点的URL从/actuator/{id}
改为/manage/{id}
(例如:/manage/info
)
提示
除非管理端口被配置为其他的的HTTP端口,否则
management.endpoints.web.base-path
的配置是相对于server.servlet.context-path
(Servlet web应用)或spring.webflux.base-path
(响应式web应用)的。如果management.server.port
被配置了,那么management.endpoints.web.base-path
是相对于management.server.base-path
的路径。
如果想将端点映射到其他路径,可以修改management.endpoints.web.path-mapping
属性,以下示例将/actuator/health
映射为/healthcheck
1 | management: |
自定义端口(Customizing the Management Server Port)
如果应用程序是基于云部署,那么使用默认的HTTP端口来暴露端点是一个明智的选择。不过,如果应用程序运行在自己内部的数据中心,可能会倾向于使用其他的HTTP端口。
可以通过设置management.server.port
属性调整HTTP端口,如下所示:
1 | management: |
提示
在Cloud Foundry上,默认情况下,应用程序只在端口8080上接收HTTP和TCP路由请求。如果想在Cloud Foundry上使用自定义的端口,你需要明确地设置应用程序的路由,将流量转发到自定义端口。
配置SSL(Configuring Management-specific SSL)
当使用了自定义端口之后,也可以通过management.server.ssl.*
属性配置独立的SSL。例如,可以让端点管理通过HTTP访问,而应用程序通过HTTPS访问,如下配置所示:
1 | server: |
又或者,端点管理和应用程序都通过SSL访问,但是使用不同的证书和秘钥(keystore),如下所示:
1 | server: |
自定义服务器地址
通过设置management.server.address
属性,可以自定义端点的访问地址。如果只想监听内部网络或运维内部网络(ops-facing network ),有或者只想监听来来自localhost的连接,这个设置就会很有用。
提示
只有当端点端口与应用程序端口不同时,才可以配置监听不同的地址。
如下配置不允许远程连接访问:
1 | management: |
禁用HTTP端点(Disabling HTTP Endpoints)
如果不想通过HTTP暴露端点,可以将端口设置为-1,例如:
1 | management: |
也可以通过设置management.endpoints.web.exposure.exclude
属性达到达到这个效果。如下配置所示:
1 | management: |
通过JMX进行监控和管理(Monitoring and Management over JMX)
JAVA管理扩展(JMX)提供了管理和监控应用程序的标准机制。这个特性默认没有被启用,可以通过设置spring.jmx.enabled
为true
来开启。默认情况下,Spring Boot的JMX MBeans位于org.springframework.boot
作用域下。要想完全控制JMX域下的端点,可以考虑实现EndpointObjectNameFactory
接口。
自定义MBean名字(Customizing MBean Names)
通常情况下,MBean的名字由端点的id
生成。例如,health
端点就被暴露为:org.springframework.boot:type=Endpoint,name=Health
。
如果应用程序拥有的ApplicationContext
不止一个的话,可能会发现名称冲突。若要解决该问题,可以设置属性spring.jmx.unique-names
为true
,这样的话,MBean的名字就是唯一的了。
可以自定义暴露端点的JMX作用域,如下例所示:
1 | spring: |
禁用JMX端点(Disabling JMX Endpoints)
如果不想通过JMX暴露端点,可以设置management.endpoints.jmx.exposure.exclude
属性为*
,如下所示:
1 | management: |
通过HTTP访问基于Jolokia的JMX端点(Using Jolokia for JMX over HTTP)
Jolokia作为一个JMX-HTTP桥接器提供了访问JMX bean的替代方案。如果想要使用Jolokia,需要添加依赖:org.jolokia:jolokia-core
。以Maven为例,配置如下所示:
1 | <dependency> |
可以通过添加jolokia
或*
到management.endpoints.web.exposure.include
属性中开启Jolokia端点。然后可以使用/actuator/jolokia
该端点。
提示
Jolokia端点将Jolokia的servlet暴露为actuator端点。这意味着它是特定于Spring MVC和Jersey等servlet环境的。并且该端点在WebFlux应用程序中不可用。
自定义Jolokia(Customizing Jolokia)
Jolokia包含许多设置,通常可以是通过设置servlet参数进行配置。而在Spring Boot下中,可以使用application.properties
。所有的Jolokia参数都以management.endpoint.jolokia.config
作为前缀,举例如下:
1 | management: |
禁用Jolokia(Disabling Jolokia)
当使用了Jolokia而又不想让Spring Boot对其进行配置,可以将management.endpoint.jolokia.enabled
设置为false
,如下所示:
1 | management: |
日志(Loggers)
Spring Boot Actuator具备查看和设置正在运行中的应用程序的日志等级的能力。可以查看完整日志列表或者单独某个日志的配置,这些配置由两部分组成:显式配置的日志等级和日志框架给定的有效日志等级。这些日志等级可以是如下任意一个:
TRACE
DEBUG
INFO
WARN
ERROR
FATAL
OFF
null
null
代表没有显示地配置日志
配置日志(Configure a Logger)
如果要配置一个日志,可以向资源URL POST
一个特定的请求体,如下所示:
1 | { |
提示
如果想重置之前设置的日志等级(并且使用默认配置),可以将
configuredLevel
设置为null
指标(Metrics)
Spring Boot Actuator提供了对 Micrometer的依赖管理和自动装配。Spring内部提供了指标门面(an application metrics facade)模式,该模式提供了对于众多监控系统的支持,包括:
- AppOptics
- Atlas
- Datadog
- Dynatrace
- Elastic
- Ganglia
- Graphite
- Humio
- Influx
- JMX
- KairosDB
- New Relic
- Prometheus
- SignalFx
- Simple (in-memory)
- Stackdriver
- StatsD
- Wavefront
提示
入门(Getting started)
Spring Boot自动装配了一个组合类型(composite)的指标注册表(MeterRegistry
),对于在classpath下发现的任何指标注册表(MeterRegistery
)的实现,Spring Boot会将其加入到这个组合类型的指标注册表中。实际上,在运行期(runtime)的classpath下增加micrometer-registry-{system}
(笔者注:此处的system可以替换成上述列表中的监控系统)依赖后,Spring Boot就会自动配置对应类型的注册表(registery)。
大多数注册表都有相同的特性。例如,即使(Micrometer的)注册表的实现类在classpath内,也可以将其禁用。例如,要禁用Datadog:
1 | management: |
也可以禁用所有注册表,除非某注册表已经通过自己的配置单独启用,如下例所示:
1 | management: |
Spring Boot将自动装配的注册器添加到Metrics
类(笔者注:全类限定名为:io.micrometer.core.instrument.Metrics
)的全局静态组合注册表中,触发显示禁用:
1 | management: |
可以注册任意数量的类型为MeterRegistryCustomizer
的bean,这些bean可以实现对注册表的自定义化配置,例如当任意指标注册到指标注册表中时,每个为这些指标增加通用的Tag标记:
1 |
|
也可以通过更具体的泛型类型的支实现对特定注册表的自定义化配置:
1 |
|
Spring Boot还内置的很多指标和仪表,可以通过配置文件或专用注解来控制这些指标。
支持的监控系统(Supported Monitoring Systems)
AppOptics
默认情况下,AppOptics注册表负责将指标周期性地推送到 api.appoptics.com/v1/measurements
。为了把指标推送到Saas AppOptics平台,需要在配置里提供API令牌(API token):
1 | management: |
Atlas
默认情况下, Atlas 指标暴露给本机正在运行的Atlas服务器。 Atlas服务器 的地址可以使用如下配置进行修改:
1 | management: |
Datadog
Datadog注册表负责周期性地将指标推送给datadoghq。为了把指标推送到 Datadog,需要在配置里提供API秘钥(API key):
1 | management: |
Dynatrace
Dynatrace注册表负责将指标周期性地推送给配置的URL。为了把指标推送到Dynatrace,需要提供API令牌(API token)、设备ID(device ID)以及URL:
1 | management: |
也可以修改推送指标到Dynatrace的间隔时间:
1 | management: |
Elastic
默认情况下,指标会被推送到本机运行的Elastic服务器上,而Elastic服务器的地址可以通过如下配置进行修改:
1 | management: |
Ganglia
默认情况下,指标会被推送到本机运行的Ganglia服务器上,Ganglia服务器的地址和端口可以通过如下配置进行修改:
1 | management: |
Graphite
默认情况下,指标会被推送到本机运行的 Graphite服务器上, Graphite服务器的地址和端口可以通过如下配置进行修改:
1 | management: |
Micrometer提供了一个默认的HierarchicalNameMapper
,用于管理如何在多维度的指标名称扁平化指标名称之间进行映射转换。
提示
如果想实现自定义的名称映射管理,需要自己实现
GraphiteMeterRegistry
并且提供自定义的HierarchicalNameMapper
,GraphiteConfig
和Clock
不需要自定义,它们会被Spring自动装配,除非用户已经自己定义。
1
2
3
4
5
6
7
8
9
10
11
12
public class MyGraphiteConfiguration {
public GraphiteMeterRegistry graphiteMeterRegistry(GraphiteConfig config, Clock clock) {
return new GraphiteMeterRegistry(config, clock, this::toHierarchicalName);
}
private String toHierarchicalName(Meter.Id id, NamingConvention convention) {
return ...
}
}
Humio
默认情况下,指标被周期性地推送到 cloud.humio.com,为了把指标推送到Saas Humio平台,需要提供API令牌(API token):
1 | management: |
也可以为每个要推送的指标配置一个或多个Tag标记,用来区分数据源:
1 | management: |
Influx
默认情况下,指标被推送(exported)给运行于本机的v1版本的 Influx,如果想把指标推送给InfluxDB v2,需要配置org
、bucket
和认证用的token
。 Influx服务器的地址可以通过如下配置进行修改:
1 | management: |
JMX
Micrometer提供了向JMX的层级映射,主要用来当做一种低成本且便携的本地查看指标的方式。默认情况下,指标被推送给JMX的metrics
作用域(domain),而作用域也可以通过如下配置进行修改:
1 | management: |
Micrometer提供了一个默认的HierarchicalNameMapper
,用于管理如何在多维度的指标名称扁平化指标名称之间进行映射转换。
提示
如果想实现自定义的名称映射管理,需要自己实现
JmxMeterRegistry
并且提供自定义的HierarchicalNameMapper
,JmxConfig
和Clock
不需要自定义,它们都被Spring自动装配,除非用户已经自己定义。
1
2
3
4
5
6
7
8
9
10
11
12
13 >
>public class MyJmxConfiguration {
public JmxMeterRegistry jmxMeterRegistry(JmxConfig config, Clock clock) {
return new JmxMeterRegistry(config, clock, this::toHierarchicalName);
}
private String toHierarchicalName(Meter.Id id, NamingConvention convention) {
return ...
}
>}
KairosDB
默认情况下,指标会被推送到本机运行的 KairosDB 服务器上, KairosDB 服务器的地址可以通过如下配置进行修改:
1 | management: |
New Relic
New Relic注册表负责周期性地将指标推送给New Relic。为了把指标推送到 New Relic,需要在配置里提供API秘钥(API key)和账号id(account id):
1 | management: |
也可以修改推送指标到New Relic的间隔时间:
1 | management: |
默认情况下,指标以REST的形式推送。也可以使用Java Agent API,如果响应的类库在classpath路径内的情况下:
1 | management: |
最后,也可以通过自定义实现NewRelicClientProvider
bean获得完全的控制权。
Prometheus
Prometheus获取指标的方式是向应用程序拉取或轮询的指标数据。Spring Boot提供了一个可用的端点/actuator/prometheus
,并以适当的方式提供给Prometheus指标采集器(Prometheus scrape)
提示
端点默认是禁用的,并且还需要开放暴露,可用查看暴露端点(Exposing Endpoints)获取更详细信息
以下是prometheus.yml
配置文件中的scrape_config
配置示例:
1 | scrape_configs: |
对于某些无法被拉取的短暂任务或批量任务, Prometheus的Pushgateway组件提供了将指标推送给Prometheus的方式。如果要启用Pushgateway的支持,需要增加如下依赖:
1 | <dependency> |
当Pushgateway 组件存在于classpath下,并且management.metrics.export.prometheus.pushgateway.enabled
被设置为true
时,Spring Boot会自动装配一个PrometheusPushGatewayManager
bean。这个bean就复杂将指标推送到Pushgateway
。
可以通过management.metrics.export.prometheus.pushgateway.
属性对PrometheusPushGatewayManager
进一步配置,当然,用户也可以自定义PrometheusPushGatewayManager
bean。
SignalFx
SignalFx注册表负责周期性地将指标推送给 SignalFx。为了把指标推送到 SignalFx,需要在配置里提供访问令牌(access token):
1 | management: |
也可以修改推送指标到SignalFx的间隔时间:
1 | management: |
Simple
Micrometer内置了一个简易的、在内存中的(in-memory)注册表。如果其他的注册表都没有被配置,它会将当做默认的指标监控系统。通过该系统,可以在指标端点中查看系统收集了哪些指标。
只要启用了其他任意监控系统,simple系统就会被自动禁用。当然也可以显式将其关闭:
1 | management: |
Stackdriver
Stackdriver注册表负责周期性地将指标推送给Stackdriver。为了把指标推送到SaaS Stackdriver平台,需要在配置里提供谷歌云的project id:
1 | management: |
也可以修改推送指标到Stackdriver的间隔时间:
1 | management: |
StatsD
StatsD注册表通过UDP将指标推送到StatsD代理。默认情况下,指标将被推送到本机运行的StatsD代理。StatsD代理的主机(host)、端口(port)和协议(协议)可以通过以下方式修改:
1 | management: |
也可以修改StatsD所使用的line协议(line protocol)(默认为Datadog):
1 | management: |
Wavefront
Wavefront注册表负责周期性地将指标推送给Wavefront。为了把指标推送到Wavefront,需要在配置里提供API令牌(API token):
1 | management: |
你可能会使用一个Wavefront边车代理(Wavefront sidecar)或设置一个内部代理,用于将指标数据转发到Wavefront API主机:
1 | management: |
指标
如果是将指标发布到Wavefront代理(如文档所述),主机的配置格式必须为:
proxy://HOST:PORT
也可以修改推送指标到Wavefront的间隔时间:
1 | management: |
支持的指标和仪表(Supported Metrics and Meters)
对于(系统使用的)各种的技术组件,Spring Boot都提供了指标自动注册。大多数情况下,这些开箱即用的指标注册表会选择适当的指标,并将其发布到任意所支持的监控系统上。
JVM指标(JVM Metrics)
自动装配机制会使用Micrometer的核心代码开启JVM指标。JVM指标被发布在jvm.
名称下。如下JVM指标都是支持的:
- 各种内存和缓冲池详细信息
- 垃圾收集相关统计
- 线程利用率
- 被加载/卸载的class数量
系统指标(System Metrics)
自动装配机制会使用Micrometer的核心代码开启系统指标。系统指标被发布在system.
和process.
名称下。如下系统指标都是支持的:
- CPU指标
- 文件指标(File descriptor metrics)
- 运行时间指标(包括系统的运行时间以及启动时的绝对时间)
日志指标(Logger Metrics)
自动装配机制支持Logback和Log4J2的日志事件。这些指标被发布在log4j2.events.
或logback.events.
下面。
Spring MVC指标( Spring MVC Metrics)
自动装配机制会开启对 Spring MVC控制器(Spring MVC controllers)和请求处理器(functional handlers)的所有请求的采集。默认情况下,指标的名称前缀为 http.server.requests
。可以通过设置 management.metrics.web.server.request.metric-name
来自定义该前缀。
@Controller
类和@RequestMapping
方法支持@Timed
注解(详情参考:[@Timed注解支持(@Timed Annotation Support)](##@Timed注解支持(@Timed Annotation Support)))。如果不想开启所有的Spring MVC请求,可以将management.metrics.web.server.request.autotime.enabled
设置为false
,而仅使用@Timed
注解。
默认情况下,Spring MVC相关的指标会被增加如下tag标记:
Tag | 详情 |
---|---|
exception |
当处理请求出现异常时,被抛出的异常类的简短类名 |
method |
请求方法(例如:GET 或POST ) |
outcome |
基于响应状态码的返回值描述,1xx:INFORMATIONAL ;2xx:SUCCESS ;3xx:REDIRECTION ;4xx:CLIENT_ERROR ;5xx:SERVER_ERROR |
status |
响应状态码(例如200 或500 ) |
url |
在变量替换之前使用请求的URI模板(例如,/api/person/{id} ) |
如果想添加默认的tag标记,可以提供一个或多个实现了WebMvcTagsContributor
的@Bean
,如果想替换(上述)tag标记,提供一个实现了WebMvcTagsProvider
的@Bean
提示
在某些情况下,控制器和请求处理器内处理的异常并不会以指标tag标记的方式(如上表)被记录。此时,应用程序可以通过将异常设置为请求的属性来确保该异常处理不会被遗漏。
Spring WebFlux指标(Spring WebFlux Metrics)
自动装配机制会开启对 Spring WebFlux控制器(Spring WebFlux controllers)和请求处理器(functional handlers)的所有请求的采集。默认情况下,指标的名称前缀为 http.server.requests
。可以通过设置 management.metrics.web.server.request.metric-name
来自定义该前缀。
@Controller
类和@RequestMapping
方法支持@Timed
注解(详情参考:[@Timed注解支持(@Timed Annotation Support)](##@Timed注解支持(@Timed Annotation Support)))。如果不想开启所有的Spring WebFlux请求,可以将management.metrics.web.server.request.autotime.enabled
设置为false
,而仅使用@Timed
注解。
默认情况下,Spring WebFlux相关的指标会被增加如下tag标记:
Tag | 详情 |
---|---|
exception |
当处理请求出现异常时,被抛出的异常类的简短类名 |
method |
请求方法(例如:GET 或POST ) |
outcome |
基于响应状态码的返回值描述,1xx:INFORMATIONAL ;2xx:SUCCESS ;3xx:REDIRECTION ;4xx:CLIENT_ERROR ;5xx:SERVER_ERROR |
status |
响应状态码(例如200 或500 ) |
url |
在变量替换之前使用请求的URI模板(例如,/api/person/{id} ) |
如果想添加默认的tag标记,可以提供一个或多个实现了WebFluxTagsContributor
的@Bean
,如果想替换(上述)tag标记,提供一个实现了WebFluxTagsProvider
的@Bean
提示
在某些情况下,控制器和请求处理器内处理的异常并不会以指标tag标记的方式(如上表)被记录。此时,应用程序可以通过将异常设置为请求的属性来确保该异常处理不会被遗漏。
Jersey Server指标(Jersey Server Metrics)
只要Micrometer的micrometer-jersey2
模块在classpath下,自动装配机制会开启所有由Jersey JAX-RS实现的请求。默认情况下,指标的名称前缀为 http.server.requests
。可以通过设置 management.metrics.web.server.request.metric-name
来自定义该前缀。
默认情况下,Jersey server相关的指标会被增加如下tag标记:
Tag | 详情 |
---|---|
exception |
当处理请求出现异常时,被抛出的异常类的简短类名 |
method |
请求方法(例如:GET 或POST ) |
outcome |
基于响应状态码的描述,1xx:INFORMATIONAL ;2xx:SUCCESS ;3xx:REDIRECTION ;4xx:CLIENT_ERROR ;5xx:SERVER_ERROR |
status |
响应状态码(例如200 或500 ) |
url |
在变量替换之前使用请求的URI模板(例如,/api/person/{id} ) |
如果想自定义这些tag标记,提供一个实现了JerseyTagsProvider
接口的@Bean
即可
HTTP Client指标(HTTP Client Metrics)
Spring Boot Actuator提供了对RestTemplate
和WebClient
的监测管理。不过使用需要通过注入自动装配的builder来创建实例:
- 通过
RestTemplateBuilder
创建RestTemplate
- 通过
WebClient.Builder
创建WebClient
也可以使用自定义的MetricsRestTemplateCustomizer
和MetricsWebClientCustomizer
实现同相同目的。
默认情况下,指标的名称前缀为 http.client.requests
,可以通过修改management.metrics.web.client.request.metric-name
来自定义该前缀
默认情况下,相关指标会增加如下tag标记:
Tag | 详情 |
---|---|
clientName |
URI的主机地址 |
method |
请求方法(例如:GET 或POST ) |
outcome |
基于响应状态码的返回值描述,1xx:INFORMATIONAL ;2xx:SUCCESS ;3xx:REDIRECTION ;4xx:CLIENT_ERROR ;5xx:SERVER_ERROR |
status |
正常情况下为HTTP响应状态码(例如200 或500 ),出现I/O异常时为IO_ERROR ,其他情况为CLIENT_ERROR |
url |
在变量替换之前使用请求的URI模板(例如,/api/person/{id} ) |
可以提供一个实现了RestTemplateExchangeTagsProvider
或WebClientExchangeTagsProvider
接口的@Bean
,实现对tag标记的自定义。RestTemplateExchangeTags
and WebClientExchangeTags
内也包含方便使用的静态函数。
Tomcat指标( Tomcat Metrics)
当MBeanRegistry
注册表被启用时,自动装配机制会开启对Tomcat的监测。默认情况下,MBeanRegistry
是关闭的,可以通过将server.tomcat.mbeanregistry.enabled
设置为true
来开启。
Tomcat指标以tomcat.
为前缀。
缓存指标(Cache Metrics)
当应用启动时,自动装配机制会开启所有已生效Caches
的监测,并以cache.
为前缀。这是基础监测指标的标准化配置(Cache instrumentation is standardized for a basic set of metrics.)。此外,某些缓存专属指标也是生效的。如下缓存库已经被支持:
- Caffeine
- EhCache 2
- Hazelcast
- Any compliant JCache (JSR-107) implementation
- Redis
这些指标会被附加两个tag标记,它们分别是以缓存命名的tag,以及实现了CacheManager
的bean的名字。
提示
只有启动时被配置的缓存会被绑定到指标注册表中。对于那些没有在配置中定义的缓存,例如当启动后,实时地或编程方式创建的缓存,则需要显示地进行注册。
CacheMetricsRegistrar
bean提供了简单易用的注册机制。
数据源指标(DataSource Metrics)
自动装配会启用对所有可用DataSource
对象的监测,这些指标以jdbc.connections
为前缀。数据源测量结果以gauges的方式显示连接池内当前活动连接数、空闲连接数、最大连接数和最小连接数。
这些指标也会被附加tag标记,这些tag标记的名字就是DataSource
bean的名字。
提示
默认情况下,对于所有支持的数据源,Spring Boot都提供了元数据(metadata)。如果使用的数据源不支持这个开箱即用的特性,可以额外提供
DataSourcePoolMetadataProvider
,可以到DataSourcePoolMetadataProvidersConfiguration
查看使用示例。
Hibernate指标( Hibernate Metrics)
如果org.hibernate:hibernate-micrometer
在classpath内,所有生效且开启统计EntityManagerFactory
实例都会被监测,指标名为:hibernate
。
这些指标也会被附加tag标记,tag标记的名字就是EntityManagerFactory
bean的名字。
如果要开启统计功能,JPA属性hibernate.generate_statistics
必须要被设置为true
,可以通过如下示例将EntityManagerFactory
开启:
1 | spring: |
Spring Data Repository指标(Spring Data Repository Metrics)
自动装配机制会开启Spring Data Repository
的所有函数调用的监测。默认情况下,指标名为spring.data.repository.invocations
,可以通过management.metrics.data.repository.metric-name
对其修改。
Repository
类及其方法支持@Timed
(查看@Timed注解支持了解更多细节)注解。如果不想对所有的Repository
调用都开启指标监控,可以将management.metrics.data.repository.autotime.enabled
设置为false,并且单独使用@Timed
。
默认情况下,Repository
相关的指标会被附加如下tag标记:
Tag | 详情 |
---|---|
repository |
Repository 的简单类名 |
method |
被调用的Repository 方法名 |
state |
状态(SUCCESS , ERROR , CANCELED or RUNNING ) |
exception |
当调用出现异常时,异常类的简单类名 |
如果想修改这些默认的tag标记,配置一个实现了RepositoryTagsProvider
接口的@Bean
。
RabbitMQ指标(RabbitMQ Metrics)
自动装配机制会开启所有可用的RabbitMQ
连接的监控,指标名为rabbitmq
。
Spring Integration指标(Spring Integration Metrics)
任何时候,当MeterRegistry
bean可用时,Spring Integration会自动提供基于Micrometer
的监测支持。并且指标会被发布在spring.integration.
下面。
Kafka指标(Kafka Metrics)
自动装配机制会分别为自动装配的消费者工厂(consumer factory)和生产者工厂(producer factory)注册一个 MicrometerConsumerListener
和 MicrometerProducerListener
。也会为StreamsBuilderFactoryBean
注册一个KafkaStreamsMicrometerListener
。更多详情,请参考Spring Kafka文档的 Micrometer原生指标。
MongoDB指标(MongoDB Metrics)
命令指标(Command Metrics)
自动装配机制会为自动装配的MongoClient
注册一个MongoMetricsCommandListener
。
对于mongoDB driver下的每一条指令,都会创建一个名为mongodb.driver.commands
的计时器指标(timer metric)。每个指标默认会附加如下tag标记:
Tag | 详情 |
---|---|
command |
命令的名称 |
cluster.id |
执行命令的monoDB集群的id |
server.address |
执行命令的mongoDB的的服务器地址 |
status |
命令返回结果(SUCCESS 或FAILED 中的一个) |
如果想替换默认的指标tag标记,可以定义一个MongoCommandTagsProvider
bean,如下所示:
1 |
|
如果想禁用上述命令指标,可以按照如下指令进行设置:
1 | management: |
连接池指标(Connection Pool Metrics)
自动装配机制会为自动装配的MongoClient
注册一个MongoMetricsConnectionPoolListener
。
连接池会创建如下gauge指标:
mongodb.driver.pool.size
上报当前连接池内的连接数量,包括空闲和使用者的连接。mongodb.driver.pool.checkedout
上报连接池内正在使用的连接数量mongodb.driver.pool.waitqueuesize
上报连接池等待队列的大小
默认情况下,每个指标都会被附加如下tag标记:
Tag | 详情 |
---|---|
cluster.id |
当前连接池对应的monoDB集群的id |
server.address |
当前连接池对应的monoDB集群的服务器地址 |
如果想替换默认的指标tag标记,可以定义一个MongoConnectionPoolTagsProvider
bean,如下所示:
1 |
|
如果想禁用上述连接池指标,可以按照如下指令进行设置:
1 | management: |
@Timed注解支持(@Timed Annotation Support)
io.micrometer.core.annotation
包内的@Timed
注解可以被上述列出的某些指标支持。一旦被支持,这个注解既可以用在类层级,也可以用在函数层级上。
例如,如下代码展示了这个注解如何监测@RestController
类的所有请求
1 |
|
如果只想监测某一个请求,可以将注解从类层级移到方法层级上:
1 |
|
如果想修改方法层级的指标信息,可以对该注解组合使用:
1 |
|
提示
带有
longTask = true
的@Timed
注解为方法启用一个长时间任务计时器指标(long task timer)。该指标需要单独的名称,并且可以与短时间任务计时器指标进行叠加。(译者注:此处没有说明叠加内容,如何叠加,需要后续进一步研究)
注册自定义指标(Registering Custom Metrics)
如果想注册自定义指标,可以将MeterRegistry
注入到自己的组件中,如下面例子所示:
1 |
|
如果要注册的指标需要依赖其他bean,建议使用MeterBinder
来注册,如下面的例子所示:
1 | public class MyMeterBinderConfiguration { |
使用MeterBinder
可以确保依赖的正确性,并且在指标被检索时,这个bean是可用的。如果经常重复性跨组件或应用监测一组指标,MeterBinder
会非常有用。
提示
默认情况下,所有的
MeterBinder
bean会自动绑定到由Spring管理的MeterRegistery
中。
自定义特定指标(Customizing Individual Metrics)
如果想对特定的Meter
实例进行自定义,可用使用io.micrometer.core.instrument.config.MeterFilte
接口。
例如,如果想对所有以com.example
开头的指标进行自定义:将mytag.region
改为mytag.area
,可用按照如下示例操作:
1 |
|
提示
默认情况下,所有
MeterFilter
bean会自动绑定到由Spring管理的MeterRegistery
中。要确保将自定义指标注册到由Spring管理的MeterRegistery
上,并且在Metrics
中不能含有静态函数。而全局的注册表并没有被Spring管理!
自定义通用Tag标记(Common Tags)
通用Tag标记常用来对诸如主机名(host)、实例名(instance)、地区(region)、集群(stack)等操作环境进行更细粒度的划分。通用Tag标记会被附加到所有的指标上,可以按照如下示例进行配置:
1 | management: |
以上示例中,会分别为每个指标增加两个tag标记:region:us-east-1
和stack:prod
。
提示
如果使用Graphite,通用tag标记的顺序非常重要。因为这个方式并不能保证通用tag标记的的属性,Graphite用户请使用
MeterFilter
的方式。
精确指标配置(Per-meter Properties)
除了MeterFilter
之外,也可以通过配置对每一个指标进行调整。可以在配置中指定指标的名称,所有以该名称为前缀的指标都会被调整。下面示例中,所有以example.remote
开头的指标都会被禁用:
1 | management: |
如下配置都可以应用到指标的调整:
属性 | 详情 |
---|---|
management.metrics.enable |
是否禁止指标 |
management.metrics.distribution.percentiles-histogram |
是否使用于百分比直方图(Whether to publish a histogram suitable for computing aggregable (across dimension) percentile approximations.) |
management.metrics.distribution.minimum-expected-value , management.metrics.distribution.maximum-expected-value |
通过设置监测有效范围可以减少直方图中桶的数量(Publish less histogram buckets by clamping the range of expected values.) |
management.metrics.distribution.percentiles |
需要被统计的百分位数(Publish percentile values computed in your application) |
management.metrics.distribution.slo |
额外自定义的应用级的直方图(Publish a cumulative histogram with buckets defined by your service-level objectives) |
译者提示
- 关于上述配置可以参考IBM developerWorks的一篇文章《使用 Micrometer 记录 Java 应用性能指标》(可惜网站已经关闭,该链接为github的备份)
management.metrics.enable
是一个map,key为指标ID前缀(最长的优先匹配),value为Booleanmanagement.metrics.distribution.percentiles
代表要统计的百分位数,这是一个map,key为指标ID前缀(最长的优先匹配),value为double型且取值区间为[0,1]的数组,代表某指标要统计的百分位数。百分位数是统计学指标,详情可以参考wikipedia词条management.metrics.distribution.slo
针对的是整个应用,而无法针对某一个指标进行单独配置
更多关于percentiles-histogram
和percentiles
的详情,可以参考micrometer文档的 “直方图和百分位数” 。
指标端点(Metrics Endpoint)
Spring Boot提供了一个metrics
端点,作为诊断性的目的,可以用来检查应用程序收集到的指标。这个端点默认没有被暴露出来,可以查看暴露端点(Exposing Endpoints)获得更多细节。
/actuator/metrics
列出了所有可用的端点的名称,可以通过指定某指标的名称进一步查看更详细信息,例如:/actuator/metrics/jvm.memory.max
。
提示
此处使用的指标名称应该和代码中的名字相匹配,而不是将指标名称进行映射转换后,特定监控系统的指标名称。例如,Prometheus使用的是蛇形命名法,
jvm.memory.max
会被映射转换成jvm_memory_max
。此时,在metrics
端点中,仍然应该使用jvm.memory.max
。
可以在查询语句上增加任意数量的查询参数:tag=KEY:VALUE
,从而获得某一维度上的详细指标,例如:/actuator/metrics/jvm.memory.max?tag=area:nonheap
。
提示
measurements
字段是某个指标下所有tag的统计数据的总和,在上面的例子中,这个数据是堆内存中“Code Cache”、“Compressed Class Space”和“Metaspace”各自最大值的总和,如果只想查看“Metaspace”的的最大值,可用在查询语句上增加额外的tag标记:tag=id:Metaspace
,例如:/actuator/metrics/jvm.memory.max?tag=area:nonheap&tag=id:Metaspace
审计(Auditing)
一旦Spring Security被启用,Spring Boot Actuator就有了一个灵活的审计框架可以发布事件(默认情况下,包括“认证成功”(authentication success)、“失败”(failure)和“拒绝访问”(access denied)的异常)。该特性对于报告和实现基于身份验证失败的锁定策略非常有用。
可以通过定义一个AuditEventRepository
类型的bean开启审计功能。为了方便用户,Spring Boot内置了一个InMemoryAuditEventRepository
。不过它的能力有限,我们建议只在开发环境下使用。至于生产环境,需要创建自己的AuditEventRepository
。
自定义审计(Custom Auditing)
如果想自定义安全事件,可以提供自定义的AbstractAuthenticationAuditListener
和AbstractAuthorizationAuditListener
的实现。
您还可以对自己的业务事件使用审计服务。要做到这一点,可以将AuditEventRepository
bean注入到自己的组件中并直接使用它,或者使用Spring ApplicationEventPublisher
(实现ApplicationEventPublisherAware
接口)发布一个AuditApplicationEvent
。
HTTP追踪(HTTP Tracing)
可以在应用中提供一个HttpTraceRepository
类型的bean开启HTTP追踪功能。为了方便用户,Spring Boot内置了一个InMemoryHttpTraceRepository
用于存储最近100条请求和响应。相比于其他最终方案,默认提供的InMemoryHttpTraceRepository
功能有限,我们建议仅在开发环境下使用。对于生产环境,请使用具备生产就绪特性的追踪、观测方案。例如ZipKin或Spring Cloud Sleuth。此外,也可以提供一个自定义的HttpTraceRepository
满足业务需求。
httptrace
端点可以用来获取存储在HttpTraceRepository
中的请求响应的信息。
自定义HTTP追踪(Custom HTTP tracing)
如果想自定义追踪数据,使用management.trace.http.include
。对于更加深入的自定义,可以考虑注册自定义实现的HttpExchangeTracer
bean。
进程监控(Process Monitoring)
在Spring Boot中,有两个类可以用来创建文件,这在监控进程时非常有用:
ApplicationPidFileWriter
可以创建一个包含应用PID的文件(默认情况下,文件位于应用目录,文件名为:application.pid
)WebServerPortFileWriter
创建一个(或多个)包含当前web服务器的端口的文件
这两个类默认是没有被激活,可以通过如下方式将其开启:
扩展配置(Extending Configuration)
在META-INF/spring.factories
中,你可以通过如下方式激活一个或多个监听,从而实现PID文件的写入:
1 | org.springframework.context.ApplicationListener=\ |
编程方式支持(Programmatically)
也可以通过调用SpringApplication.addListeners(…)
来激活一个监听器,并传入一个Writer
对象,这种方式允许你在Writer
的构造函数中自定义文件名、文件路径。
Cloud Foundry 支持(Cloud Foundry Support)
Spring Boot Actuator对Cloud Foundry提供了额外支持,当应用被部署到兼容的Cloud Foundry实例时,该特性会被激活。/cloudfoundryapplication
提供了另外一种到所有端点@Endpoint
bean安全路由。
提示
对于常规用户来说,
/cloudfoundryapplication
路径不能被直接访问。如果想使用该端点,需要在请求中提供一个UAA令牌(UAA token)。
禁用Cloud Foundry Actuator支持(Disabling Extended Cloud Foundry Actuator Support)
如果想完全禁用/cloudfoundryapplication
端点,可以进行如下配置:
1 | management: |
Cloud Foundry自签名证书(Cloud Foundry Self-signed Certificates)
默认情况下,/cloudfoundry
端点的安全认证会对Cloud Foundry服务进行SSL调用。如果您的Cloud Foundry UAA或Cloud Controller服务使用自签名证书,您需要设置以下属性:
1 | management: |
自定义上下文路径(Custom Context Path)
如果服务器的上下文路径并非/
,而是其他路径,那么根路径下的Cloud Foundry端点会不可用。例如,对于配置server.servlet.context-path=/app
,Cloud Foundry端点路径为:/app/cloudfoundryapplication/*
。
如果想实现这个需求:不管服务器的上下文路径如何配置, Cloud Foundry端点的路径都位于:/cloudfoundryapplication/*
,需要在应用中进行配置,至于配置方式,根据所使用的web服务器的不同而不尽相同。以Tomcat为例,可以使用如下配置:
1 |
|
接下来要读什么(What to Read Next)
你可能想读一些关于图形工具的文档,例如Graphite](https://graphiteapp.org/)