Sentinel 监控数据持久化(mysql)
Sentinel 实时监控仅存储 5 分钟以内的数据,如果需要持久化,需要通过调用实时监控接口来定制,即自行扩展实现 MetricsRepository 接口(修改 控制台源码)。
本文通过使用Mysql持久化监控数据。
1.构建存储表(mysql)
CREATE TABLE `sentinel_metric` (`id` INT NOT NULL AUTO_INCREMENT COMMENT 'id,主键',`gmt_create` DATETIME COMMENT '创建时间',`gmt_modified` DATETIME COMMENT '修改时间',`app` VARCHAR(100) COMMENT '应用名称',`timestamp` DATETIME COMMENT '统计时间',`resource` VARCHAR(500) COMMENT '资源名称',`pass_qps` INT COMMENT '通过qps',`success_qps` INT COMMENT '成功qps',`block_qps` INT COMMENT '限流qps:拒绝的qps',`exception_qps` INT COMMENT '发送异常的次数',`rt` DOUBLE COMMENT '所有successQps的rt的和,单位ms; 控制台响应时间(平均响应时间)=rt/success_qps',`count` INT COMMENT '本次聚合的总条数: 集群的服务数量',`resource_code` INT COMMENT '资源的hashCode',INDEX app_idx(`app`) USING BTREE,INDEX timestamp_idx(`timestamp`) USING BTREE,PRIMARY KEY (`id`)
) ENGINE=INNODB DEFAULT CHARSET=utf8;
2.修改控制台源码
2.1 添加Maven依赖
<!-- mysql db --><dependency><groupId>mysql</groupId><artifactId>mysql-connector-java</artifactId><version>8.0.25</version></dependency><dependency><groupId>com.baomidou</groupId><artifactId>mybatis-plus-boot-starter</artifactId><version>3.5.1</version></dependency>
2.2 修改配置文件
spring.datasource.url=jdbc:mysql://127.0.0.1:3306/xx?useUnicode=true&characterEncoding=UTF-8
spring.datasource.username=xx
spring.datasource.password=xxxxx
spring.datasource.driver-class=com.mysql.cj.jdbc.Driver
2.3 逆向代码生成(新增)
参考:Springboot入门之Mybatis逆向工程_Ocean@上源码的博客-CSDN博客
package com.alibaba.csp.sentinel.dashboard.metric.dao;import com.alibaba.csp.sentinel.dashboard.datasource.entity.MetricEntity;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;import java.util.Date;@TableName("sentinel_metric")
public class Metric {/*** 主键ID*/@TableId(value = "id", type = IdType.INPUT)private Long id;/*** 创建时间*/@TableField("gmt_create")private Date gmtCreate;/*** 修改时间*/@TableField("gmt_modified")private Date gmtModified;/*** 应用名称*/private String app;/*** 监控信息的时间戳*/private Date timestamp;/*** 资源名*/private String resource;/*** 通过qps*/@TableField("pass_qps")private Long passQps;/*** 成功qps*/@TableField("success_qps")private Long successQps;/*** 限流qps*/@TableField("block_qps")private Long blockQps;/*** 异常qps*/@TableField("exception_qps")private Long exceptionQps;/*** 所有successQps的rt的和*/private Double rt;/*** 本次聚合的总条数*/private Integer count;/*** 资源的hashCode*/@TableField("resource_code")private Integer resourceCode;public Metric(MetricEntity metric) {this.id = metric.getId();this.gmtCreate = metric.getGmtCreate();this.gmtModified = metric.getGmtModified();this.app = metric.getApp();this.timestamp = metric.getTimestamp();this.resource = metric.getResource();this.passQps = metric.getPassQps();this.successQps = metric.getSuccessQps();this.blockQps = metric.getBlockQps();this.exceptionQps = metric.getExceptionQps();this.rt = metric.getRt();this.count = metric.getCount();this.resourceCode = metric.getResourceCode();}public Metric() {}public Long getId() {return id;}public void setId(Long id) {this.id = id;}public Date getGmtCreate() {return gmtCreate;}public void setGmtCreate(Date gmtCreate) {this.gmtCreate = gmtCreate;}public Date getGmtModified() {return gmtModified;}public void setGmtModified(Date gmtModified) {this.gmtModified = gmtModified;}public String getApp() {return app;}public void setApp(String app) {this.app = app;}public Date getTimestamp() {return timestamp;}public void setTimestamp(Date timestamp) {this.timestamp = timestamp;}public String getResource() {return resource;}public void setResource(String resource) {this.resource = resource;}public Long getPassQps() {return passQps;}public void setPassQps(Long passQps) {this.passQps = passQps;}public Long getSuccessQps() {return successQps;}public void setSuccessQps(Long successQps) {this.successQps = successQps;}public Long getBlockQps() {return blockQps;}public void setBlockQps(Long blockQps) {this.blockQps = blockQps;}public Long getExceptionQps() {return exceptionQps;}public void setExceptionQps(Long exceptionQps) {this.exceptionQps = exceptionQps;}public Double getRt() {return rt;}public void setRt(Double rt) {this.rt = rt;}public Integer getCount() {return count;}public void setCount(Integer count) {this.count = count;}public Integer getResourceCode() {return resourceCode;}public void setResourceCode(Integer resourceCode) {this.resourceCode = resourceCode;}@Overridepublic String toString() {return "SentinelMetricsEntity{" +"id=" + id +", gmtCreate=" + gmtCreate +", gmtModified=" + gmtModified +", app='" + app + '\'' +", timestamp=" + timestamp +", resource='" + resource + '\'' +", passQps=" + passQps +", successQps=" + successQps +", blockQps=" + blockQps +", exceptionQps=" + exceptionQps +", rt=" + rt +", count=" + count +", resourceCode=" + resourceCode +'}';}}
package com.alibaba.csp.sentinel.dashboard.metric.dao;import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import org.apache.ibatis.annotations.Mapper;@Mapper
public interface MetricMapper extends BaseMapper<Metric> {}
package com.alibaba.csp.sentinel.dashboard.metric.service;import com.alibaba.csp.sentinel.dashboard.datasource.entity.MetricEntity;
import com.alibaba.csp.sentinel.dashboard.metric.dao.Metric;
import com.baomidou.mybatisplus.extension.service.IService;import java.util.Collection;
import java.util.List;/*** <p>* 服务类* </p>** @author ocean* @since 2023-05-21*/
public interface MetricService extends IService<Metric> {List<String> listResourcesOfApp(String app);List<MetricEntity> queryByAppAndResourceBetween(String app, String resource, Long startTime, Long endTime);void saveAll(Iterable<MetricEntity> metrics);}
package com.alibaba.csp.sentinel.dashboard.metric.service.impl;import com.alibaba.csp.sentinel.dashboard.datasource.entity.MetricEntity;
import com.alibaba.csp.sentinel.dashboard.metric.dao.Metric;
import com.alibaba.csp.sentinel.dashboard.metric.dao.MetricMapper;
import com.alibaba.csp.sentinel.dashboard.metric.service.MetricService;
import com.alibaba.csp.sentinel.util.StringUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.google.common.collect.Lists;
import org.springframework.stereotype.Service;import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.concurrent.locks.ReentrantReadWriteLock;
import java.util.stream.Collectors;@Service
public class MetricServiceImpl extends ServiceImpl<MetricMapper, Metric> implements MetricService {private final ReentrantReadWriteLock readWriteLock = new ReentrantReadWriteLock();@Overridepublic void saveAll(Iterable<MetricEntity> metrics) {if (metrics == null) {return;}readWriteLock.writeLock().lock();try {List<Metric> metricList = Lists.newArrayList();metrics.forEach(data -> {metricList.add(new Metric(data));});this.saveBatch(metricList);} finally {readWriteLock.writeLock().unlock();}}@Overridepublic List<String> listResourcesOfApp(String app) {List<String> results = new ArrayList<>();if (StringUtil.isBlank(app)) {return results;}readWriteLock.readLock().lock();try {LambdaQueryWrapper<Metric> metricLambdaQueryWrapper = Wrappers.lambdaQuery(Metric.class).eq(Metric::getApp, app).orderByAsc(Metric::getTimestamp);return this.list(metricLambdaQueryWrapper).stream().map(Metric::getResource).collect(Collectors.toList());} finally {readWriteLock.readLock().unlock();}}@Overridepublic List<MetricEntity> queryByAppAndResourceBetween(String app, String resource, Long startTime, Long endTime) {List<MetricEntity> results = new ArrayList<>();if (StringUtil.isBlank(app)) {return results;}readWriteLock.readLock().lock();try {LambdaQueryWrapper<Metric> metricLambdaQueryWrapper = Wrappers.lambdaQuery(Metric.class).eq(Metric::getApp, app).eq(Metric::getResource, resource).ge(Metric::getTimestamp, new Date(startTime)).le(Metric::getTimestamp, new Date(endTime)).orderByAsc(Metric::getTimestamp);List<Metric> metricList = this.list(metricLambdaQueryWrapper);return metricList.stream().map(MetricEntity::new).collect(Collectors.toList());} finally {readWriteLock.readLock().unlock();}}
}
2.4 修改源码
2.4.1 MetricController

