写点什么

玩转 Spring Boot Actuator 集成,基操,勿六

用户头像
白亦杨
关注
发布于: 2021 年 07 月 12 日

前言

曾经看到 Spring Boot Actuator 这个框架时,一直在想,它到底有什么作用呢?虽然知道它提供了很多端点,有助于应用程序的监控和管理,但如果没有直接的实践案例,还是很难有说服力的。

直到上篇文章《微服务架构:Nacos 本地缓存 PK 微服务优雅下线》中讲到可以利用其中 Actuator 定义的端点来达到微服务的优雅下线效果,才发现 Actuator 是真的很有用。

那么本文便基于 Spring Boot 系统如何集成 Actuator,如何使用,以及如何自定义一个端点(Endpoint)来展开。

Spring Boot Actuator 简介

Spring Boot Actuator 是 Spring Boot 提供用于对应用系统进行自省和监控的功能模块,基于此开发人员可以方便地对应用系统某些监控指标进行查看、统计、审计、指标收集等。Actuator 提供了基于 Http 端点或 JMX 来管理和监视应用程序。

刚接触 Actuator 朋友通常会有一个疑惑,Actuator 可以通过 Http 端点进行访问,那么它与 Spring Web 提供的 @Controller 的对外服务有什么区别呢?它们都可以通过 Http 的方式让外部来访问应用程序,但功能的定义边界不同。就像上面说的 Actuator 通常用于应用程序本身运行情况的监控和操作,而 @Controller 更多的是业务层面运用。通过与 @Controller 这么一对照,你可能更容易理解 Actuator 的作用了。

Actuator 默认功能

Actuator 提供了一些默认的 REST 接口,基于这些接口我们可以很方便的了解应用程序的运行状况。其中某些端口比较敏感,需要在指定的权限下才能进行访问。

通过 Actuator 可以监控应用程序的 Health 健康信息、Info 应用信息、HTTP Request 跟踪信息、Metrics 信息、@RequestMapping 的路径信息、应用程序的各种配置信息、程序请求的次数时间等各种信息。

这里暂且不做具体端点的解释,因为不同的版本还是有所出入的。先来看一下将所有的端点打开,然后访问 http://localhost:8080/actuator 能够看到的端点信息。


至于你所使用的版本包含哪些端点,也采用同样的方法来进行查看。

Spring Boot 的集成

将 Spring Boot Actuator 集成到 Spring Boot 项目中是非常方便的,只需在 pom 文件中添加对应的依赖即可:

<dependency>    <groupId>org.springframework.boot</groupId>    <artifactId>spring-boot-starter-actuator</artifactId></dependency>
复制代码

这里采用的是 Spring Boot 2.2.2.RELEASE 版本。启动项目,访问 http://localhost:8080/actuator 就可以看到目前可访问的端口列表信息了:

{"_links": {"self": {"href": "http://localhost:8080/actuator","templated": false},"health-path": {"href": "http://localhost:8080/actuator/health/{*path}","templated": true},"health": {"href": "http://localhost:8080/actuator/health","templated": false},"info": {"href": "http://localhost:8080/actuator/info","templated": false}}}
复制代码

可以看出,当前版本默认支持 self、health-path、health 和 info 端点信息的访问,其他信息是未对外开放的。

此时,如果需要查看像前面提到的全部的端点,可在 application 配置文件中进行如下配置:

management:  endpoints:    web:      exposure:        include: '*'    jmx:      exposure:        include: '*'
复制代码

这样便可以看到所有的端点了。此种方式是针对 Spring Boot 2.0 以后的版本才起效。需要注意的是配置中的*是需要添加单引号或双引号的。

另外,这种形式的配置也是不推荐的。这样会将所有的端点对外暴露,而没有进行权限验证。建议的模式是,使用到哪些端点,直接在 include 中明确指出。同时,敏感操作还需要进行认证。

指定配置的形式如下:

management:  endpoints:    web:      exposure:        include: health,info    jmx:      exposure:        include: health,info
复制代码

不同的端点通过英文逗号分隔即可。

Endpoint 的数据结构

其实最开始我们已经看了/actuator 返回的数据结构了,这便是端点 self 的信息。在/actuator 的返回信息中还可以看到其他可访问的端点的地址,比如这里访问 http://localhost:8080/actuator/health ,结构如下:

{"status": "UP"}
复制代码

端点返回的结果为 JSON 格式,上面返回了 status 为 UP 的状态,也就是说系统处于健康运行当中。当然,针对其他端点的访问,返回结果基本一致,这里就不逐一展示了。

停服操作

