SpringBoot定时监控数据库状态

1.application.properties配置文件

# config for mysql
spring.datasource.url = jdbc\:mysql\://127.0.0.1\:3306/数据库名?characterEncoding\=utf8&useSSL\=false
spring.datasource.username = 账号
spring.datasource.password = 密码
spring.datasource.validation-query= SELECT 1
spring.jpa.properties.hibernate.dialect =org.hibernate.dialect.MySQL5Dialect
#spring.datasource.druid.driver-class-name=com.mysql.cj.jdbc.driver
# ================ 重连配置 ================
# 最大重试次数
spring.datasource.druid.connection-error-retry-attempts=10
# 重试间隔时间(毫秒)
spring.datasource.druid.time-between-connect-error-millis=10000
# 获取连接失败后中断
spring.datasource.druid.break-after-acquire-failure=false# 自定义监控配置
monitoring.database.enabled=true
#30秒检查一次
monitoring.database.interval=30000
#5秒超时
monitoring.database.connection-timeout=5000

2.引入对应依赖

          <dependency><groupId>mysql</groupId><artifactId>mysql-connector-java</artifactId><version>8.0.33</version><!-- 明确排除旧版依赖冲突 --><exclusions><exclusion><groupId>mysql</groupId><artifactId>mysql-connector-java</artifactId></exclusion></exclusions></dependency><!-- Druid 连接池 --><dependency><groupId>com.alibaba</groupId><artifactId>druid-spring-boot-starter</artifactId><version>1.2.16</version></dependency>
<!-- Spring Actuator for Health Checks --><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-actuator</artifactId></dependency>
<!-- 内置的有Schedul的依赖 --><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId></dependency>

3.代码实现