修改统计时长修改如下标记处代码:
2.4.2 MetricFetcher

3. 验证查询数据库

相关文章:
Sentinel 监控数据持久化(mysql)
Sentinel 实时监控仅存储 5 分钟以内的数据,如果需要持久化,需要通过调用实时监控接口来定制,即自行扩展实现 MetricsRepository 接口(修改 控制台源码)。 本文通过使用Mysql持久化监控数据。 1.构建存储表(…...
基于法医调查算法优化概率神经网络PNN的分类预测 - 附代码
基于法医调查算法优化概率神经网络PNN的分类预测 - 附代码 文章目录 基于法医调查算法优化概率神经网络PNN的分类预测 - 附代码1.PNN网络概述2.变压器故障诊街系统相关背景2.1 模型建立 3.基于法医调查优化的PNN网络5.测试结果6.参考文献7.Matlab代码 摘要:针对PNN神…...
canvas高级动画001:文字瀑布流
canvas实例应用100 专栏提供canvas的基础知识,高级动画,相关应用扩展等信息。 canvas作为html的一部分,是图像图标地图可视化的一个重要的基础,学好了canvas,在其他的一些应用上将会起到非常重要的帮助。 文章目录 示例…...
抽象类, 接口, Object类 ---java
目录 一. 抽象类 1.1 抽象类概念 1.2 抽象类语法 1.3 抽象类特性 1.4 抽象类的作用 二. 接口 2.1 接口的概念 2.2 语法规则 2.3 接口的使用 2.4 接口间的继承 2.5 抽象类和接口的区别 三. Object类 3.1 toString() 方法 3.2 对象比较equals()方法 3.3 hash…...
SOAP 协议和 HTTP 协议:深入解读与对比
SOAP 和 HTTP 协议 SOAP 协议 SOAP( Simple Object Access Protocol)是一种用于在节点之间交换结构化数据的网络协议。它使用XML格式来传输消息。它在 HTML 和 SMTP 等应用层协议的基础上进行标记和传输。SOAP 允许进程在整个平台、语言和操作系统中进…...
Unity发布IOS后,使用xcode打包报错:MapFileParser.sh:Permissiondenied
1.错误提示 使用xcode打包错误提示:/Users/mymac/Desktop/myproject/MapFileParser.sh: Permission denied 2.解决方案 打开控制台输入:chmod ax /Users/mymac/Desktop/myproject/MapFileParser.sh。按回车键执行,然后重新使用xcode发布程序…...
2021年12月 Scratch(三级)真题解析#中国电子学会#全国青少年软件编程等级考试
Scratch等级考试(1~4级)全部真题・点这里 一、单选题(共25题,每题2分,共50分) 第1题 执行下列程序,屏幕上可以看到几只小猫? A:1 B:3 C:4 D:0 答案:B 第2题 下列程序哪个可以实现:按下空格键,播放完音乐后说“你好!”2秒? A: B: C:...
mac上Homebrew的安装与使用
打开终端:command空格 ,搜索‘’终端 ’,打开终端 在终端中输入以下命令并按下回车键: /bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)"这个命令会自动下载并安装…...
YOLOv5 分类模型 预处理 OpenCV实现
YOLOv5 分类模型 预处理 OpenCV实现 flyfish YOLOv5 分类模型 预处理 PIL 实现 YOLOv5 分类模型 OpenCV和PIL两者实现预处理的差异 YOLOv5 分类模型 数据集加载 1 样本处理 YOLOv5 分类模型 数据集加载 2 切片处理 YOLOv5 分类模型 数据集加载 3 自定义类别 YOLOv5 分类模型…...
在arm 64 环境下使用halcon算法
背景: halcon,机器视觉领域神一样得存在,在windows上,应用得特别多, 但是arm环境下使用得很少。那如何在arm下使用halcon呢。按照官方说明,arm下只提供了运行时环境,并且需要使用价值一万多人民…...
H5(uniapp)中使用echarts
1,安装echarts npm install echarts 2,具体页面 <template><view class"container notice-list"><view><view class"aa" id"main" style"width: 500px; height: 400px;"></view></v…...
QLineEdit设置掩码Ip
目的 有时,用单行编辑框想限制输入,但QLineEdit提供的setInputMask()方法用来限制输入字符或者数字还可以,但要做约束,得和验证器结合。 setInputMash()描述 此属性包含验证输入掩码 如果没有设置掩码,inputMask() …...
开源语音大语言模型来了!阿里基于Qwen-Chat提出Qwen-Audio!
论文链接:https://arxiv.org/pdf/2311.07919.pdf 开源代码:https://github.com/QwenLM/Qwen-Audio 引言 大型语言模型(LLMs)由于其良好的知识保留能力、复杂的推理和解决问题能力,在通用人工智能(AGI&am…...
缓存雪崩、击穿、穿透及解决方案_保证缓存和数据库一致性
文章目录 缓存雪崩、击穿、穿透1.缓存雪崩造成缓存雪崩解决缓存雪崩 2. 缓存击穿造成缓存击穿解决缓存击穿 3.缓存穿透造成缓存穿透解决缓存穿透 更新数据时,如何保证数据库和缓存的一致性?1. 先更新数据库?先更新缓存?解决方案 2…...
仿 美图 / 饿了么,店铺详情页功能
前言 UI有所不同,但功能差不多,商品添加购物车功能 正在写,写完会提交仓库。 效果图一:左右RecyclerView 联动 效果图二:通过点击 向上偏移至最大值 效果图三:通过点击 或 拖动 展开收缩公告 效果图四&…...
Redis Cluster主从模式详解
在软件的架构中,主从模式(Master-Slave)是使用较多的一种架构。主(Master)和从(Slave)分别部署在不同的服务器上,当主节点服务器写入数据时,同时也会将数据同步至从节点服…...
Linux技能篇-非交互式修改密码
今天的文章没有格式,简单分享一个小技能,就是标题所说–非交互式修改密码。 一、普通方式修改用户密码 最普通的修改密码的命令就是passwd命令 [rootlocalhost ~]# passwd root Changing password for user root. New password: Retype new password:…...
记一次docker服务启动失败解决过程
环境:centos 7.6 报错:start request repeated too quickly for docker.service 由于服务器修复了内核漏洞,需要重启,没想到重启后,docker启动失败了 查看状态 systemctl status docker如下图 里面有一行提示&…...
npm ERR! node-sass@4.13.0 postinstall: `node scripts/build.js`
npm ERR! node-sass4.13.0 postinstall: node scripts/build.js npm config set sass_binary_sitehttps://npm.taobao.org/mirrors/node-sass npm install npm run dev Microsoft Windows [版本 10.0.19045.2965] (c) Microsoft Corporation。保留所有权利。C:\Users\Administr…...
Java定时任务 ScheduledThreadPoolExecutor
ScheduledThreadPoolExecutor 的创建 ScheduledThreadPoolExecutor executorService new ScheduledThreadPoolExecutor(1, // 核心线程数new BasicThreadFactory.Builder().namingPattern("example-schedule-pool-%d") // 线程命名规则.daemon(true) // 设置线程为…...
论文解读:交大港大上海AI Lab开源论文 | 宇树机器人多姿态起立控制强化学习框架(二)
HoST框架核心实现方法详解 - 论文深度解读(第二部分) 《Learning Humanoid Standing-up Control across Diverse Postures》 系列文章: 论文深度解读 + 算法与代码分析(二) 作者机构: 上海AI Lab, 上海交通大学, 香港大学, 浙江大学, 香港中文大学 论文主题: 人形机器人…...
1.3 VSCode安装与环境配置
进入网址Visual Studio Code - Code Editing. Redefined下载.deb文件,然后打开终端,进入下载文件夹,键入命令 sudo dpkg -i code_1.100.3-1748872405_amd64.deb 在终端键入命令code即启动vscode 需要安装插件列表 1.Chinese简化 2.ros …...
使用van-uploader 的UI组件,结合vue2如何实现图片上传组件的封装
以下是基于 vant-ui(适配 Vue2 版本 )实现截图中照片上传预览、删除功能,并封装成可复用组件的完整代码,包含样式和逻辑实现,可直接在 Vue2 项目中使用: 1. 封装的图片上传组件 ImageUploader.vue <te…...
鸿蒙中用HarmonyOS SDK应用服务 HarmonyOS5开发一个医院查看报告小程序
一、开发环境准备 工具安装: 下载安装DevEco Studio 4.0(支持HarmonyOS 5)配置HarmonyOS SDK 5.0确保Node.js版本≥14 项目初始化: ohpm init harmony/hospital-report-app 二、核心功能模块实现 1. 报告列表…...
【Web 进阶篇】优雅的接口设计:统一响应、全局异常处理与参数校验
系列回顾: 在上一篇中,我们成功地为应用集成了数据库,并使用 Spring Data JPA 实现了基本的 CRUD API。我们的应用现在能“记忆”数据了!但是,如果你仔细审视那些 API,会发现它们还很“粗糙”:有…...
三体问题详解
从物理学角度,三体问题之所以不稳定,是因为三个天体在万有引力作用下相互作用,形成一个非线性耦合系统。我们可以从牛顿经典力学出发,列出具体的运动方程,并说明为何这个系统本质上是混沌的,无法得到一般解…...
关于 WASM:1. WASM 基础原理
一、WASM 简介 1.1 WebAssembly 是什么? WebAssembly(WASM) 是一种能在现代浏览器中高效运行的二进制指令格式,它不是传统的编程语言,而是一种 低级字节码格式,可由高级语言(如 C、C、Rust&am…...
Spring Cloud Gateway 中自定义验证码接口返回 404 的排查与解决
Spring Cloud Gateway 中自定义验证码接口返回 404 的排查与解决 问题背景 在一个基于 Spring Cloud Gateway WebFlux 构建的微服务项目中,新增了一个本地验证码接口 /code,使用函数式路由(RouterFunction)和 Hutool 的 Circle…...
九天毕昇深度学习平台 | 如何安装库?
pip install 库名 -i https://pypi.tuna.tsinghua.edu.cn/simple --user 举个例子: 报错 ModuleNotFoundError: No module named torch 那么我需要安装 torch pip install torch -i https://pypi.tuna.tsinghua.edu.cn/simple --user pip install 库名&#x…...
vulnyx Blogger writeup
信息收集 arp-scan nmap 获取userFlag 上web看看 一个默认的页面,gobuster扫一下目录 可以看到扫出的目录中得到了一个有价值的目录/wordpress,说明目标所使用的cms是wordpress,访问http://192.168.43.213/wordpress/然后查看源码能看到 这…...