在上面的端点中,你会发现并没有关闭服务的端点。是的,默认情况下,即使 include 设置为“*”,依旧没有开启 shutdown 这类影响服务的操作。

针对这类操作,我们先要设置其可用:

management:  endpoint:    shutdown:      enabled: true  endpoints:    web:      exposure:        include: '*'    jmx:      exposure:        include: '*'
复制代码

此时,再访问/actuator 就可以看到/shutdown 端点对应的路径了 http://localhost:8080/actuator/shutdown 。

通过 curl 命令或 postman 等发送一个 post 请求到该端点:

curl -X "POST" "http://localhost:8080/actuator/shutdown"
复制代码

执行之后,发现服务被关停了。类似停服的操作还有很多,比如 restart、pause、restart 等。可根据具体版本进行配置,目前版本只发现有 shutdown 端点,未 restart、pause、restart 等端点的配置项。

通过上述方式,SpringBoot 应用可以优雅地关闭,但是存在很大的安全隐患,如果知道了 ip、端口号后就可以模拟该请求停止服务了,因此需要增加一些安全限制。

  • management.endpoints.web.base-path 自定义 shutdown 的请求路径;

  • management.server.address 设置为本地 ip,防止远程访问该连接进行关闭服务;

  • management.server.port 自定义 shutdown 请求路径的端口号;

调整后的配置文件如下:

management:  endpoint:    shutdown:      enabled: true  endpoints:    web:      exposure:        include: '*'    jmx:      exposure:        include: '*'  server:    # 自定义端口    port: 8080    # 不允许远程管理连接,安全性考虑    address: 127.0.0.1
复制代码

当然,如果此种方式并不适合你,还可以考虑引入 spring-boot-starter-security,通过 Spring Security 来保证 Actuator Endpoints 的安全,此时再访问时就需要用户名和密码的验证了。关于 Spring Security 在本篇文章就不再拓展。

自定义 Endpoint

默认的端点虽然可以满足大多数的需求,但一些特殊的需求还是需要能够支持自定义端点的。自定义 Endpoint 端点,只需要在我们的新建 Bean 上使用 @Endpoint 注解即可, Bean 中的方法就可以通过 JMX 或者 HTTP 公开。除此之外,还可以使用 @JmxEndpoint 或 @WebEndpoint 编写 EndPoint。但这些 EndPoint 仅限于各自的公开方式。例如,@WebEndpoint 仅通过 HTTP 公开,而不通过 JMX 公开。

那么是不是类中所有的方法都支持对外公开呢?很明显不是的。Actuator 提供了三个用于方法上的注解,只有加三个注解的方法才支持对外公开,并且每个注解都有支持它的 HTTP method。

@ReadOperation 对应 HTTP 的 GET 请求,@WriteOperation 对应 HTTP 的 POST 请求,@DeleteOperation 对应 HTTP 的 DELETE 请求。

来看一个简单的使用实例:

@Component@Endpoint(id = "my")public class EndpointCustom {
@ReadOperation public String endpointCustomRead(String content) { return "请求的内容: " + content; }
@WriteOperation public String endpointCustomWrite(String content) { return "写的内容: " + content; }
@DeleteOperation public String endpointCustomDelete(String content) { return "删除的内容: " + content; }
}
复制代码

对应 GET 请求:

curl -X GET http://localhost:8080/actuator/my?content=endpointGet
复制代码

执行之后,会返回信息“请求的内容: endpointGet”。

同样的 POST 请求为:

curl -X POST http://localhost:8080/actuator/my?content=endpointPost
复制代码

DELETE 请求为:

curl -X DELETE http://localhost:8080/actuator/my?content=endpointDELETE
复制代码

上面只是简单自定义实例,根据具体的业务场景,可以定义更加丰富的端点实现。

小结

通过本篇我们了解了 Spring Boot 集成 Actuator 的基本操作。集成起来非常简单,因为 Spring Boot 已经帮我们做了大多数的事情,我们只需要有针对性地进行配置即可。对于预定义端点无法满足业务需求的情况,还可以通过自定义的形式来实现特殊化处理。学习 Actuator 最重要的点在于知道它的运用场景。

本文完整源码地址:https://github.com/secbr/springboot-all/tree/master/springboot-actuator

原文链接:https://mp.weixin.qq.com/s/BaNQWygQb8UXxktrXetOcw

作者:程序新视界

如果觉得本文对你有帮助,可以转发关注支持一下

用户头像

白亦杨

关注

还未添加个人签名 2021.07.06 加入

还未添加个人简介

评论

发布
暂无评论
玩转Spring Boot Actuator集成,基操,勿六