应用监控
当一个SpringBoot项目在运行时,开发者需要对SpringBoot项目进行实时监控,获取项目的运行情况,在项目出错时能够实现自动报警等。SpringBoot提供了actuator(读作[ˈæktjuˌeɪtər]
)来帮助开发者获取应用程序的实时运行数据。开发者可以选择使用HTTP端点或JMX来管理和监控应用程序,获取应用程序的运行数据,包括健康状况、应用信息、内存使用情况等。
端点配置
开启端点
在SpringBoot中开启应用监控非常容易,只需要添加actuator
依赖即可,actuator(执行器)是制造业术语,指一个用于移动或控制机械装置的工具,一个很小的变化就能让执行器产生大量的运动。
第一步,创建项目。使用spring Initializr
构建工具构建一个SpringBoot的Web应用,名称为actuatorspringboot
,然后在pom.xml文件中添加如下依赖:
1 | <!--添加actuator依赖--> |
开发者可以使用执行器中的端点(EndPoints)对应用进行监控或者与应用进行交互,SpringBoot默认包含许多端点,如下图所示:
如果是一个Web应用,还会有下图的信息:
这些端点大部分都是默认开启的,只有shutdown端点默认未开启,如果需要开启,可以在application.properties
配置文件中进行设置:
1 | management.endpoint.shutdown.enabled=true |
如果开发者不想暴露出这么多端点,那么可以关闭默认的配置,然后手动指定需要开启哪些端点,如下配置表示关闭所有的端点,只开启info端点:
1 | management.endpoints.enabled-by-default=false |
暴露端点
由于有的端点包含敏感信息,因此端点的启用和暴露需要慎重对待。下图展示了端点的默认暴露情况:
从上图中可以看出,在Web应用中,默认只有health和info两个端点暴露,即当开发者在SpringBoot项目中加入spring-boot-starter-actuator
依赖并启动SpringBoot项目后,默认只有这两个端口可以访问,即只能访问以下三个连接:
1 | http://localhost:8080/actuator/health |
其实当你在浏览器中访问http://localhost:8080/actuator
的时候,页面返回了一个JSON对象,这个对象中就包含了所有能访问的链接:
开发者可以在application.properties
配置文件中自定义需要暴露的端点,举个例子来说,需要暴露mappings和metrics端点,只需要添加如下配置即可:
1 | management.endpoints.web.exposure.include=mappings,metrics |
如果需要暴露所有的端点,也只需要添加如下配置:
1 | management.endpoints.web.exposure.include=* |
由于*在YAML格式的配置文件中有特殊的含义,因此如果开发者想在YAML文件中配置暴露所有的端点,可以按照如下方式进行配置:
1 | management: |
当配置暴露所有端点后,/actuator
接口下的所有子接口都是可以被访问的:
细心的你可能已经发现了,并不是所有的端点都在这个/actuator
接口下,这是因为部分端点需要相关依赖才能使用,如sessions站点需要spring-session
依赖。对于已经展示出来的接口,开发者可以直接发送相应的请求来查看相关信息,如health端点,如下图所示。status:up
表示应用在线,默认展示的health信息较少,后面会详细介绍health端点的其他配置:
端点保护
如果这些端点需要对外提供服务,那么最好能够将这些端点保护起来,若classpath中存在Spring Security,则默认使用Spring Security保护,使用Spring Security保护的步骤非常简单。
首先添加Spring Security依赖,代码如下所示:
1 | <!--添加security依赖--> |
然后添加Spring Security配置。新建一个config包,并在其中创建ActuatorSecurity
类,注意需要继承WebSecurityConfigurerAdapter
并重写configure(HttpSecurity http)
方法,相应的代码为:
1 | @Configuration |
注意在HttpSecurity中配置所有的Endpoint都需要具有ADMIN角色才能访问,同时开启httpBasic
认证。注意EndpointRequest.toAnyEndpoint()
表示匹配所有的Endpoint,例如shutdown、mappings、health等,但是不包括开发者通过使用@RequestMapping
注解定义的接口(可以参看之前的文章,里面有说明)。
这里为了演示方便就不连接数据库了,而是直接在application.properties
配置文件中定义一个用户并进行测试,相应的代码为:
1 | # 定义一个security用户信息 |
定义完成后,启动SpringBoot项目,再去访问health端口,也就是http://localhost:8080/actuator/health
链接时,页面会提示需要登录以后才能进行访问。
端点响应缓存
对于一些不带参数的端点,请求会自动进行缓存,开发者可以通过如下方式配置缓存时间:
1 | # 配置端点响应缓存 |
这个配置表示beans端点的缓存时间为100ms,如果需要配置其他的端点,只需将beans修改为其他的端点名称即可。注意,如果端点添加了Spring Security保护,那么此时Principal会被视为端点的输入,因此端点响应将不会被缓存。
路径映射
默认情况下,所有端点都暴露在/actuator
路径下,例如heal端点的访问路径是/actuator/health
,但是开发者需要对端点路径进行定制,可以在application.properties
配置文件内添加如下配置:
1 | # 自定义路径映射 |
第一行配置表示将默认的/actuator
,修改为/
,这行配置会使所有的端点访问路径失去/actuator
前缀。第二行的配置表示将/health
修改为/healthcheck
,修改后health端点的访问路径由之前默认的/actuator/health
,变为现在的/healthcheck
。此时启动项目,直接在浏览器地址栏中访问http://localhost:8080/
可以看到现在的端点信息,这里就不附上图片了。
CORS支持
所有端点默认都没有开启跨域,开发者可以通过在application.properties
配置文件内添加如下配置来快速开启CORS支持,进而实现跨域:
1 | # CORS支持 |
上述配置表示允许端点处理来自http://localhost:8081
地址的请求,允许的请求方法为GET和POST。
健康信息
(1)展示健康信息详情。
开发者可以通过查看健康信息来获取应用的运行数据,进而提早发现应用问题,提早解决,避免造成损失。默认情况下,开发者只能获取到status信息:
这是因为detail信息默认不显示,开发者可以通过management.endpoint.health.show-details
属性来配置detail信息的显示策略,该属性的取值一共有三种:
(1)never,即不显示detail信息,这是默认的设置;(2)when_authorized,details信息只展示给认证用户,即用户登录后可以查看details信息,未登录则不能查看,另外还可以通过management.endpoint.health.roles
属性配置要求的角色,如果不配置,那么通过认证的用户都可以查看details信息,如果配置了,如management.endpoint.health.roles=ADMIN
则表示认证的用户必须具有ADMIN角色才能查看details信息。(3)always,表示将details信息展示给所有用户。
例如,在pom.xml文件中引入Spring Security
后,在application.properties
配置文件中增加如下配置:
1 | management.endpoints.web.exposure.include=* |
这里首先暴露所有的端点,配置health的details信息只展示给认证用户,且认证用户还必须具有ADMIN角色,然后配置一个默认的用户,用户名为envy,用户密码为1234,用户角色是ADMIN。
配置完成后,启动SpringBoot项目,并在Postman测试工具中访问health端点,如下图所示:
请注意上面这个链接是需要验证的,因此必须使用Authorization模式。
其实这些信息可以在控制台右侧的Endpoints中进行查看,如下图所示:
健康指示器
SpringBoot会根据classpath中依赖的添加情况来自动配置一些HealthIndicators
,如下图所示:
如果项目中存在相关依赖,那么列表中对应的HealthIndicators
将会被自动配置。举个例子来说,如果开发人员在pom.xml文件中添加了Redis依赖,且配置好了连接信息,那么此时访问health端点,结果则如下图所示:
若开发者不需要这么多的HealthIndicators
,则可以通过如下配置来关闭所有的HealthIndicators
自动化配置,只需要在application.properties
配置文件内添加如下代码:
1 | management.health.defaults.enabled=false |
(3)自定义HealthInfo。除了SpringBoot自动收集的这些HealthInfo
之外,开发者也可以自定义HealthInfo,只需要实现HealthIndicator
接口且重写其中的health方法即可。新建一个component包,并在其中创建一个EnvythinkHealth
类,里面的代码为:
1 | @Component |
解释一下上述代码的含义:
- 开发者自定义实现一个
EnvythinkHealth
类,它实现了HealthIndicator
接口,并重写了其中的health
方法。在health方法内,定义了一个变量flag,这里设置初始值为true,Health中的up和down方法分别对应两种常见的响应状态:up和down。 - 默认的响应状态一共有4种,在
OrderedHealthAggregator
类中(其实准确的说是在Status类中),分别是DOWN、OUT_OF_SERVICE、UP和UNKNOWN。如果开发者想增加响应状态,可以自定义类继承自HealthAggregator
类,或者在application.properties
配置文件内通过management.health.status.order
属性来进行配置。
配置完成后,启动SpringBoot项目,访问http://localhost:8080/actuator/health
链接,可以看到访问结果如下图所示:
如果开发者想要增加响应状态FATAL,那么只需在application.properties
配置文件内新增如下配置:
1 | management.health.status.order=FATAL,DOWN,OUT_OF_SERVICE,UP,UNKNOWN |
配置完成后,就可以在health方法中返回自定义的响应状态了,修改EnvythinkHealth
的health方法为如下所示:
1 | @Override |
修改完成后,此时重新启动SpringBoot项目,访问health端点,结果如下图所示:
请注意,此时虽然返回的status为FATAL,但是HTTP的响应码是200,在默认的4种响应状态中,DOWN和OUT_OF_SERVICE的HTTP响应码为503,UP和UNKNOWN的HTTP响应码为200,如果开发者需要对自定义的响应状态配置响应码,只需要在application.properties
配置文件中添加如下配置:
1 | # 响应状态配置响应码 |
此时再来访问一下health端点,可以看结果如下:
应用信息
应用信息就是通过/actuator/info
接口获取到的信息,主要包含三大类:自定义信息、Git信息以及项目构建信息,接下来就分别进行学习。
(1)自定义信息。
自定义信息可以在application.properties
配置文件中添加,也可以在Java代码中添加,个人推荐在配置文件中添加的方式。在application.properties
配置文件中添加是指手动定义以info开头的信息,这些信息将在info端点中显示出来。举个例子来说,在application.properties
配置文件中添加如下配置信息:
1 | # 自定义信息 |
请注意,上面的@...@
表示引用Maven中的定义。添加完这些配置信息以后,重启SpringBoot项目,访问/autuator/info
端点,得到的信息如下所示:
如果你想通过Java代码来实现自定义信息这一目的,只需要自定义类,实现InfoContributor
接口并重写其中的contribute(Info.Builder builder)
方法即可:
1 | @Component |
此时再来访问一下info端点,可以看结果如下:
(2)Git信息。
Git信息是指Git提交信息,当classpath下存在一个git.properties
文件时,SpringBoot会自动配置一个GitProperties Bean。开发者可通过Git插件自动生成Git提交信息,然后将这些展示在info端点中。具体的操作步骤如下:
首先进入到当前目录下(这里是指pom.xml文件同级目录),初始化Git仓库并且提交代码到本地仓库,代码如下:
1 | git init |
注意上面这些操作并没有将项目推送至远程分支,接下来在pom.xml文件中,添加如下plugin:
1 | <!--添加git-commit插件--> |
使用该插件来生成Git提交信息,插件添加成功后,接下来在IDEA中单击右侧的Maven Project按钮,然后找到该插件,单击git-commit-id:revision
按钮,即可生成Git提交信息,如下图所示:
当出现如下结果,则表明Git信息已经生成完成:
Git提交信息生成成功后,在当前项目的target/classes目录下会看到一个git.properties
文件,里面都是Git的提交信息,基本上所有的Git提交信息都包括在内,如分支、提交的版本号、提交的message、提交的用户、用户邮箱等信息:
最后在application.properties
配置文件中添加如下配置,表示展示所有的Git提交信息:
1 | # 展示所有的Git提交信息 |
请注意management.info.git.mode
的取值还可以是simple,表示只展示一部分核心提交信息。配置完成后,启动SpringBoot项目,访问info端点,结果如下图所示,所有的Git提交信息都展示出来了:
(3)项目构建信息。
如果classpath下存在META-INF/build-info.properties
文件,SpringBoot将自动构建BuildProperties Bean,然后info端点会发布build-info.properties
文件中的信息。build-info.properties
文件可以通过插件自动生成。具体操作步骤如下:
首先在pom.xml文件中添加如下插件:
1 | <plugin> |
然后在IDEA中单击Maven Project
,找到该插件,单击spring-boot:build-info
按钮,生成构建信息,如下图所示:
构建信息生成成功后,在当前项目目录下的target/classes/META-INF
目录下生成了一个build-info.properties
文件,内容如下:
配置完成后,启动SpringBoot项目,访问info端点,结果如下图所示,构建信息都将被自动发布出来了:
监控信息可视化
前面介绍了监控端点,返回JSON数据,但是这样信息查看非常不方便。SpringBoot中提供了监控信息管理端,用来实时监控信息的可视化,这样可以方便开发者快速查看系统的运行状况,而不用一个一个地调用接口。具体的配置步骤如下:
第一步,创建项目。使用spring Initializr
构建工具构建一个SpringBoot的Web应用,名称为adminspringboot
,然后在pom.xml文件中添加如下依赖:
1 | <dependency> |
请注意spring-boot-admin-starter-server
的版本极易与SpringBoot的版本产生冲突,这里推荐一个版本为SpringBoot 2.1.14
版本,对应spring-boot-admin-starter-server
的版本2.1.0,亲测没有Bug出现,其他版本尚未测试。关于的信息,可以点击查看 这里。
第二步,启动AdminServer。在项目启动类上添加@EnableAdminServer
注解,表示启动AdminServer,相应的代码如下:
1 | @SpringBootApplication |
第三步,启动项目。当上述配置完成以后,启动SpringBoot项目,在浏览器地址栏中输入http://localhost:8080/index.html
链接,结果如下所示:
此时Admin端将通过图表的方式展示监控信息。接下来开发Client。Client实际上就是一个一个的服务,Client将被注册到AdminServer然后AdminServer获取Client的运行数据并展示出来。因此这里使用前面的actuatorspringboot
项目作为Client。改造时分为以下两个步骤:
第一步,添加相关依赖。在pom.xml文件中添加如下以下:
1 | <!--配置Client依赖--> |
第二步,在application.properties
配置文件中新增如下两行配置:
1 | # 配置AdminServer地址 |
请注意此处AdminServer是配置在adminsprigboot
项目中的,不是在本actuatorspringboot
项目中,但是Client却是在actuatorspringboot
项目中。spring.boot.admin.client.url
表示配置AdminServer的地址。配置完成后,启动Client项目,此时AdminServer就可以看到Client的运行数据,如下图所示,该图展示了当前注册到AdminServer上Client列表:
如果出现下面的错误:
1 | org.springframework.web.reactive.function.BodyExtractors$ReadCancellationException: null |
那么说明是actuatorspringboot
项目中的SpringSecurity框架引起的冲突,此时需要注释掉pom.xml文件中的SpringSecurity框架依赖,并注释掉其余关于SpringSecurity框架和FATAL的相关信息,然后重新启动就会发现不会再出错误了。
点击AdminServer的Client列表中右上角的Wallboard按钮,它展示了Client的简略信息,如下图所示:
接着单击图中的实例名称,即可看到Client运行的详细数据,如下图所示。一些常见的信息展示在Details选项卡中,其他的选项卡都对应不同的端点数据:
接着点击AdminServer的Client列表中右上角的Journal按钮,它展示了项目运行日志,如下图所示:
邮件报警
虽然使用AdminServer可以实现监控信息可视化,但是项目运维工程师不可能一天24小时都在盯着屏幕查看各个应用的运行状况, 如果在应用运行出问题时能够自动发送邮件通知运维工程师,这样会方便很多。对此,SpringBoot提供了相应的支持,只需要按照如下配置方式进行操作即可。
修改adminsprigboot
项目中的Admin工程,在pom.xml文件中新增邮件发送的依赖:
1 | <!--添加mail发送依赖--> |
接着在application.properties
配置文件中新增邮件发送的基本信息:
1 | # 邮件发送基本信息 |
可以看到关于邮件发送的配置,这里分成了两部分,前者为邮件发送基本信息,后者为admin邮件发送功能配置信息。在admin邮件发送功能配置信息中设置了邮件的发送者、收件人、抄送地址以及忽略的事件。默认情况下,当监控应用应用的状态变为UNKNOWN或者UP时不会发送报警邮件,这里的配置表示被监控应用的任何变化都会发送报警邮件。
配置完成后,重新启动AdminServer,然后启动被监控应用,就会收到应用上线的邮件报警,如下图所示:
现在保持AdminServer所在项目正常运行,停止运行被监控项目也就是actuatorspringboot
项目,可以发现此时也会收到应用下线的邮件报警,如下图所示:
应用监控小结
本篇学习了SpringBoot项目中常见的应用监控,分别介绍了端点的配置以及监控数据的可视化, SpringBoot提供的这一整套应用监控解决方案非常强大,在常规项目中稍微修改就可以直接用于生产环境。邮件报警可以使运维工程师及时获取应用的运行信息,特别是在应用程序上下线时及时收到通知后,可以尽早解决问题,进而避免造成一定的损失。