Spring Boot Actuator 端点监控

       spring-boot-starter-actuator库主要用来暴露自身信息。有助于对应用程序进行监控和管理,以及采集一些应用指标。actuator通过 restful api 请求来监管、审计、收集应用的运行情况。

actuator每个restful api请求对应一个端点Endpoint。

       Actuator模块不仅会根据应用依赖和配置自动创建出来的监控和管理端点Endpoint(原生端点: health、info、beans、httptrace、shutdown等等),同时我们也可以它的基础之上扩展实现一些自定义的监控需求(自定义端点)。

一 Spring Boot添加Actuator

1.1 pom依赖

       pom.xml文件添加spring-boot-actuator模块。

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

1.2 属性配置

       application.yml文件加入如下配置,当然大家可以根据自己的需求做修改。

# actuator监控
management:
  #  server:
  #    # 设置监控服务端口,如果没写默认就是服务器的端口
  #    port: 8081
  endpoints:
    # 设置端点是否可用 默认只有shutdown可用
    enabled-by-default: true
    web:
      # 设置是否暴露端点 默认只有health和info可见
      exposure:
        # 包括所有端点
        include: "*" # 注意需要添加引号
        # 排除端点
        exclude: shutdown
  endpoint:
    health:
      show-details: always
    #可以关闭指定的端点
    shutdown:
      enabled: false

属性配置主要是配置一些actuator endpoint的打开和关闭(配置是否可以用个HTTP的方式暴露出去,使得他们能被远程进入),关于属性的配置大家一看单词就能大概知道对应的意思。。

1.3 添加plugin

       访问info Endpoint需要添加该插件

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

       做完上面三个步骤Actuator我们就已经引入到我们项目中来了。

1.4 运行程序

       把应用程序跑起来,在应用程序启动过程中,我们可以找到如下打印。证明Actuator确实已经引入进来了。

在这里插入图片描述

二 原生端点

       Actuator里面已经默认给提供了大量的端点。如下:

Endpoints id 描述 HTTP方法 是否敏感信息
auditevents 显示当前应用程序的审计事件信息 GET Yes
beans 显示应用上下文中创建的所有Bean GET Yes
caches 显示可用缓存信息 GET Yes
conditions 显示自动装配类的状态及及应用信息 GET Yes
configprops 显示所有 @ConfigurationProperties 列表 GET Yes
env 显示 ConfigurableEnvironment 中的属性 GET Yes
flyway 显示 Flyway 数据库迁移信息 GET Yes
health 显示应用的健康信息(未认证只显示status,认证显示全部信息详情) GET No
info 显示任意的应用信息(在资源文件写info.xxx即可) GET No
liquibase 展示Liquibase 数据库迁移 GET Yes
metrics 提供应用运行状态的完整度量指标报告 GET Yes
mappings 显示所有 @RequestMapping 路径集列表 GET Yes
scheduledtasks 显示应用程序中的计划任务 GET Yes
sessions 允许从Spring会话支持的会话存储中检索和删除用户会话。 GET Yes
shutdown 允许应用以优雅的方式关闭(默认情况下不启用) POST Yes
threaddump 执行一个线程dump GET Yes
httptrace 显示HTTP跟踪信息(默认显示最后100个HTTP请求 - 响应交换) GET Yes

       大部分端点我们通过GET方式就能获取到对应的信息。部分端点需要POST请求,比如shutdown端点。关于actuator里面原生的端点,我们就主要就讲两个:health、metrics。

2.1 health

       /health端点 用来获取应用的各类健康指标信息。在spring-boot-starter-actuator模块中自带实现了一些常用资源的健康指标检测器。这些检测器都通过HealthIndicator接口实现,并且会根据依赖关系的引入实现自动化装配,比如用于检测磁盘的DiskSpaceHealthIndicator、检测DataSource连接是否可用的DataSourceHealthIndicator等。actuator里面自带的健康指标检测器如下(当前前提是工程里面有使用到,比如如果程序里面有用到redis,health Endpoint里面就有带有Radis的健康检测):

健康指标检测器 解释
CassandraHealthIndicator 检查 Cassandra 数据库是否启动。
DiskSpaceHealthIndicator 检查磁盘空间不足。
DataSourceHealthIndicator 检查是否可以获得连接 DataSource。
ElasticsearchHealthIndicator 检查 Elasticsearch 集群是否启动。
InfluxDbHealthIndicator 检查 InfluxDB 服务器是否启动。
JmsHealthIndicator 检查 JMS 代理是否启动。
MailHealthIndicator 检查邮件服务器是否启动。
MongoHealthIndicator 检查 Mongo 数据库是否启动。
Neo4jHealthIndicator 检查 Neo4j 服务器是否启动。
RabbitHealthIndicator 检查 Rabbit 服务器是否启动。
RedisHealthIndicator 检查 Redis 服务器是否启动。
SolrHealthIndicator 检查 Solr 服务器是否已启动。

       我们要怎么才能看到health端点对应的信息呢。很简单,咱们不是说了其实每个端点就对应一个restful api请求。health Endpoint 对应GET请求。比如我们实例里面的health端点地址:http://127.0.0.1:2224/actuator/health 请求结果如下:(因为我们实例工程里面什么都没有,我连数据库都没有添加进去。所以你只能看到DiskSpaceHealthIndicator检测器检测到的diskSpace信息)

