05. Springboot admin集成Actuator(一)
目录
1、前言
2、Actuator监控端点
2.1、健康检查
2.2、信息端点
2.3、环境信息
2.4、度量指标
2.5、日志文件查看
2.6、追踪信息
2.7、Beans信息
2.8、Mappings信息
3、快速使用
2.1、添加依赖
2.2、添加配置文件
2.3、启动程序
4、自定义端点Endpoint
5、自定义health
6、附录
7、小结
1、前言
Spring Boot Actuator是Spring Boot提供的一个用于监控和管理应用程序的扩展模块。Actuator通过HTTP端点和JMX(Java Management Extensions)提供了一系列功能,包括查看应用程序的运行状况、度量指标、日志、追踪和应用信息。它为开发人员和运维人员提供了方便的手段来监控和管理Spring Boot应用。
2、Actuator监控端点
Actuator提供了一系列内置的端点(EndPoints)用于查看应用程序的运行状况、运行情况、指标等信息。其中主要提供了如下一些端点:
2.1、健康检查
HTTP端点:`/actuator/health`。提供了应用程序的健康状态,包括磁盘空间、数据库连接等信息。健康检查对于监控和负载均衡非常有用。返回的状态包括 UP(正常)、DOWN(异常)和 OUT_OF_SERVICE(维护中)等。
2.2、信息端点
HTTP端点:`/actuator/info`。提供了应用程序的自定义信息,可以在配置文件中定义,用于展示应用的版本、描述等。这些信息通常来源于应用程序的配置文件或构建系统。
2.3、环境信息
HTTP端点:`/actuator/env`。显示应用程序的环境属性,包括配置属性、系统属性等。可以通过添加参数来查看特定属性的值,如:/actuator/env/server.port。
2.4、度量指标
HTTP端点:`/actuator/metrics`。提供了应用程序的度量指标,例如内存使用、线程池状态、HTTP请求等,对性能分析和优化非常有帮助。如:/actuator/metrics/jvm.memory.used。
2.5、日志文件查看
HTTP端点:`/actuator/logfile`。允许查看应用程序的日志文件内容,方便进行故障排除。
2.6、追踪信息
HTTP端点:`/actuator/trace`。提供了应用程序的请求追踪信息,显示HTTP请求的调用链,便于跟踪请求的处理过程。
2.7、Beans信息
HTTP端点:`/actuator/beans`。显示所有在Spring应用程序上下文中注册的Beans信息,包括它们的名称、类型等。
2.8、Mappings信息
HTTP端点:`/actuator/mappings`。 显示所有的URI映射,展示了请求如何被映射到控制器方法上。
3、快速使用
了解了Actuator的各个主要端点以及他们的作用后,我们便可以选择适当的端点作为我们的监控行为,集成到项目中。
基础环境:SpringBoot-2.7.14,JDK-17.0.2。构建基础springboot demo工程。
3.1、添加依赖
<dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
3.2、添加配置文件
spring:application:name: springboot-actuator-demo
server:port: 8080management:server:port: 8081 # 指定了actuator服务端口endpoints:web:exposure:include: '*' # 表示开启所有端点,如果指定具体多个端点,可以用,隔开。如health,info
3.3、启动程序
启动日志中可以看到启动了actuator端口为8081,且访问路径为/actuator。我们访问下http://localhost:8081/actuator:
可以看到actuator返回了一列指标的访问连接。
接着继续访问给定的连接,实际上就是http://localhost:8081/actuator/端点url。如查看当前JVM内存占用情况,直接访问http://localhost:8081/actuator/metrics/jvm.memory.used
4、自定义端点Endpoint
除了Actuator自带的端点以外,我们还可以自定义所需要的端点。自定义端点需要先了解以下几个注解:
- @Component:注册为一个Spring Bean。
- @Endpoint:声明端点的注解,需要指定id=""属性,标识端点名称。
- @ReadOperation:用于定义读操作,允许获取关于应用程序状态的信息。它对应 HTTP 请求的 GET 方法。通常用于返回只读信息,例如获取应用程序的状态、性能指标等。
- @WriteOperation:用于定义写操作,允许进行应用程序的修改。它对应 HTTP 请求的 POST 方法。通常用于执行会修改应用程序状态的操作,例如重新加载配置、清理缓存等。
- @DeleteOperation:用于定义删除操作,允许进行资源的删除。它对应 HTTP 请求的 DELETE 方法。通常用于执行删除资源的操作,例如关闭数据库连接池、停止某个服务等。
- @Selector:用于@ReadOperation、@WriteOperation、@DeleteOperation标注的 Endpoint 方法时允许传递一些参数。
简单demo:
package com.example.springbootactuator.entpoint;import org.springframework.boot.actuate.endpoint.annotation.*;
import org.springframework.context.annotation.Configuration;
import org.springframework.http.HttpMethod;
import org.springframework.stereotype.Component;import java.util.HashMap;
import java.util.Map;/*** 注意:这里定义的端点名称只能是英文字母+数字,不能有其他字符,甚至下划线也不行。不然会提示 Value must only contain valid chars*/
@Component
@Endpoint(id = "myendpoint", enableByDefault = true)
public class MyEndpoint {@ReadOperationpublic Map<String, Object> endpointMyRead(@Selector String content) {Map<String, Object> customMap = new HashMap<>();customMap.put("httpMethod", HttpMethod.GET.toString());customMap.put("status", "200");customMap.put("content", content);return customMap;}@WriteOperationpublic Map<String, Object> endpointMyWrite() {Map<String, Object> customMap = new HashMap<>();customMap.put("httpMethod", HttpMethod.POST.toString());return customMap;}@DeleteOperationpublic Map<String, Object> endpointMyDelete() {Map<String, Object> customMap = new HashMap<>();customMap.put("httpMethod", HttpMethod.DELETE.toString());return customMap;}
}
运行后查看端点,可以看到多了我们自定义的myendpoint端点名称,同时多了一个可以接收{content}的端点连接,这个就是我们加了@Selector注解,允许接收参数。
来尝试访问下:http://localhost:8081/actuator/myendpoint/hello123123123。可以得到我们返回的map结构。
5、自定义health
我们还可以自定义health,用来检测其健康状态。这个也是我项目中用的比较多的,当时有一个需求是汇总所有的API请求,检测对方的API健康状态,并告警提醒,就是自定义了health。
要自定义health,可以自定义 HealthIndicator 来添加自定义的健康检查项。HealthIndicator 接口定义了一个 health() 方法,该方法返回一个 Health 对象,其中包含了应用程序的健康信息。也可以通过继承AbstractHealthIndicator抽象类来实现。
import org.springframework.boot.actuate.health.Health;
import org.springframework.boot.actuate.health.HealthIndicator;
import org.springframework.stereotype.Component;@Component
public class CustomHealthIndicator implements HealthIndicator {@Overridepublic Health health() {// 实现自定义的健康检查逻辑boolean isHealthy = checkHealth(); // 替换为实际的健康检查逻辑if (isHealthy) {return Health.up().withDetail("message", "Application is healthy").build();} else {return Health.down().withDetail("message", "Application is not healthy").build();}}private boolean checkHealth() {// 实际的健康检查逻辑,例如检查数据库连接、第三方服务状态等// 返回 true 表示健康,返回 false 表示不健康// 这里简单返回 true,实际应用中需要根据业务逻辑进行判断return true;}
}
运行程序,访问http://localhost:8081/actuator/health:
此外,可以添加以下配置,来查看health的详细信息:
management:endpoint:health:show-details: always
6、附录
贴出之前我对第三方API地址进行拨测的,实现health方式来检测健康状态的部分关键代码:
ThirdPartApiManager.java
import com.google.common.collect.HashBasedTable;
import com.google.common.collect.Table;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Configuration;/*** 第三方api地址管理器,统一管理API地址,不要直接在业务代码写死* 这里管理的api地址会进行状态监控*/
@Configuration
public class ThirdPartApiManager {@AutowiredThirdPartApiIpConfig thirdPartApiIpConfig;public static final Table<String, String, Long> THIRD_PART_API_TABLE = HashBasedTable.create();/*** 每次api心跳间隔,默认10分钟*/public static final Long INTERVAL_MICO_SECONDS = 10 * 60L * 1000;@SuppressWarnings("java:S125")public void thirdPartApiAdd() {//THIRD_PART_API_TABLE.put("获取客户信息", "http://localhost:8080/xxxxx", 1 * 60L * 1000);}}
ThirdPartApiManagerMonitor.java:
import cn.hutool.core.date.DateUtil;
import cn.hutool.json.JSONUtil;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.actuate.autoconfigure.health.HealthEndpointProperties;
import org.springframework.boot.actuate.autoconfigure.health.HealthIndicatorAutoConfiguration;
import org.springframework.boot.actuate.health.Health;
import org.springframework.boot.actuate.health.HealthIndicator;
import org.springframework.boot.autoconfigure.AutoConfigureBefore;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.context.ConfigurableApplicationContext;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Profile;
import org.springframework.scheduling.annotation.SchedulingConfigurer;
import org.springframework.scheduling.config.ScheduledTaskRegistrar;
import org.springframework.stereotype.Component;import javax.annotation.PostConstruct;
import java.io.IOException;
import java.net.HttpURLConnection;
import java.net.URL;
import java.util.Map;
import java.util.Optional;
import java.util.concurrent.ConcurrentHashMap;
import java.util.function.Function;/*** 第三方api地址心跳拨测* 拨测方式:对http发起options预请求,来诊断该接口的可用性* 注意:这里不发送trace方法,原因是trace可能会被黑客攻击,所以大多数系统trace是关闭的。*/
@Component
@Configuration
@AutoConfigureBefore({HealthIndicatorAutoConfiguration.class})
@EnableConfigurationProperties(HealthEndpointProperties.class)
@Slf4j
@Profile({"prod"})
public class ThirdPartApiManagerMonitor implements SchedulingConfigurer {@AutowiredConfigurableApplicationContext context;@AutowiredThirdPartApiManager thirdPartApiManager;@Beanpublic Map<String, Health> apiHealthResultMap() {return new ConcurrentHashMap<>(ThirdPartApiManager.THIRD_PART_API_TABLE.columnKeySet().size());}Function<ThirdPartApiDto, Health> healthIndicatorFunction = apiDto -> {Health.Builder healthBuilder = new Health.Builder().status(String.valueOf(apiDto.getStatus())).withDetail("httpCode", apiDto.getStatus()).withDetail("name", apiDto.getName()).withDetail("url", apiDto.getApi()).withDetail("description", apiDto.getName());/*** 状态码说明:* 100-199 用于指定客户端应相应的某些动作。* 200-299 用于表示请求成功。* 300-399 用于已经移动的文件并且常被包含在定位头信息中指定新的地址信息。* 400-499 用于指出客户端的错误。* 500-599 用于支持服务器错误。*/if (apiDto.getStatus() >= 400) {// 推送提醒......sendLarkMessage(apiDto);return healthBuilder.down().build();}return healthBuilder.up().build();};public int tryConnect(String url) {try {URL urlObj = new URL(url);HttpURLConnection connect = (HttpURLConnection) urlObj.openConnection();connect.setUseCaches(false);connect.setRequestMethod("OPTIONS");connect.setConnectTimeout(5000);return connect.getResponseCode();} catch (IOException e) {// nopreturn 500;}}@PostConstructpublic void registerApiHealth() {thirdPartApiManager.thirdPartApiAdd();ThirdPartApiManager.THIRD_PART_API_TABLE.columnKeySet().forEach(api -> {Optional<String> first = ThirdPartApiManager.THIRD_PART_API_TABLE.column(api).keySet().stream().findFirst();if (!first.isPresent()) {return;}context.getBeanFactory().registerSingleton(first.get() + "HealthIndicator", (HealthIndicator) () -> {if (apiHealthResultMap().containsKey(first.get())) {return apiHealthResultMap().get(first.get());}int status = tryConnect(api);ThirdPartApiDto thirdPartApiDto = ThirdPartApiDto.builder().name(first.get()).api(api).interval(ThirdPartApiManager.THIRD_PART_API_TABLE.column(api).getOrDefault(first.get(), ThirdPartApiManager.INTERVAL_MICO_SECONDS)).status(status).result(JSONUtil.toJsonStr(status)).createTime(DateUtil.now()).build();return healthIndicatorFunction.apply(thirdPartApiDto);});});}/*** 按照配置api,定时监控外部http状态*/@Overridepublic void configureTasks(ScheduledTaskRegistrar scheduledTaskRegistrar) {ThirdPartApiManager.THIRD_PART_API_TABLE.columnKeySet().forEach(api -> {Optional<String> first = ThirdPartApiManager.THIRD_PART_API_TABLE.column(api).keySet().stream().findFirst();if (!first.isPresent()) {return;}LOGGER.info("拨测接口:{}, 地址:{}", first.get(), api);scheduledTaskRegistrar.addFixedRateTask(() -> {int status = tryConnect(api);ThirdPartApiDto thirdPartApiDto = ThirdPartApiDto.builder().name(first.get()).api(api).interval(ThirdPartApiManager.THIRD_PART_API_TABLE.column(api).getOrDefault(first.get(), ThirdPartApiManager.INTERVAL_MICO_SECONDS)).status(status).result(JSONUtil.toJsonStr(status)).createTime(DateUtil.now()).build();apiHealthResultMap().put(first.get(), healthIndicatorFunction.apply(thirdPartApiDto));}, ThirdPartApiManager.THIRD_PART_API_TABLE.column(api).getOrDefault(first.get(), ThirdPartApiManager.INTERVAL_MICO_SECONDS));});}@Beanpublic HealthIndicator testHealthIndicator() {return () -> new Health.Builder().up().build();}public void sendLarkMessage(ThirdPartApiDto thirdPartApiDto) {// ...}
}
7、小结
Spring Actuator在实际项目中使用还是很广泛的,根据项目实际情况适当扩展或自定义各个端点,提供更契合场景的度量指标,对项目会有很大的帮助。
相关文章:

05. Springboot admin集成Actuator(一)
目录 1、前言 2、Actuator监控端点 2.1、健康检查 2.2、信息端点 2.3、环境信息 2.4、度量指标 2.5、日志文件查看 2.6、追踪信息 2.7、Beans信息 2.8、Mappings信息 3、快速使用 2.1、添加依赖 2.2、添加配置文件 2.3、启动程序 4、自定义端点Endpoint 5、自定…...

AI生成SolidUI-新版本架构调试Debug
背景 SolidUI 0.5.0 版本重构全新版本架构。 dev-python 新架构临时分支,架构调整完后,所有代码合并到dev分支 https://github.com/CloudOrc/SolidUI 使用 设置参数 FLASK_DEBUG 设置 在开发过程中,Web框架的服务器通常会监视代码的变…...

ctfshow sql 195-200
195 堆叠注入 十六进制 if(preg_match(/ |\*|\x09|\x0a|\x0b|\x0c|\x0d|\xa0|\x00|\#|\x23|\|\"|select|union|or|and|\x26|\x7c|file|into/i, $username)){$ret[msg]用户名非法;die(json_encode($ret));}可以看到没被过滤,select 空格 被过滤了,可…...
微信小程序实现地图功能(腾讯地图)
微信小程序实现地图功能(腾讯地图) 主要功能 通过微信 API 获取用户当前位置信息 使用腾讯地图 API 将经纬度转换为地址信息 显示当前位置信息以及周围的 POI(兴趣点) 代码实现 index.wxml <!-- index.wxml --> <view class"container&…...

Vue如何请求接口——axios请求
1、安装axios 在cmd或powershell打开文件后,输入下面的命令 npm install axios 可在项目框架中的package.json中查看是否: 二、引用axios import axios from axios 在需要使用的页面中引用 三、get方式使用 get请求使用params传参,本文只列举常用参数…...

【数据结构一】初始Java集合框架(前置知识)
Java中的数据结构 Java语言在设计之初有一个非常重要的理念便是:write once,run anywhere!所以Java中的数据结构是已经被设计者封装好的了,我们只需要实例化出想使用的对象,便可以操作相应的数据结构了,本篇…...
直接将第三方数据插入到 Redis 中
Redis 是一个内存数据库,可以用于缓存和持久化数据。虽然常见的使用场景是将数据从关系型数据库(如MySQL)同步到 Redis 中进行缓存,但也可以直接将第三方数据插入到 Redis 中。 你可以通过编程语言的 Redis 客户端库(…...
【重点】【DP】322.零钱兑换
题目 法1:动态规划 // 时间复杂度:O(kN) class Solution {public int coinChange(int[] coins, int amount) {int[] dp new int[amount 1];Arrays.fill(dp, amount 1);dp[0] 0;for (int i 1; i < dp.length; i) {for (int coin : coins) {if (…...

Python入门学习篇(六)——for循环while循环
1 for循环 1.1 常规for循环 1.1.1 语法结构 for 变量名 in 可迭代对象:# 遍历对象时执行的代码 else:# 当for循环全部正常运行完(没有报错和执行break)后执行的代码1.1.2 示例代码 print("----->学生检查系统<------") student_lists["张三",&qu…...

el-table 实现行拖拽排序
element ui 表格实现拖拽排序的功能,可以借助第三方插件Sortablejs来实现。 引入sortablejs npm install sortablejs --save组件中使用 import Sortable from sortablejs;<el-table ref"el-table":data"listData" row-key"id" …...

2. 结构型模式 - 桥接模式
亦称: Bridge 意图 桥接模式是一种结构型设计模式, 可将一个大类或一系列紧密相关的类拆分为抽象和实现两个独立的层次结构, 从而能在开发时分别使用 问题 抽象? 实现? 听上去挺吓人? 让我们慢慢来&#x…...

最小二乘法简介
最小二乘法简介 1、背景描述2、最小二乘法2.1、最小二乘准则2.2、最小二乘法 3、最小二乘法与线性回归3.1、最小二乘法与线性回归3.2、最小二乘法与最大似然估计 4、正态分布(高斯分布) 1、背景描述 在工程应用中,我们通常会用一组观测数据去…...

mathtype公式章节编号
1. word每章标题后插入章节符 如果插入后显示章节符,需要进行隐藏 开始->样式->MTEquationSection->修改样式->字体,勾选隐藏 2. 设置mathtype公式编号格式 插入编号->格式化->设置格式...

医学实验室检验科LIS信息系统源码
实验室信息管理是专为医院检验科设计的一套实验室信息管理系统,能将实验仪器与计算机组成网络,使病人样品登录、实验数据存取、报告审核、打印分发,实验数据统计分析等繁杂的操作过程实现了智能化、自动化和规范化管理。 实验室管理系统功能介…...

无需改动现有网络,企业高速远程访问内网Linux服务器
某企业为数据治理工具盒厂商,帮助客户摆脱数据问题困扰、轻松使用数据,使得客户可以把更多精力投入至数据应用及业务赋能,让数据充分发挥其作为生产要素的作用。 目前,该企业在北京、南京、西安、武汉等地均设有产研中心ÿ…...

Opencv入门五 (显示图片灰度值)
源码如下: #include <opencv2/opencv.hpp> int main(int argc, char** argv) { cv::Mat img_rgb, img_gry, img_cny; cv::namedWindow("Example Gray",cv::WINDOW_AUTOSIZE); cv::namedWindow("Example Canny", cv::WINDOW_…...

STM32F4 HAL流水灯Proteus仿真
源码下载:https://download.csdn.net/download/zlkk00/88654405...

【K8s】4# 使用kuboard部署开源项目实战
文章目录 1.开源项目2.实战2.1.创建spring-blade命名空间2.2.导入 spring-blade 到 K8S 名称空间2.3.设置存储卷参数2.4.调整节点端口2.5.确认导入2.6.查看集群2.7.导入配置到 nacos2.8.启动微服务工作负载 3.验证部署结果3.1.Nacos3.2. web 4.问题汇总Q1:Nacos启动…...

Mysql数据库(1)
目录 一.操作系统 二.数据库mysql 对象: 库 -> 表 -> 二维表格形式的结构化数据 常用的数据类型: MySQL的六大约束属性: SQL语句 :DDL DML DQL DCL 三.mysql的基础操作 查看当前服务器中的数据库 查看当前服务器中…...

网络安全-API接口安全
本文为作者学习文章,按作者习惯写成,如有错误或需要追加内容请留言(不喜勿喷) 本文为追加文章,后期慢慢追加 API接口概念 API接口(Application Programming Interface,应用程序编程接口&…...
前端倒计时误差!
提示:记录工作中遇到的需求及解决办法 文章目录 前言一、误差从何而来?二、五大解决方案1. 动态校准法(基础版)2. Web Worker 计时3. 服务器时间同步4. Performance API 高精度计时5. 页面可见性API优化三、生产环境最佳实践四、终极解决方案架构前言 前几天听说公司某个项…...

【网络安全产品大调研系列】2. 体验漏洞扫描
前言 2023 年漏洞扫描服务市场规模预计为 3.06(十亿美元)。漏洞扫描服务市场行业预计将从 2024 年的 3.48(十亿美元)增长到 2032 年的 9.54(十亿美元)。预测期内漏洞扫描服务市场 CAGR(增长率&…...
【Java学习笔记】BigInteger 和 BigDecimal 类
BigInteger 和 BigDecimal 类 二者共有的常见方法 方法功能add加subtract减multiply乘divide除 注意点:传参类型必须是类对象 一、BigInteger 1. 作用:适合保存比较大的整型数 2. 使用说明 创建BigInteger对象 传入字符串 3. 代码示例 import j…...

Mysql中select查询语句的执行过程
目录 1、介绍 1.1、组件介绍 1.2、Sql执行顺序 2、执行流程 2.1. 连接与认证 2.2. 查询缓存 2.3. 语法解析(Parser) 2.4、执行sql 1. 预处理(Preprocessor) 2. 查询优化器(Optimizer) 3. 执行器…...

RabbitMQ入门4.1.0版本(基于java、SpringBoot操作)
RabbitMQ 一、RabbitMQ概述 RabbitMQ RabbitMQ最初由LShift和CohesiveFT于2007年开发,后来由Pivotal Software Inc.(现为VMware子公司)接管。RabbitMQ 是一个开源的消息代理和队列服务器,用 Erlang 语言编写。广泛应用于各种分布…...
libfmt: 现代C++的格式化工具库介绍与酷炫功能
libfmt: 现代C的格式化工具库介绍与酷炫功能 libfmt 是一个开源的C格式化库,提供了高效、安全的文本格式化功能,是C20中引入的std::format的基础实现。它比传统的printf和iostream更安全、更灵活、性能更好。 基本介绍 主要特点 类型安全:…...
数据库正常,但后端收不到数据原因及解决
从代码和日志来看,后端SQL查询确实返回了数据,但最终user对象却为null。这表明查询结果没有正确映射到User对象上。 在前后端分离,并且ai辅助开发的时候,很容易出现前后端变量名不一致情况,还不报错,只是单…...

python基础语法Ⅰ
python基础语法Ⅰ 常量和表达式变量是什么变量的语法1.定义变量使用变量 变量的类型1.整数2.浮点数(小数)3.字符串4.布尔5.其他 动态类型特征注释注释是什么注释的语法1.行注释2.文档字符串 注释的规范 常量和表达式 我们可以把python当作一个计算器,来进行一些算术…...

以太网PHY布局布线指南
1. 简介 对于以太网布局布线遵循以下准则很重要,因为这将有助于减少信号发射,最大程度地减少噪声,确保器件作用,最大程度地减少泄漏并提高信号质量。 2. PHY设计准则 2.1 DRC错误检查 首先检查DRC规则是否设置正确,然…...

dvwa11——XSS(Reflected)
LOW 分析源码:无过滤 和上一关一样,这一关在输入框内输入,成功回显 <script>alert(relee);</script> MEDIUM 分析源码,是把<script>替换成了空格,但没有禁用大写 改大写即可,注意函数…...