package com.dianju.signatureServer;import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import srvSeal.SrvSealUtil;import javax.annotation.PostConstruct;
import java.sql.*;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.concurrent.atomic.AtomicLong;@RestController
@RequestMapping("/monitorservice")
public class MonitorController {private final Logger log = LoggerFactory.getLogger(this.getClass());@Value("${spring.datasource.url}")private String jdbcUrl;@Value("${spring.datasource.username}")private String username;@Value("${spring.datasource.password}")private String password;@Value("${spring.datasource.validation-query}")private String validationQuery;@Value("${monitoring.database.interval}")private long checkInterval;@Value("${monitoring.database.connection-timeout}")private int connectionTimeout;// 状态跟踪变量private final AtomicInteger consecutiveFailures = new AtomicInteger(0);private final AtomicLong lastFailureTime = new AtomicLong(0);private final AtomicLong lastSuccessTime = new AtomicLong(System.currentTimeMillis());@Autowiredprivate SrvSealUtil srvSealUtil;@PostConstructpublic void init() {try {// 显式加载MySQL驱动Class.forName("com.mysql.cj.jdbc.Driver");log.info("✅ MySQL驱动加载成功");// 打印配置信息log.info("数据库监控配置:");log.info("连接URL: {}", jdbcUrl);log.info("用户名: {}", username);log.info("验证查询: {}", validationQuery);log.info("监控间隔: {}ms", checkInterval);log.info("连接超时: {}ms", connectionTimeout);} catch (ClassNotFoundException e) {log.error("❌ 加载MySQL驱动失败", e);throw new RuntimeException("数据库驱动加载失败", e);}}@Scheduled(fixedRateString = "${monitoring.database.interval}")public void monitorDatabase() {long startTime = System.currentTimeMillis();boolean isHealthy = checkDatabaseHealth();long responseTime = System.currentTimeMillis() - startTime;if (isHealthy) {handleSuccess(responseTime);} else {handleFailure();}}private boolean checkDatabaseHealth() {try (Connection conn = DriverManager.getConnection(buildConnectionUrl(),username,password)) {try (Statement stmt = conn.createStatement();ResultSet rs = stmt.executeQuery(validationQuery)) {return rs.next() && rs.getInt(1) == 1;}} catch (Exception e) {log.error("❌ 数据库健康检查失败", e);return false;}}// 正确构建带超时的连接URLprivate String buildConnectionUrl() {StringBuilder urlBuilder = new StringBuilder(jdbcUrl);if (jdbcUrl.contains("?")) {urlBuilder.append("&connectTimeout=").append(connectionTimeout);} else {urlBuilder.append("?connectTimeout=").append(connectionTimeout);}return urlBuilder.toString();}private void handleSuccess(long responseTime) {// 重置失败计数器consecutiveFailures.set(0);// 更新最后成功时间lastSuccessTime.set(System.currentTimeMillis());// 如果之前有失败记录,输出恢复信息if (lastFailureTime.get() > 0) {long downTime = System.currentTimeMillis() - lastFailureTime.get();log.info("\n🔥 数据库恢复可用! 宕机时长: {}秒\n", downTime / 1000);// 重置失败时间戳lastFailureTime.set(0);}// 输出正常日志log.info("✅ 数据库正常 | 响应时间: {}ms", responseTime);}private void handleFailure() {// 增加失败计数int failures = consecutiveFailures.incrementAndGet();// 记录第一次失败时间if (failures == 1) {lastFailureTime.set(System.currentTimeMillis());}// 获取宕机时长(秒)long downTime = 0;if (lastFailureTime.get() > 0) {downTime = (System.currentTimeMillis() - lastFailureTime.get()) / 1000;}// 输出错误日志log.error("❌ 数据库连接失败 | 连续失败次数: {} | 宕机时长: {}秒", failures, downTime);}// 获取数据库状态(供其他服务查询)public boolean isDatabaseUp() {return consecutiveFailures.get() == 0;}// 获取数据库最后健康时间public long getLastHealthyTime() {return lastSuccessTime.get();}}

断开mysql连接,会自动尝试重连,并记录宕机时长

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。
如若转载,请注明出处:http://www.pswp.cn/web/84179.shtml
繁体地址,请注明出处:http://hk.pswp.cn/web/84179.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Qt联合Halcon开发一:Qt配置Halcon环境【详细图解流程】

在Qt中使用Halcon库进行图像处理开发&#xff0c;可以有效地结合Qt的图形界面和Halcon强大的计算机视觉功能。下面是详细的配置过程&#xff0c;帮助你在Qt项目中成功集成Halcon库。 步骤 1: 安装Halcon软件并授权 首先&#xff0c;确保你已经在电脑上安装了Halcon软件&#x…

一体化(HIS系统)医院信息系统,让医疗数据互联互通

在医疗信息化浪潮下&#xff0c;HIS系统、LIS系统、PACS系统、电子病历系统等信息系统成为医疗机构必不可少的一部分&#xff0c;从患者挂号到看诊&#xff0c;从各种检查到用药&#xff0c;从院内治疗到院外管理……医疗机构不同部门、不同科室的各类医疗、管理业务几乎都初步…

Spring Boot 的 3 种二级缓存落地方式

在高并发系统设计中&#xff0c;缓存是提升性能的关键策略之一。随着业务的发展&#xff0c;单一的缓存方案往往无法同时兼顾性能、可靠性和一致性等多方面需求。 此时&#xff0c;二级缓存架构应运而生&#xff0c;本文将介绍在Spring Boot中实现二级缓存的三种方案。 一、二…

Android Studio Profiler使用

一:memory 参考文献: AndroidStudio之内层泄漏工具Profiler使用指南_android studio profiler-CSDN博客

Zephyr boot

<!DOCTYPE html> <html lang"zh-CN"> <head> <meta charset"UTF-8"> <meta name"viewport" content"widthdevice-width, initial-scale1.0"> <title>Zephyr设备初始化机制交互式解析…

腾讯地图Web版解决热力图被轮廓覆盖的问题

前言 你好&#xff0c;我是喵喵侠。 还记得那天傍晚&#xff0c;我正对着电脑调试一个腾讯地图的热力图页面。项目是一个区域人流密度可视化模块&#xff0c;我加了一个淡蓝色的轮廓图层用于表示区域范围&#xff0c;热力图放在下面用于展示人流热度。效果一预览&#xff0c;…

【JVMGC垃圾回收场景总结】

文章目录 CMS在并发标记阶段&#xff0c;已经被标记的对象&#xff0c;又被新生代跨带引用&#xff0c;这时JVM会怎么处理?为什么 Minor GC 会发生 STW&#xff1f;有哪些对象是在栈上分配的&#xff1f;对象在 JVM 中的内存结构为什么需要对齐填充&#xff1f;JVM 对象分配空…

3_STM32开发板使用(STM32F103ZET6)

STM32开发板使用(STM32F103ZET6) 一、概述 当前所用开发板为正点原子精英板,MCU: STM32F103ZET6。一般而言,拿到板子之后先要对板子有基础的认识,包括对开发板上电开机、固件下载、调试方法这三个部分有基本的掌握。 二、系统开机 2.1 硬件连接 直接接电源线或Type-c线…

crackme012

crackme012 名称值软件名称attackiko.exe加壳方式无保护方式serial编译语言Delphi v1.0调试环境win10 64位使用工具x32dbg,PEid破解日期2025-06-18 -发现是 16位windows 程序环境还没搭好先留坑

CppCon 2016 学习:I Just Wanted a Random Integer

你想要一个随机整数&#xff0c;用于模拟随机大小的DNA读取片段&#xff08;reads&#xff09;&#xff0c;希望覆盖不同长度范围&#xff0c;也能测试边界情况。 代码部分是&#xff1a; #include <cstdlib> auto r std::rand() % 100;它生成一个0到99之间的随机整数&…

MySQL层级查询实战:无函数实现部门父路径

本次需要击毙的MySQL函数 函数主要用于获取部门的完整层级路径&#xff0c;方便在应用程序或SQL查询中直接调用&#xff0c;快速获得部门的上下级关系信息。执行该函数之后简单使用SQL可以实现数据库中部门名称查询。例如下面sql select name,GetDepartmentParentNames(du.de…

Python初学者教程:如何从文本中提取IP地址

Python初学者教程:如何从文本中提取IP地址 在网络安全和数据分析领域,经常需要从文本文件中提取IP地址。本文将引导您使用Python创建一个简单但实用的工具,用于从文本文件提取所有IP地址并将其保存到新文件中。即使您是编程新手,也可以跟随本教程学习Python的基础知识! …

【Redis】Redis核心探秘:数据类型的编码实现与高速访问之道

&#x1f4da;️前言 &#x1f31f;&#x1f31f;&#x1f31f;精彩导读 本次我们将全面剖析Redis的核心技术要点&#xff0c;包括其丰富的数据类型体系、高效的编码方式以及秒级响应的性能奥秘。对于渴望深入理解Redis底层机制的技术爱好者&#xff0c;这是一次难得的学习机会…

Halcon —— 多种二维码检测

工业视觉实战&#xff1a;Halcon多类型二维码识别技术详解 在工业自动化场景中&#xff0c;兼容多种二维码类型是提高生产线灵活性的关键。本文将深入解析Halcon实现Data Matrix、QR Code和PDF417三种主流二维码的兼容识别方案&#xff0c;并重点解释核心算子参数。 一、多类型…

安卓vscodeAI开发实例

前言 前些天发现了一个巨牛的人工智能免费学习网站&#xff0c;通俗易懂&#xff0c;风趣幽默&#xff0c;忍不住分享一下给大家。点击跳转到网站 目录 一、安卓开发基础与工具链革新 1.1 Android Studio的局限性分析 1.2 VSCode在移动开发中的崛起 1.3 跨平台开发工具链对比…

③通用搜索---解析FastAdmin中的表格列表的功能

深度解析FastAdmin中的表格列表的功能-CSDN博客文章浏览阅读25次。本文将FastAdmin框架的CRUD功能配置要点进行了系统梳理。官方文档与开发经验相结合&#xff0c;详细介绍了菜单显示、TAB过滤、通用搜索、工具栏按钮、动态统计、快速搜索等17项功能的配置方法。包括字段渲染&a…

DeepSeek 助力 Vue3 开发:打造丝滑的日历(Calendar),日历_项目里程碑示例(CalendarView01_22)

前言&#xff1a;哈喽&#xff0c;大家好&#xff0c;今天给大家分享一篇文章&#xff01;并提供具体代码帮助大家深入理解&#xff0c;彻底掌握&#xff01;创作不易&#xff0c;如果能帮助到大家或者给大家一些灵感和启发&#xff0c;欢迎收藏关注哦 &#x1f495; 目录 Deep…

Python爬虫实战:获取Diesel电商数据并分析

1. 引言 在当今数字化时代,电商平台积累了海量的产品和用户数据。通过对这些数据的挖掘和分析,企业可以深入了解市场动态、消费者需求和竞争态势,从而制定更有效的营销策略和产品规划。Diesel 作为知名的时尚品牌,其在电商平台上的表现备受关注。本研究旨在通过 Python 爬…

Spring RestTemplate + MultiValueMap vs OkHttp 多值参数的处理

&#x1f4cc; Spring RestTemplate vs OkHttp&#xff1a;多值参数处理 一、MultiValueMap 与 FormBody 的差异 特性RestTemplate MultiValueMapOkHttp FormBody多值参数支持✅ 原生支持&#xff08;add("key", "value") 自动追加&#xff09;❌ 需显…

GelSight视触觉3D轮廓仪赋能Beomni人形机器人触觉遥测,开启人形机器人触觉应用新场景

在智能制造、航空航天等领域&#xff0c;传统机器人常面临操作精度不足、环境适应力弱等问题。GelSight触觉传感技术与Beomni人形机器人的融合&#xff0c;为这些场景提供了新可能 —— 通过亚微米级触觉感知能力&#xff0c;操作员可远程感知物体表面细节&#xff0c;在复杂环…