{
    "status": "UP",
    "details": {
        "diskSpace": {
            "status": "UP",
            "details": {
                "total": 264598032384,
                "free": 210941227008,
                "threshold": 10485760
            }
        },
        "refreshScope": {
            "status": "UP"
        },
        "discoveryComposite": {
            "status": "UP",
            "details": {
                "discoveryClient": {
                    "status": "UP",
                    "details": {
                        "services": []
                    }
                },
                "eureka": {
                    "description": "Eureka discovery client has not yet successfully connected to a Eureka server",
                    "status": "UP",
                    "details": {
                        "applications": {}
                    }
                }
            }
        },
        "configServer": {
            "status": "UNKNOWN",
            "details": {
                "error": "no property sources located"
            }
        },
        "hystrix": {
            "status": "UP"
        }
    }
}

       虽然health 端点里面已经默认给实现了很多健康信息的检测。但是有的时候我们也想在health端点里面添加我们自定义的健康检测任务。有两种方式实现:继承AbstractHealthIndicator类、实现HealthIndicator接口。

2.1.1 继承AbstractHealthIndicator类实现我们自己的健康检测

       我们可以通过自定义一个类继承自AbstractHealthIndicator类来实现我们自己的健康检测。比如有这样一个例子,我们自定义一个AllDiskSpaceAbstractHealthIndicator类检测所有磁盘的磁盘信息。代码如下

/**
 * 通过自定义一个类继承AbstractHealthIndicator,往health端点添加数据
 *
 * allDiskSpace2 对应的信息会在 http://127.0.0.1:2224/actuator/health 里面显示出来
 */
@Component("allDiskSpace2")
public class AllDiskSpaceAbstractHealthIndicator extends AbstractHealthIndicator {

    @Override
    protected void doHealthCheck(Health.Builder builder) throws Exception {

        File[] rootFiles = File.listRoots();
        if (rootFiles != null && rootFiles.length != 0) {
            long total = 0, free = 0;
            for (File file : rootFiles) {
                total += file.getTotalSpace(); // 总量
                free += file.getUsableSpace(); // 未用
            }
            long user = total - free; // 已用
            double userRate = total == 0 ? 0 : ((double) user / total);// 利用率
            builder.up()
                    .withDetail("diskspaceTotal", total)
                    .withDetail("diskspaceFree", free)
                    .withDetail("diskspaceUsage", userRate * 100)
                    .build();
        } else {
            builder.down().build();
        }

    }
}


       然后我们再通过 http://127.0.0.1:2224/actuator/health 来访问下health端点,看下我们自定义的所有磁盘容量检测是否也更随一起返回了。注意在health端点返回的数据里面查找allDiskSpace2节点对应的数据。allDiskSpace2就是 @Component(“allDiskSpace2”)里面对应的allDiskSpace2。结果如下。

在这里插入图片描述

2.1.2 实现HealthIndicator接口实现我们自己的健康检测

       除了继承AbstractHealthIndicator类,我们也可以通过实现HealthIndicator接口的方式来实现自己的健康检测。代码如下:

/**
 * 通过自定义一个类实现HealthIndicator接口,往health端点添加数据
 * allDiskSpace0 对应的信息会在 http://127.0.0.1:2224/actuator/health 里面显示出来
 */
@Component("allDiskSpace0")
public class AllDiskSpaceHealthIndicator implements HealthIndicator {

    @Override
    public Health health() {
        File[] rootFiles = File.listRoots();
        if (rootFiles != null && rootFiles.length != 0) {
            long total = 0, free = 0;
            for (File file : rootFiles) {
                total += file.getTotalSpace(); // 总量
                free += file.getUsableSpace(); // 未用
            }
            long user = total - free; // 已用
            double userRate = total == 0 ? 0 : ((double) user / total);// 利用率
            return Health.up()
                    .withDetail("diskspaceTotal", total)
                    .withDetail("diskspaceFree", free)
                    .withDetail("diskspaceUsage", userRate * 100)
                    .build();
        } else {
            return Health.down().build();
        }
    }
}

       程序跑起来,http://127.0.0.1:2224/actuator/health 返回的端点数据里是否有 allDiskSpace0 节点数据。

在这里插入图片描述

2.2 metrics

       metrics端点用来返回当前应用的各类重要度量指标,比如:内存信息、线程信息、垃圾回收信息等。我们可以通过http://127.0.0.1:2224/actuator/metrics 请求来查看我们工程metrics端点所支持的度量指标(metrics更小的细粒度)有哪些。请求结果如下所示:

{
    "names": [
        "jvm.memory.max",
        "process.files.max",
        "jvm.gc.memory.promoted",
        "tomcat.cache.hit",
        "system.load.average.1m",
        "tomcat.cache.access",
        "jvm.memory.used",
        "jvm.gc.max.data.size",
        "jvm.memory.committed",
        "system.cpu.count",
        "logback.events",
        "tomcat.global.sent",
        "jvm.buffer.memory.used",
        "tomcat.sessions.created",
        "jvm.threads.daemon",
        "system.cpu.usage",
        "jvm.gc.memory.allocated",
        "tomcat.global.request.max",
        "tomcat.global.request",
        "tomcat.sessions.expired",
        "jvm.threads.live",
        "jvm.threads.peak",
        "tomcat.global.received",
        "process.uptime",
        "tomcat.sessions.rejected",
        "process.cpu.usage",
        "tomcat.threads.config.max",
        "jvm.classes.loaded",
        "jvm.gc.pause",
        "jvm.classes.unloaded",
        "tomcat.global.error",
        "tomcat.sessions.active.current",
        "tomcat.sessions.alive.max",
        "jvm.gc.live.data.size",
        "tomcat.servlet.request.max",
        "tomcat.threads.current",
        "tomcat.servlet.request",
        "process.files.open",
        "jvm.buffer.count",
        "jvm.buffer.total.capacity",
        "tomcat.sessions.active.max",
        "tomcat.threads.busy",
        "process.start.time",
        "tomcat.servlet.error"
    ]
}

在知道了metrics端点支持的那些度量指标之后,我们就可以通过http://127.0.0.1:2224/actuator/metrics/{name} 的方式来请求获取每个度量指标对应的信息。比如我们可以通过 http://127.0.0.1:2224/actuator/metrics/jvm.memory.max 来获取 jvm.memory.max对应的信息。

       虽然metrics端点里面已经给实现了很多度量指标的检测。metrics端点里面咱们也是可以加入自己的度量指标。我们还是以磁盘容量作为例子,我们准备在metrics里面添加 diskSpaceInfo.total、diskSpaceInfo.free、diskSpaceInfo.usage三个度量指标,并且计算出度量值。代码如下。

@Component
public class DiskMetrics implements MeterBinder {

    private File rootFilePath;

    public DiskMetrics() {
        this.rootFilePath = new File(".");
    }

    @Override
    public void bindTo(@NotNull MeterRegistry registry) {
        // 磁盘已用容量
        Gauge.builder("diskSpaceInfo.total", rootFilePath, File::getTotalSpace)
                .register(registry);
        // 磁盘剩余容量
        Gauge.builder("diskSpaceInfo.free", rootFilePath, File::getFreeSpace)
                .register(registry);
        // 磁盘使用率
        Gauge.builder("diskSpaceInfo.usage", rootFilePath, c -> {
            long totalDiskSpace = rootFilePath.getTotalSpace();
            if (totalDiskSpace == 0) {
                return 0.0;
            }

            long usedDiskSpace = totalDiskSpace - rootFilePath.getFreeSpace();
            return (double) usedDiskSpace / totalDiskSpace * 100;
        })
                .register(registry);
    }
}

二 自定义端点

       除了默认的这些health、metrics等端点之外。咱们也是可以自定义端点的。比如我们现在要自定义一个diskspace端点。展示磁盘信息。代码如下:注意添加@Configuration、@Endpoint(id = “diskspace”) 注解。

/**
 * 自定义一个端点 id = diskspace 获取磁盘容量信息
 */
@Configuration
@Endpoint(id = "diskspace") // @EndPoint中的id不能使用驼峰法,需要以-分割
public class DiskSpaceEndPoint {

    /**
     * 获取自定义端点需要监测的数据 -- 磁盘容量信息
     *
     * @return Map<String, String>
     */
    @ReadOperation
    public Map<String, String> diskSpaceInfo() {
        Map<String, String> result = new HashMap<>();
        // 获取磁盘容量信息
        File[] rootFiles = File.listRoots();
        if (rootFiles != null && rootFiles.length != 0) {
            long total = 0;
            long free = 0;
            for (File file : rootFiles) {
                total += file.getTotalSpace(); // 总量
                free += file.getUsableSpace(); // 未用
            }
            long user = total - free; // 已用
            double userRate = total == 0 ? 0 : ((double) user / total);// 利用率
            result.put("diskspaceTotal", String.valueOf(total));
            result.put("diskspaceFree", String.valueOf(free));
            result.put("diskspaceUsage", String.valueOf(userRate * 100));
        }
        return result;
    }

}

之后http://127.0.0.1:2224/actuator/diskspace 访问diskspace端点。结果如下:

{
    "diskspaceTotal": "264598032384",
    "diskspaceUsage": "20.483477416545355",
    "diskspaceFree": "210399154176"
}

       关于Actuator更加高级的用法大家可以去看下Prometheus,Prometheus是一个开源的系统监控及告警工具。

       上文涉及到的实例代码下载地址
https://github.com/tuacy/microservice-framework。对应代码里面的actuator module

猜你喜欢

转载自blog.csdn.net/wuyuxing24/article/details/88767060