监控系统
2025-10-20 19:28:08 0 举报
AI智能生成
监控系统的介绍,监控系统的实现,服务器监控,jvm监控,线程池监控,redis监控,mq监控,ES监控,mysql监控,业务监控
作者其他创作
大纲/内容
监控方案设计
1、每个应用自监控或者统一上报监控?
自监控
应用自监控,就是每个应用实例的监控数据存放在应用本身,比如一个Map。然后通过JMX或者其他方式暴露出去。然后开发人员可以通过JConsole或者API(一般是Web界面)得到这些监控数据。比如Druid就是这种做法。访问: hk01-xxxx-mob03.hk01:8090/druid/index.html 得到hk01-xxxx-mob03.hk01:8090这个应用的监控数据。
统一监控
统一上报监控方式,就是所有的应用监控数据都上报到监控中心,由监控中心负责接收、分析、合并、存储、可视化查询、报警等逻辑。这种方式是瘦客户端模型,客户端的职责就是埋点上报监控数据。所有的监控逻辑都在中心处理
结论
自监控的话实现起来简单,并且没有与监控中心的网络交互,性能也会好很多。但是缺点就是缺乏全局的统计和监控。从实用角度来说还是集中式监控好一些。
2、监控中心与客户端应用之间要不要通过本地Agent上报?
agent上报
一个物理机上的多台服务器通过一个统一的agent向监控中心上报监控数据
独立上报
一个物理机上的多台服务器各自向监控中心上报统计数据
结论
网络通常的情况下,直接独立上报
3、存储最终状态还是事件序列
最终状态
经过业务逻辑的处理,得到相关的统计数据,然后再做储存
事件序列
直接就存储上报的统计信息本身的数据
结论
最终状态还是弱了一些,事件序列会好一些,存储可以采用HBase这样的分布式存储系统,性能问题可以采用预聚合等方式解决
4、数据存储
因为Events或者Metrics的特殊性,一般都会采用一种专门的存储结构——Distributed time series database
RRD(round-robin-database): RRDtool使用的底层存储。C语言编写的。性能比较高
whisper: Graphite底层的存储,Python写的
prometheus: An open-source service monitoring system and time series database. 目前只有单机版本。
InfluxDB: 开源distributed time series, metrics, and events database。Go语言编写, 不依赖于其他外部服务。底层支持多种存储引擎,目前是LevelDB, RocksDB, HyberLevelDB和LMDB(0.9之后将只支持Bolt)。
OpenTSDB: 基于HBase编写的Time Series Database
结论
如果要存储事件序列,那么InfluexDB和OpenTSDB是个非常不错的选择。都是可扩展,分布式存储,文档很详细,还是开源的。 influexDB 0.9.0之后支持tag,使用风格跟Google Cloud Monitor很相似,而且支持String类型。并且最重要的是不需要额外搭建HBase(Thus Hadoop & Zookeeper),看起来非常值得期待,不过截至今天0.9.0还是RC阶段(非Stable)。OpenTSDBvalue不支持String类型,这意味着日志不能上报到OpenTSDB,需要另外处理。
5、如果服务器挂掉了,统计数据怎么处理?缓存本地,等服务器起来再发送?还是丢弃?
前期可以先丢弃,后续要缓存起来。受影响比较大的是counter接口。
存储的话,可以考虑使用本地存储在RRD文件或者BDB中,或者消息队列中(RabbitMQ, ie.),最后再异步批量上报给中心的TSDB。
6、网络通信和协议
如何高性能的接收大量客户端的上报请求。以及使用什么通讯协议
有几种选择:
HTTP
TCP
UDP: fire and forget, 主要需要注意MTU问题。
HTTP
TCP
UDP: fire and forget, 主要需要注意MTU问题。
同时要考虑同步和异步接口
各种应用监控
数据库监控
mysql监控
java监听Mysql数据变化
具体步骤
1、修改配置
log-bin=mysql-bin #[必须]启用二-进制日志
server-id=100 #[必须]服务器唯一ID,如果是用于多台MySQL,ID不要重复就行
binlog-format = ROW
server-id=100 #[必须]服务器唯一ID,如果是用于多台MySQL,ID不要重复就行
binlog-format = ROW
binlog-format = ROW,binlog_format 设置为 ROW可以保证数据的一致, 因为在 STATEMENT 或 MIXED 模式下, Binlog 只会记录和传输 SQL 语句(以减少日志大小),而不包含具体数据,我们也就无法保存了。
2、引入依赖包
<dependency>
<groupId>com.zendesk</groupId>
<artifactId>mysql-binlog-connector-java</artifactId>
<version>0.27.1</version> <!--2022.09.17版的-->
</dependency>
<groupId>com.zendesk</groupId>
<artifactId>mysql-binlog-connector-java</artifactId>
<version>0.27.1</version> <!--2022.09.17版的-->
</dependency>
3、具体代码demo
//为什么甚至路径都一样,还是com.github.shyiko.***,
// 因为com.zendesk这个包,里面包了个com.github.shyiko.***这玩意,我怀疑是收购关系
import com.github.shyiko.mysql.binlog.BinaryLogClient;
import com.github.shyiko.mysql.binlog.event.*;
import org.springframework.boot.ApplicationArguments;
import org.springframework.boot.ApplicationRunner;
import org.springframework.stereotype.Component;
import lombok.extern.slf4j.Slf4j;
import java.io.IOException;
//此类可以监控MySQL库数据的增删改
@Component
@Slf4j //用于打印日志
//在SpringBoot中,提供了一个接口:ApplicationRunner。
//该接口中,只有一个run方法,他执行的时机是:spring容器启动完成之后,就会紧接着执行这个接口实现类的run方法。
public class MysqlBinLogClient implements ApplicationRunner {
@Override
public void run(ApplicationArguments args) throws Exception {
//项目启动完成连接bin-log
new Thread(() -> {
connectMysqlBinLog();
}).start();
}
/**
* 连接mysqlBinLog
*/
public void connectMysqlBinLog() {
log.info("监控BinLog服务已启动");
//自己MySQL的信息。host,port,username,password
BinaryLogClient client = new BinaryLogClient("localhost", 3306, "root", "root");
/**因为binlog不是以数据库为单位划分的,所以监控binglog不是监控的单个的数据库,而是整个当前所设置连接的MySQL,
*其中任何一个库发生数据增删改,这里都能检测到,
*所以不用设置所监控的数据库的名字(我也不知道怎么设置,没发现有包含这个形参的构造函数)
*如果需要只监控指定的数据库,可以看后面代码,可以获取到当前发生变更的数据库名称。可以根据名称来决定是否监控
**/
client.setServerId(100); //和自己之前设置的server-id保持一致,但是我不知道为什么不一致也能成功
//下面直接照抄就行
client.registerEventListener(event -> {
EventData data = event.getData();
if (data instanceof TableMapEventData) {
//只要连接的MySQL发生的增删改的操作,则都会进入这里,无论哪个数据库
TableMapEventData tableMapEventData = (TableMapEventData) data;
//可以通过转成TableMapEventData类实例的tableMapEventData来获取当前发生变更的数据库
System.out.println("发生变更的数据库:"+tableMapEventData.getDatabase());
System.out.print("TableID:");
//表ID
System.out.println(tableMapEventData.getTableId());
System.out.print("TableName:");
//表名字
System.out.println(tableMapEventData.getTable());
}
//表数据发生修改时触发
if (data instanceof UpdateRowsEventData) {
System.out.println("Update:");
System.out.println(data.toString());
//表数据发生插入时触发
} else if (data instanceof WriteRowsEventData) {
System.out.println("Insert:");
System.out.println(data.toString());
//表数据发生删除后触发
} else if (data instanceof DeleteRowsEventData) {
System.out.println("Delete:");
System.out.println(data.toString());
}
});
try {
client.connect();
} catch (IOException e) {
e.printStackTrace();
}
}
}
// 因为com.zendesk这个包,里面包了个com.github.shyiko.***这玩意,我怀疑是收购关系
import com.github.shyiko.mysql.binlog.BinaryLogClient;
import com.github.shyiko.mysql.binlog.event.*;
import org.springframework.boot.ApplicationArguments;
import org.springframework.boot.ApplicationRunner;
import org.springframework.stereotype.Component;
import lombok.extern.slf4j.Slf4j;
import java.io.IOException;
//此类可以监控MySQL库数据的增删改
@Component
@Slf4j //用于打印日志
//在SpringBoot中,提供了一个接口:ApplicationRunner。
//该接口中,只有一个run方法,他执行的时机是:spring容器启动完成之后,就会紧接着执行这个接口实现类的run方法。
public class MysqlBinLogClient implements ApplicationRunner {
@Override
public void run(ApplicationArguments args) throws Exception {
//项目启动完成连接bin-log
new Thread(() -> {
connectMysqlBinLog();
}).start();
}
/**
* 连接mysqlBinLog
*/
public void connectMysqlBinLog() {
log.info("监控BinLog服务已启动");
//自己MySQL的信息。host,port,username,password
BinaryLogClient client = new BinaryLogClient("localhost", 3306, "root", "root");
/**因为binlog不是以数据库为单位划分的,所以监控binglog不是监控的单个的数据库,而是整个当前所设置连接的MySQL,
*其中任何一个库发生数据增删改,这里都能检测到,
*所以不用设置所监控的数据库的名字(我也不知道怎么设置,没发现有包含这个形参的构造函数)
*如果需要只监控指定的数据库,可以看后面代码,可以获取到当前发生变更的数据库名称。可以根据名称来决定是否监控
**/
client.setServerId(100); //和自己之前设置的server-id保持一致,但是我不知道为什么不一致也能成功
//下面直接照抄就行
client.registerEventListener(event -> {
EventData data = event.getData();
if (data instanceof TableMapEventData) {
//只要连接的MySQL发生的增删改的操作,则都会进入这里,无论哪个数据库
TableMapEventData tableMapEventData = (TableMapEventData) data;
//可以通过转成TableMapEventData类实例的tableMapEventData来获取当前发生变更的数据库
System.out.println("发生变更的数据库:"+tableMapEventData.getDatabase());
System.out.print("TableID:");
//表ID
System.out.println(tableMapEventData.getTableId());
System.out.print("TableName:");
//表名字
System.out.println(tableMapEventData.getTable());
}
//表数据发生修改时触发
if (data instanceof UpdateRowsEventData) {
System.out.println("Update:");
System.out.println(data.toString());
//表数据发生插入时触发
} else if (data instanceof WriteRowsEventData) {
System.out.println("Insert:");
System.out.println(data.toString());
//表数据发生删除后触发
} else if (data instanceof DeleteRowsEventData) {
System.out.println("Delete:");
System.out.println(data.toString());
}
});
try {
client.connect();
} catch (IOException e) {
e.printStackTrace();
}
}
}
参考文档
https://blog.csdn.net/qq_45821251/article/details/127490460
https://blog.csdn.net/chengsw1993/article/details/119328869
监控工具
SigNoz
Prometheus
MySQL Enterprise Monitor
MySQL 企业版附带了 MySQL 企业级监视器
特性
基于云的远程监控
查询分析可视化
支持 MySQL 集群监控
实时健康状态上报、可用性监控
易于配置
Paessler PRTG Network Monitor
Sematext
Solarwinds
开源监控系统
Prometheus
Prometheus相关介绍
概述
Prometheus是一个开源的系统监控和警报工具包
历史
最初由SoundCloud构建。自2012年成立以来,许多公司和组织都采用了Prometheus,该项目拥有非常活跃的开发人员和用户社区。它现在是一个独立的开源项目,独立于任何公司进行维护
Prometheus于2016年加入了云原生计算基金会,成为Kubernetes之后的第二个托管项目
特点
1、一个多维数据模型,其时间序列数据由度量名称和键/值对标识
2、有自己独有的的查询语言,PromQL
3、不依赖分布式存储;单个服务器节点是自治的
但是可以把采集到的数据再次被同步到其他平台,或者数据存储库
Prometheus有具体的接口可以提供查询指标数据
对应的第三方的支持将数据导入到第三方
4、(统计指标)收集通过HTTP上的拉模型进行
5、通过中间网关支持推送(统计指标)时间序列
6、被采集的服务是通过服务发现或者静态配置的
7、支持多种模式的图形化和仪表板
架构
具体组件
1、主服务器,用于采集存储统计指标数据
2、搭载在各种客户端库数据采集器
3、数据推送网关
4、各种导出组件
5、告警组件
6、支持各种第三方工具
架构图
使用场景
1、以机器为核心的监控
2、多维度手机和查询数据
3、可靠性
不适合的场景
1、需要百分之百保证数据准确性
Prometheus收集到的数据并不是非常详细完整
Prometheus统计指标
Prometheus客户端库提供了四种核心指标类型
总和 Counter
计数器是一种累积度量,表示一个单调递增的计数器,其值只能在重新启动时增加或重置为零
例如,您可以使用计数器来表示服务的请求、完成的任务或错误的数量
Gauge
度量是指表示单个数值的度量,该数值可以任意上下波动
内存使用的最大子,最小值
Histogram
直方图对观测值进行采样(通常是请求持续时间或响应大小),并将它们计数在可配置的桶中
Summary
与直方图类似,摘要对观察结果进行抽样(通常是请求持续时间和响应大小)。虽然它也提供了观测的总数和所有观测值的总和,但它可以在滑动时间窗口上计算可配置的分位数。
Prometheus监控
Exporter
广义上讲所有可以向Prometheus提供监控样本数据的程序都可以被称为一个Exporter,Exporter的一个实例称为target
数据导出器
导出器来源
社区
用户自定义
需要根据基于Prometheus提供的Client Library创建自己的Exporter程序
Promthues社区官方提供了对以下编程语言的支持:Go、Java/Scala、Python、Ruby
导出器的运行方式
独立使用
需要独立部署的
MySQL Exporter、Redis Exporter等都是通过这种方式实现
集成到应用中
为了能够更好的监控系统的内部运行状态,有些开源项目如Kubernetes,ETCD等直接在代码中使用了Prometheus的Client Library,提供了对Prometheus的直接支持。这种方式打破的监控的界限,让应用程序可以直接将内部的运行状态暴露给Prometheus,适合于一些需要更多自定义监控指标需求的项目。
自定义export
需要在自定义的程序中引入prometheus的依赖包,且需要和prometheus定义通讯连接
Prometheus 监控 Java 应用
监控方式
使用官方提供的jar包,然后嵌入到应用中
这种方式一般都是新项目
prometheus的jmx_exporter
具体监控实施文档
https://blog.csdn.net/qq_25934401/article/details/82185236
https://blog.csdn.net/penngo/article/details/126982183
监控容器
cAdvisor
介绍
CAdvisor是Google开源的一款用于展示和分析容器运行状态的可视化工具
通过在主机上运行CAdvisor用户可以轻松的获取到当前主机上容器的运行统计信息,并以图表的形式向用户展示
CAdvisor默认只保存2分钟的监控数据
CAdvisor已经内置了对Prometheus的支持
相对于docker命令行工具
用户不用再登录到服务器中即可以可视化图表的形式查看主机上所有容器的运行状态
典型指标
container_cpu_load_average_10s gauge 过去10秒容器CPU的平均负载
container_cpu_usage_seconds_total counter 容器在每个CPU内核上的累积占用时间 (单位:秒)
container_cpu_system_seconds_total counter System CPU累积占用时间(单位:秒)
container_cpu_user_seconds_total counter User CPU累积占用时间(单位:秒)
container_fs_usage_bytes gauge 容器中文件系统的使用量(单位:字节)
container_fs_limit_bytes gauge 容器可以使用的文件系统总量(单位:字节)
container_fs_reads_bytes_total counter 容器累积读取数据的总量(单位:字节)
container_fs_writes_bytes_total counter 容器累积写入数据的总量(单位:字节)
container_memory_max_usage_bytes gauge 容器的最大内存使用量(单位:字节)
container_memory_usage_bytes gauge 容器当前的内存使用量(单位:字节
container_spec_memory_limit_bytes gauge 容器的内存使用量限制
machine_memory_bytes gauge 当前主机的内存总量
container_network_receive_bytes_total counter 容器网络累积接收数据总量(单位:字节)
container_network_transmit_bytes_total counter 容器网络累积传输数据总量(单位:字节)
container_cpu_usage_seconds_total counter 容器在每个CPU内核上的累积占用时间 (单位:秒)
container_cpu_system_seconds_total counter System CPU累积占用时间(单位:秒)
container_cpu_user_seconds_total counter User CPU累积占用时间(单位:秒)
container_fs_usage_bytes gauge 容器中文件系统的使用量(单位:字节)
container_fs_limit_bytes gauge 容器可以使用的文件系统总量(单位:字节)
container_fs_reads_bytes_total counter 容器累积读取数据的总量(单位:字节)
container_fs_writes_bytes_total counter 容器累积写入数据的总量(单位:字节)
container_memory_max_usage_bytes gauge 容器的最大内存使用量(单位:字节)
container_memory_usage_bytes gauge 容器当前的内存使用量(单位:字节
container_spec_memory_limit_bytes gauge 容器的内存使用量限制
machine_memory_bytes gauge 当前主机的内存总量
container_network_receive_bytes_total counter 容器网络累积接收数据总量(单位:字节)
container_network_transmit_bytes_total counter 容器网络累积传输数据总量(单位:字节)
和Prometheus集成
先启动cadvisor
Prometheus配置文件中配置cadvisor的ip地址和端口
然后启动Prometheus
监控mysql数据库
监控步骤
1、先部署MySQL_Exporter
该引用并不是和mysql整合在一起
2、在Prometheus配置MySQL_Exporter的IP和端口
redis监控
同mysql监控类似,通过redis_export
Prometheus数据存储
本地存储
将2小时作为一个时间窗口产生的数据放在一个数据块里面,保存在本地磁盘上
单个Prometheus Server基本上能够应对大部分用户监控规模的需求。
Prometheus数据序列数据库设计
核心设计思想:内置了一个本地数据序列数据库
优缺点
优点
1、可降低部署和管理复杂性
2、减少高可用带来的复杂性
缺点
本地存储无法将数据持久化,无法存储大量的数据,无法做到灵活扩展和迁移
远程存储
Prometheus定义两个标准接口(读写),让用户基于这两个接口保存到任意第三方存储服务,这就是远程存储
解决数据无法持久化问题
读写
远程写
远程读
联邦集群
特点
数据的采集和数据存储是分开的
利用数据是做远程存储,可以在每一个数据监控中安装一个监控实例,这个监控实例从公用的远程存储中心获取数据。
一个实例已经处理处理上千规模的集群
原理
1、在每一个数据监控中心部署一个实例
2、由中心的实力负责聚合多个数据中心的监控数据
示意图
数据可视化
概述
prometheus本身有自己的大盘数据,但是不太好用,一般是与grafana集成在一起
grafana
Grafana官方提供了对:Graphite, InfluxDB, OpenTSDB, Prometheus, Elasticsearch, CloudWatch的支持
所以prometheus可以将数据导入到grafana大盘中
Promthues高可用部署
基本HA:服务可用性
示意图
子主题
概述
1、部署多台服务器
2、多台服务器都会向同样的一批被监控的应用或者服务采集数据
3、数据展示的时候通过nginx负载均衡后从其中一台服务器拉取数据
优缺点
优点
确保Promthues服务的可用性问题
缺点
Prometheus Server之间的数据一致性问题
持久化问题(数据丢失后无法恢复)
无法进行动态的扩展
适用场景
适合监控规模不大
Promthues Server也不会频繁发生迁移的情况
保存短周期监控数据
基本HA + 远程存储
示意图
子主题
概述
相对于基础的服务可用性,此种部署方式,让数据在远程
优缺点
优点
确保了数据持久化,增加了系统可扩展性
Promthues宕机后,可以快速回复
可进行数据迁移
适用场景
用户监控规模不大,但是希望能够将监控数据持久化,同时能够确保Promthues Server的可迁移性的场景
基本HA + 远程存储 + 联邦集群
示意图
子主题
概述
将不同的采集任务划分到不同的Promthues
使用场景
场景一:单数据中心 + 大量的采集任务
场景二:多数据中心
按照实例进行功能分区
示意图
子主题
概述
极端情况下,采集的目标数量过大,通过联邦集群进行功能分区,也无法有效处理,考虑按照被采集的对象的级别,进行区分采集
Promthues服务发现
Promthues服务发现概述
服务注册中心存储所有监控目标的访问信息,Promthues只需要去访问服务注册中心就知道需要对那些目标进行监控,这种模式成为服务发现
为什么需要有服务发现注册
很多云平台的服务,可以创建销毁应用,在这个过程被监控的对象的信息都是在变化中,但是Promthues无法动态感知到这些信息的变化,需要有一个外部注册中心来感知这个,然后Promthues通过统一的调用注册中心的信息得到这些变化的信息;
示意图
子主题
注册中心
不同的场景下,会有不同的东西来扮演注册中心
注册中心举例
平台级别的公有云
AWS公有云平台
平台级别的私有云
OpenStack的私有云平台
容易云
Kubernetes容器管理平台
文件
DNS解析
服务发现实战
基于文件的服务发现
Promthues通过读取文件中的被监控者的信息,来动态更新监控对象的信息
可以不依赖第三方的平台
基于Consul的服务发现
Consul本身是一个支持多数据中心的分布式服务发现和键值对存储服务的开源软件
被监控的服务的信息会被注册到Consul
Promthues去Consul拉取对应的被监控的信息
服务发现与Relabeling
通过自定义标签,来区分不同环境的被监控对象的信息
Nagios
Zabbix
监控系统的要求
1、快速发现故障
2、快速定位故障
3、辅助进行程序性能优化
监控维度
一、基础资源监控
1. 主机/容器资源
CPU、内存、磁盘、网络IO
容器层:Docker Stats、cAdvisor
2. 节点健康
节点是否在线、负载情况
K8s:Node Condition、Pod 状态
3. 存储和数据库
存储和数据库指标
1. 性能指标
查询响应时间(Query Latency)
单条 SQL 或事务平均耗时,慢查询监控
每秒查询数(QPS/Queries Per Second)
SQL 执行频率
并发连接数
当前活跃连接数 vs 最大连接数
事务吞吐量(TPS/Transactions Per Second)
每秒事务提交/回滚数
锁等待
死锁、行锁/表锁等待情况
缓存命中率
缓存层(如 MySQL InnoDB Buffer Pool、Redis)命中率
事务回滚率
反映异常或错误事务比例
2. 资源指标
CPU 使用率
数据库进程的 CPU 占用
内存使用
数据库缓存、buffer pool、连接缓存等内存使用
磁盘 I/O
读写吞吐量、延迟
网络 I/O
数据库与应用通信流量
数据库空间
数据文件/日志文件大小,剩余容量
3. 健康状态指标
数据库实例是否可用(Ping/Heartbeat)
子主题
主从复制延迟(MySQL、PostgreSQL 等)
数据库错误日志中的异常条数
进程数量/线程池状态
4. 业务指标(可选)
订单数量、支付事务量等业务层面的 DB 指标
这些指标有助于理解数据库负载和业务压力的关系
数据库指标获取(以mysql为例)
数据源
mysql内置监控工具
global_status
QPS、TPS、连接数、慢查询数等
global_variables
配置参数,缓存大小、线程数等
info_schema.*
表大小、索引、行数、锁等待等
perf_schema.*
SQL 执行时间分布、表锁/死锁等
慢查询日志 → 找到耗时长的 SQL
错误日志 → 监控异常事件、死锁、连接失败
数据传输
Prometheus + mysqld_exporter
通过 MySQL 提供的状态信息(主要是系统表和状态变量)采集,再以 Prometheus 可抓取的格式暴露
连接数据库,查询mysql的系统信息和信息表,将这些信息转成Prometheus 格式,通过http接口暴露给Prometheus
二、服务运行监控
1. 服务可用性(Availability)
服务实例是否存活(Health Check)
接口是否可访问(HTTP 200/500 状态码统计)
2. 请求指标监控
接口相关
调用总数
接口调用
错误数
最慢
最快
999线
95线
99线
平均耗时
总耗时
最大并发
平均QPS
错误率(Error Rate)、超时率
QPS(每秒请求数)、TPS(事务数)、延迟(Latency)
Exception监控
异常类型
异常方法:
异常时间
异常数量
堆栈信息
3. 资源消耗
服务容器 CPU/内存使用、线程数、GC频率
4. 容量与伸缩
当前实例数 vs 压力 vs 自动扩缩容阈值
数据库连接池监控
数据库连接池监控指标
连接池使用情况
活跃连接数(Active Connections / Used Connections)
当前正在使用的连接数
空闲连接数(Idle Connections)
可立即使用的空闲连接数
最大连接数(Max Connections)
连接池允许的最大连接数
等待获取连接数 / 阻塞数
当所有连接都被占用时,新的请求等待的数量
连接池性能指标
连接获取时间
获取连接的平均/最大耗时
连接池拒绝请求数
当连接池满时,拒绝的请求或抛出的异常
连接池初始化/关闭事件
监控池生命周期异常
其他辅助指标
连接池泄漏
长时间不释放的连接
数据库端活跃连接数
与应用端连接池使用情况对比
数据库连接池监控指标参数获取
通过连接池自身暴露的监控接口
大多数 Java 连接池都提供内置监控接口
HikariCP
HikariDataSource.getHikariPoolMXBean() → 获取活跃连接、空闲连接、等待数、连接获取耗时
Druid
Druid 提供 StatViewServlet 和 DruidDataSource.getStat() → 全面监控连接池状态
Tomcat JDBC Pool
org.apache.tomcat.jdbc.pool.jmx.ConnectionPoolMBean → JMX 方式暴露指标
C3P0
ComboPooledDataSource.getNumBusyConnections() / getNumIdleConnections() / JMX 支持
HikariDataSource.getHikariPoolMXBean() → 获取活跃连接、空闲连接、等待数、连接获取耗时
Druid
Druid 提供 StatViewServlet 和 DruidDataSource.getStat() → 全面监控连接池状态
Tomcat JDBC Pool
org.apache.tomcat.jdbc.pool.jmx.ConnectionPoolMBean → JMX 方式暴露指标
C3P0
ComboPooledDataSource.getNumBusyConnections() / getNumIdleConnections() / JMX 支持
集成到应用监控系统
实现方式
Spring Boot + Micrometer
直接采集这些数据;暴露在 /actuator/metrics 或 Prometheus 格式接口
Prometheus
通过 Micrometer 或自定义 exporter 拉取连接池指标,转成Prometheus格式,提供http接口给Prometheus调用
没有现成的针对连接池的exporter工具
jvm监控
jvm监控指标
1. 堆内存(Heap)
Eden / Survivor / Old Generation
Eden区:新对象分配区,频繁GC
Survivor区:短暂存活对象
Old区:长寿命对象,Full GC 发生在这里
指标:
已用 vs 总容量
GC 次数与时间
堆使用趋势
2. 非堆内存(Non-Heap)
方法区/元空间(Metaspace)
存放类元数据和静态信息
指标:
已用 vs 总容量
Metaspace 内存泄漏监控
3. GC 性能
指标:
Minor GC / Major GC 次数
GC 暂停时间(Stop-the-world)
GC 时间占比
4. 线程与类加载
活跃线程数、线程池状态
已加载/卸载类数量
5. JVM 其他指标(可选)
堆外内存(Direct Memory)使用情况
文件句柄、Socket 连接等
常用监控工具
Prometheus + JMX Exporter + Grafana
通过 JMX 获取 JVM 内存、GC、线程等指标。
2. Spring Boot Actuator + Micrometer
简单易集成,指标直接暴露 HTTP 接口。
jvm内存监控参数获取
JMX
概述
全称Java Management Extensions,jdk5引进的技术
java.management包下提供接口
接口功能
ClassLoadingMXBean
获取类装载信息,已装载、已卸载量
CompilationMXBean
获取编译器信息
GarbageCollectionMXBean
获取GC信息,但他仅仅提供了GC的次数和GC花费总时间
MemoryManagerMXBean
提供了内存管理和内存池的名字信息
MemoryMXBean
提供整个虚拟机中内存的使用情况
MemoryPoolMXBean
提供获取各个内存池的使用信息
OperatingSystemMXBean
提供操作系统的简单信息
RuntimeMXBean
提供运行时当前JVM的详细信息
ThreadMXBean
提供对线程使用的状态信息
Java Management API 是 JMX 的 Java 内置实现和封装,使开发者无需手动操作 MBean 就能获取 JVM 指标
JMX架构
分层
资源层
包含 MBean 及其可管理的资源
提供了实现 JMX 技术可管理资源的规范
代理层
充当 MBean 和应用程序之间的中介
远程管理层
为远程程序提供Connector 和 Adapter访问 MBean Server
架构图
核心功能
实现对运行时应用程序动态资源查询
修改对运行时应用程序动态资源配置
利用JMX创建javaBean规则
JMX创建javaBean规则
具体规则
1、创建需要被存入进程的对象;
2、对象必须是接口,且必须以MBean结尾
demo
创建接口
public interface BlackListMBean {
// 获取黑名单列表
public String[] getBlackList();
// 在黑名单列表中添加一个用户
public void addBlackItem(String uid);
// 判断某个用户是否在黑名单中
public boolean contains(String uid);
// 获取黑名单大小
public int getBlackListSize();
}
// 获取黑名单列表
public String[] getBlackList();
// 在黑名单列表中添加一个用户
public void addBlackItem(String uid);
// 判断某个用户是否在黑名单中
public boolean contains(String uid);
// 获取黑名单大小
public int getBlackListSize();
}
实现接口
public class BlackList implements BlackListMBean {
private Set<String> uidSet = new HashSet<>();
@Override
public String[] getBlackList() {
return uidSet.toArray(new String[0]);
}
@Override
public void addBlackItem(String uid) {
uidSet.add(uid);
}
@Override
public boolean contains(String uid) {
return uidSet.contains(uid);
}
@Override
public int getBlackListSize() {
return uidSet.size();
}
}
private Set<String> uidSet = new HashSet<>();
@Override
public String[] getBlackList() {
return uidSet.toArray(new String[0]);
}
@Override
public void addBlackItem(String uid) {
uidSet.add(uid);
}
@Override
public boolean contains(String uid) {
return uidSet.contains(uid);
}
@Override
public int getBlackListSize() {
return uidSet.size();
}
}
MBean 注册到 MBeanServer
// 获取 MBean Server
MBeanServer platformMBeanServer = ManagementFactory.getPlatformMBeanServer();
// 创建 MBean 初始黑名单用户为 a 和 b
BlackList blackList = new BlackList();
blackList.addBlackItem("a");
blackList.addBlackItem("b");
// 注册
ObjectName objectName = new ObjectName("com.common.example.jmx:type=BlackList, name=BlackListMBean");
platformMBeanServer.registerMBean(blackList, objectName);
MBeanServer platformMBeanServer = ManagementFactory.getPlatformMBeanServer();
// 创建 MBean 初始黑名单用户为 a 和 b
BlackList blackList = new BlackList();
blackList.addBlackItem("a");
blackList.addBlackItem("b");
// 注册
ObjectName objectName = new ObjectName("com.common.example.jmx:type=BlackList, name=BlackListMBean");
platformMBeanServer.registerMBean(blackList, objectName);
演示
String hostname = "localhost";
int port = 9000;
// 循环接收
while (true) {
// 简单从 Socket 接收字符串模拟接收到的用户Id
try (Socket socket = new Socket()) {
socket.connect(new InetSocketAddress(hostname, port), 0);
try (BufferedReader reader = new BufferedReader(new InputStreamReader(socket.getInputStream()))) {
char[] buffer = new char[8012];
int bytes;
while ((bytes = reader.read(buffer)) != -1) {
String result = new String(buffer, 0, bytes);
String uid = result;
// 去掉换行符
if (result.endsWith("\n")) {
uid = result.substring(0, result.length() - 1);
}
if (blackList.contains(uid)) {
System.out.println("[INFO] uid " + uid + " is in black list");
} else {
System.out.println("[INFO] uid " + uid + " is not in black list");
}
}
}
}
Thread.sleep(3000);
System.out.println("[INFO] 休眠 3s ..............");
}
int port = 9000;
// 循环接收
while (true) {
// 简单从 Socket 接收字符串模拟接收到的用户Id
try (Socket socket = new Socket()) {
socket.connect(new InetSocketAddress(hostname, port), 0);
try (BufferedReader reader = new BufferedReader(new InputStreamReader(socket.getInputStream()))) {
char[] buffer = new char[8012];
int bytes;
while ((bytes = reader.read(buffer)) != -1) {
String result = new String(buffer, 0, bytes);
String uid = result;
// 去掉换行符
if (result.endsWith("\n")) {
uid = result.substring(0, result.length() - 1);
}
if (blackList.contains(uid)) {
System.out.println("[INFO] uid " + uid + " is in black list");
} else {
System.out.println("[INFO] uid " + uid + " is not in black list");
}
}
}
}
Thread.sleep(3000);
System.out.println("[INFO] 休眠 3s ..............");
}
添加jvm配置
-Dcom.sun.management.jmxremote.port=8888 --表示远程jmx的端口
-Dcom.sun.management.jmxremote.authenticate=false --是否要使用用户名和口令验证
-Dcom.sun.management.jmxremote.ssl=false --是否使用安全socket
-Dcom.sun.management.jmxremote.authenticate=false --是否要使用用户名和口令验证
-Dcom.sun.management.jmxremote.ssl=false --是否使用安全socket
开通远程接口调用权限
登录远程jvm
已经实现的应用
jconsole
Java内置的实现监控工具 jconsole
消息中间件监控
rabbitMq监控
监控指标
基础设施和核心指标
CPU状态(user、system、iowait&idle percentages
内存使用率(used、buffered、cached & free percentages)
虚拟内存统计信息(dirty page flushes, writeback volume)
磁盘I/O(operations & amount of data transferred per unit time, time to service operations)
装载上用于节点数据目录的可用磁盘空间
beam.smp使用的文件描述符与最大系统限制
按状态列出的TCP连接(ESTABLISHED,CLOSE_WAIT,TIME_WATT)
网络吞吐量(bytes received,bytes sent) & 最大网络吞吐量
网络延迟(集群中所有RabbitMQ节点之间以及客户端之间)
集群监控指标
集群信息获取
集群指标获取
请求集群中的任意节点获取
该节点在声场响应之前,需要收集组合来自其他节点的数据
集群指标
集群名称
cluster_name
集群范围的消息速率
message_stats
总连接数量
生产者,消费者和服务端的链接数量
object_totals.connections
总消息通道数量
消息通道是轻量级的连接
object_totals.channels
总队列数量
object_totals.queues
总的消费者数量
object_totals.consumers
消息总数(ready+unacked)
queue_totals.messages
准备交付的消息数量
queue_totals.messages_ready
未确认消息总量
queue_totals.messages_unacknowledged
最近发送消息数量
message_stats.publish
消息发布的速度
message_stats.publish_details.rate
最近给消费者消息数量
message_stats.deliver_get
消息发送速度
message_stats.deliver_get.rate
Other message stats
节点指标获取
可以对任意节点请求获取统计指标
节点指标
总的内存使用大小
mem_used
Memory usage high watermark
内存使用大小的最高水位
统计历史
内存使用阈值
以上两种理解?如何选择
当内存使用超过阈值时将触发报警memory alarm
Is a memory alarm in effect?
mem_alarm
剩余磁盘空间阈值
disk_free_limit
当空闲磁盘空间低于配置的限制时,将触发报警
可用文件描述符总数
已经使用的文件描述符大小
尝试打开的文件描述符数量
socket 系统连接最大值
socket 连接已经使用数量
Message store disk reads
?
Message store disk writes
?
Inter-node communication links
垃圾回收次数
垃圾回收内存大小
erlang 最大进程数量
已经使用的erlang 进程数量
正在运行的队列
单个队列指标获取
队列指标
内存大小
消息总数(ready+unacknowledged)
准备交付的消息数量
总的消息大小
准备传送的消息数量
未确认的消息数量
最近发布的消息数量
消息发布速度
最近交付的消息数量
消息传送速度
Other message stats
本质都是通过RabbitMq提供的Http api接口获取
GET /api/overview
返回集群范围的指标
GET /api/nodes/{node}
返回单个节点的状态
GET /api/nodes
返回所有集群成员节点的状态
GET /api/queues/{vhost}/{qname}
单个队列的指标
应用程序级指标
监控的rabbitMq系统本身指标
应用程序跟踪的指标可以是特定于系统
客户端库和框架提供了注册指标收集器或收集现成指标的方法
RabbitMQ Java客户端和Spring AMQP就是两个例子。其它开发人员必须跟踪应用程序代码中的指标。
监听堵塞消息
可以在MQ中专门创建一个监控的队列,定时的发送和消费队列中的消息,并且通过的如下的代码去监控队列是否已经堵塞,如果监听到队列已经堵塞,就立即发送告警的短信和邮件
监控检测
集群中是否有资源报警
rabbitMq是否正常运行
当前节点是否有报警
监控频率
生产系统建议收集间隔30秒-60秒
频率太高,容易对系统产生负面影响
数据采集
Management Plugin
Management Plugin 是一个官方插件,旨在为 RabbitMQ 提供图形化管理界面、HTTP API 和命令行工具,方便用户进行监控、配置和管理
RabbitMQ Exporter 采集通过 Management Plugin 采集到数据封装成Prometheus的格式,提供http接口给Prometheus
监控工具实现
RabbitMq自带管理平台
公开了节点、连接、队列、消息速率等的RabbitMQ指标
限制
监控系统与被监控系统交织在一起
占用系统一定的开销
它只存储最近的数据(最多一天,不是几天天或几个月)
它有一个基本的用户界面
它的设计强调易用性,而不是最佳可用性
管理UI访问通过RabbitMQ权限标记系统(或JWT令牌作用域的约定)进行控制
rabbitmqctl命令
后端命令行工具
REST API
Http接口
监控工具
Prometheus & Grafana
优点
监控系统与被监控系统分离
降低服务开销
长期存储指标
方便关联聚合对比各个相关指标
更强大和可定制的用户界面
易于分享的指标数据
更健全的访问权限
针对不同节点的数据收集更具弹性
RabbitMQ自带的(Management插件
Rocketmq监控
rocketMq参数采集和获取
Broker 内置 metrics → 可通过 Prometheus Exporter 或管理控制台获取
监控工具
1、官方提供的一个console web监控工具
本质依赖的是rokcetMq mqadmin命令行工具
2、Prometheus
将rockeMq的数据源导入到Prometheus上做相关监控
大体步骤
1、系统rocketMq服务
大致流程
1、通过 RocketMQ Exporter 工具从rokcetMq 上获取到相关的指标数据;
2、配置Prometheus 从RocketMQ Exporter 获取到对应的指标数据
kafka监控
监控实现原理
jmx
kafka官方也是提倡使用jmx并且提供了jmx的调用给用户以监控kafka.
提供 Topic、Partition、Producer/Consumer、Broker 指标
实现过程
Kafka JMX Exporter连接kafka,获取到核心参数,转换成Prometheus的格式,提供http接口给Prometheus调用
监控指标
资源类型监控
实例监控
实例消息生产流量(bytes/s)
实例消息消费流量(bytes/s)
实例磁盘使用率(%)-实例各节点中磁盘使用率的最大值
topic
Topic 消息生产流量(bytes/s)
Topic 消息消费流量(bytes/s)
group监控
Group 未消费消息总数(个)
Broker 指标
Kafka-emitted 指标
未复制的分区数
UnderReplicatedPartitions(可用性)kafka.server:type=ReplicaManager,name=UnderReplicatedPartitions
在运行正常集群中,同步副本(ISR)数量应等于副本总数。如果分区副本远远落后于 Leader,则从 ISR 池中删除这个 follower。如果代理不可用,则 UnderReplicatedPartitions 指标急剧增加。Tips:UnderReplicatedPartitions 较长时间内大于零,需要进行排查。
同步副本(ISR)池缩小/扩展的速率
IsrShrinksPerSec / IsrExpandsPerSec(可用性)kafka.server:type=ReplicaManager,name=IsrShrinksPerSec
如果某副本在一段时间内未联系 Leader 或者 follower 的 offset 远远落后于 Leader,则将其从 ISR 池中删除。因此,需要关注 IsrShrinksPerSec / IsrExpandsPerSec 的相关波动。IsrShrinksPerSec 增加,不应该造成 IsrExpandsPerSec 增加。在扩展 Brokers 集群或删除分区等特殊情况以外,特定分区同步副本(ISR)数量应保持相对稳定。
离线分区数(仅控制器)
OfflinePartitionsCount(可用性)kafka.controller:type=KafkaController,name=OfflinePartitionsCount
主要统计没有活跃 Leader 的分区数。Tips:由于所有读写操作仅在分区引导程序上执行,因此该指标出现非零值,就需要进行关注,防止服务中断。
集群中活动控制器的数量
ActiveControllerCount(可用性)kafka.server:type=ReplicaManager,name=IsrShrinksPerSec
所有 brokers 中 ActiveControllerCount 总和始终等于 1,如出现波动应及时告警。Kafka 集群中启动的第一个节点将自动成为Controller且只有一个。Kafka 集群中的Controller负责维护分区 Leader 列表,并协调 Leader 变更(比如某分区 leader 不可用)。
每秒 UncleanLeader 选举次数
UncleanLeaderElectionsPerSec(可用性)kafka.controller:type=ControllerStats,name=UncleanLeaderElectionsPerSec
在可用性和一致性之间,Kafka 默选了可用性。当 Kafka Brokers 的分区 Leader 不可用时,就会发生 unclean 的 leader 选举。当作为分区 Leader 的代理脱机时,将从该分区的 ISR 集中选举出新的 Leader。Tips:UncleanLeaderElectionsPerSec 代表着数据丢失,因此需要进行告警。
特定请求(生产/提取)用时
TotalTimeMs 作为一个指标族,用来衡量服务请求(包括生产请求,获取消费者请求或获取跟随者请求)的用时,其中涵盖在请求队列中等待所花费的时间 Queue,处理所花费的时间 Local,等待消费者响应所花费的时间 Remote(仅当时requests.required.acks=-1)发送回复的时间 Response。
传入/传出字节率
每秒请求数
Host 基础指标 & JVM 垃圾收集指标
消耗磁盘空间消耗与可用磁盘空间
页面缓存读取与磁盘读取的比率
CPU 使用率
网络字节发送/接收
JVM 执行垃圾回收进程总数
JVM 执行垃圾收集进程用时
Producer 指标
每秒收到的平均响应数
每秒发送的平均请求数
平均请求等待时长
每秒平均传出/传入字节数
I / O 线程等待的平均时长
每个分区每个请求发送的平均字节数
Consumer 指标
Consumer 在此分区上滞后于 Producer 的消息数
特定 Topic 每秒平均消耗的字节数
特定 Topic 每秒平均消耗的记录数
Consumer 每秒获取的请求数
监控工具
Kafka Manager
Kafka Eagle
Logi-KafkaManager
消息中间件监控核心指标
1. 服务运行时监控(核心部分)
消息吞吐和延迟
消息生产速率、消费速率
队列长度/堆积量
消息延迟/滞留时间
消息可靠性
消息确认状态(ack/nack)
重试次数、失败率
客户端/连接状态
活跃消费者数
客户端连接数
集群/Broker 状态
节点存活、Leader/Partition 状态
副本同步状态、消息复制延迟
2. 基础资源监控(辅助部分)
系统资源使用
CPU、内存、磁盘 I/O、网络 I/O
Broker 进程相关
文件句柄、线程数
缓存监控
redis监控
监控指标数据来源
redis自带的info命令和monitor命令的相关信息
INFO 命令
Redis 内置命令,提供全量的服务器状态信息
数据类型
Server:Redis 版本、运行时间、进程 ID
Clients:客户端连接数、阻塞连接数
Memory:已用内存、内存碎片率、内存峰值
Persistence:RDB/AOF 状态、最后一次保存时间
Stats:命令执行次数、QPS、慢查询数量、缓存命中率
Replication:主从复制状态、延迟
CPU:Redis 进程 CPU 使用情况
Cluster:集群节点状态、槽分布
MONITOR 命令
作用:实时打印 Redis 收到的每条命令
用途:分析慢命令、异常操作,但会增加 CPU 开销,不适合生产环境持续使用
SLOWLOG 命令
作用:获取慢查询日志
用途:分析执行时间过长的命令,优化 Redis 配置和数据结构
客户端统计
Redis 客户端(Jedis、Spring Data Redis)可以采集:
请求/响应时间
错误率
重试次数
通过 自定义指标暴露给监控系统
监控采集过程
集成到Prometheus + redis_exporter
redis_exporter 连接redis获取指标,封装成Prometheus格式,再提供http接口给Prometheus
集成到 Spring Boot / Micrometer
Spring Boot 应用可通过 Micrometer Redis 模块采集 Redis 指标
数据会暴露在 /actuator/metrics,可被 Prometheus 拉取
redis监控指标
连接检测
连接失败检测
客户端连接数
执行 info clients 命令获取 connected_clients 就是客户端连接数
吞吐量监控
info stats
此命令可以查询吞吐量相关的监控项
具体指标
总执行命令数量
从 Redis 启动以来总计处理的命令数,可以通过前后两次监控组件获取的差值除以时间差,以得到 QPS
total_commands_processed
当前 Redis 实例的 OPS
instantaneous_ops_per_sec
网络总入量
total_net_input_bytes
网络总出量
total_net_output_bytes
每秒输入量,单位是kb/s
instantaneous_input_kbps
每秒输出量,单位是kb/s
instantaneous_output_kbps
内存监控
已使用内存大小
used_memory
通过 info memory 获取,表示 Redis 真实使用的内存
最大内存大小
maxmemory
通过 config get maxmemory 获取。
内存碎片
计算方式:used_memory_rss/used_memory
两个参数均通过 info memory 获取
大于 1 表示有内存碎片,越大表示越多;小于 1 表示正在使用虚拟内存,虚拟内存其实就是硬盘,性能会下降很多。一般内存碎片率在 1 - 1.5 之间比较健康。
持久化监控
持久化可以防止数据丢失
相关参数均为执行完 info Persistence 的结果
上一次 RDB 持久化状态
rdb_last_bgsave_status
上一次 RDB 持久化的持续时间
rdb_last_bgsave_time_sec
查看 AOF 文件大小
aof_current_size
key监控
大key
什么是大key
指单个 key 存储的数据量过大(比如一个 Hash 里有几百万字段,或者一个字符串值大小几十 MB)。
危害
单次读取或写入耗时长
阻塞 Redis 单线程
影响主从复制和 AOF 持久化性能
监控方式
如何监控大key(最优解)
MEMORY USAGE命令
查询单个 key 占用内存:
可结合脚本扫描所有 key,统计大于阈值的 key
实现
编写脚本使用MEMORY USAGE命令扫描各个 Master 节点
获取到每一个节点的key排行榜,最后汇总
可视化监控
Redis Exporter + Prometheus
收集 key 的统计信息(按前缀或类型)
可以设置告警:
单 key 内存占用超过阈值
集合长度超过阈值
redis自带的redis-cli --bigkeys
作用
可以找出五种数据类型中各自最大的key;
缺点
只能显示每种类型的最大 key,不提供全部排行
一般不适用该种方式监控
通过脚本或者命令扫描所有的key
缺点
结果的准确性不高,集合类型的扫描只能扫描出集合的长度,而不是value的大小
还会阻塞redis正常的执行
解析rdb文件
通过解析工具解析rdb文件,获取大key
常用解析工具
很多第三方的解析工具
通过代码aop的方式,异步每一次key的大小
大 key 告警
告警实现
在Prometheus 配置规则
key_memory_bytes > 阈值 → 告警
内存超过阈值 → 警告
单 key 访问耗时超过阈值 → 警告
热点大 key → CPU/延迟告警
优化策略
拆分 key
List / Set / ZSet → 按分页或哈希拆分
限制写入
避免一次性 push/insert 大量数据
设置 TTL
避免长期占用大量内存
本地缓存或外部存储
超大对象存储在对象存储或数据库,Redis 缓存部分数据
热key
热点数据的定义
Hot Key:访问频率远高于其他 key 的数据
Hot Slot:某个 slot 被频繁访问的情况(适用于 Redis Cluster)
表现为:
单节点 QPS 占总流量的很大比例
CPU/内存消耗异常高
单 key TTL 短或数据量大
原理
MONITOR 命令,可以统计每个 key 的访问次数,可用脚本收集频率,发现热点 key
看每一个master节点的QPS数据量,如果存在异常,极有可能存在热点key
自建对热key监控
可视化监控(最优解)
Redis Exporter + Prometheus 做到可视化
Redis Exporter 可以收集:
每个命令调用次数(keyspace_hits, keyspace_misses)
每个 DB 的 key 数量
配合 Prometheus/Grafana:
绘制 key 或 slot 热点图
配置告警(单 key 访问量过高)
机器
监控示意图
四种方式优缺点对比
客户端监控
每一个链接redis的客户端,都做相应的热key监控
代理端监控
监控示意图
子主题
服务端监控
监控示意图
子主题
原理
利用monitor命令的结果就可以统计出一段时间内的热点
key排行榜、命令排行榜、客户端分布
key排行榜、命令排行榜、客户端分布
缺点
monitor命令的执行影响正常的reids命令的执行
只能统计单机的热key
子主题
慢查询监控
慢查询涉及参数
执行时间超过了多久,会被记录到慢查询日志中
slowlog-log-slower-than
默认10000微妙
慢日志的长度
当慢查询日志达到最大条数时,如果有新的慢查询,会移除最大的慢查询。
slowlog-max-len
具体命令
slowlog get
查询所有慢查询
slowlog get 1
显示最新的一条慢查询
集群监控
具体指标
集群状态
cluster_state
hash槽状态
cluster_slots_fail
节点数量
cluster_known_nodes
具体命令
cluster info 命令中可以获取集群的状态
缓存命中率
HitRate = keyspace_hits / (keyspace_hits + keyspace_misses)
keyspace_hits 表示 Redis 请求键被命中的次数
keyspace_misses 表示 Redis 请求键未被命中的次数
info stats 可以获取两个指标
建议缓存命中率不要低于90%,越高越好
命中率越低,导致越多的缓存穿透,对mysql容易造成影响
线程池监控
线程池自带查询当前线程状态的方法
线程池中正在执行任务的线程数量
getActiveCount()
线程池已完成的任务数量,该值小于等于taskCount
getCompletedTaskCount()
线程池的核心线程数量
getCorePoolSize()
线程池曾经创建过的最大线程数量。通过这个数据可以知道线程池是否满过,也就是达到了maximumPoolSize
getLargestPoolSize
线程池的最大线程数量
getMaximumPoolSize
线程池当前的线程数量
getPoolSize
线程池已经执行的和未执行的任务总数
getTaskCount
线程池动态修改参数
具体可修改参数
核心线程数
ThreadPoolExecutor的api setCorePoolSize(int corePoolSize)
最大线程数
ThreadPoolExecutor的api setMaximumPoolSize(int maximumPoolSize)
等待队列大小
自定一个阻塞队列继承阻塞队类,然后在队列长度字段设置可以做修改。此队列作为线程池的阻塞队列
是否自动扩容
?
都是需要在县城的运行期做相关的操作进行修改
监控任务
任务分类
执行任务前后全量统计任务排队时间和执行时间
定时任务,定时获取活跃线程数,队列中的任务数,核心线程数,最大线程数等数据
线程池告警
告警指标
任务超时时间告警阈值
任务执行超时时间告警阈值
等待队列排队数量告警阈值
线程池定时监控时间间隔
告警实现
1、ThreadPoolExecutor线程池中beforeExecute和afterExecute方法是空实现
2、自定义线程池继承线程池类,实现beforeExecute和afterExecute方法
3、通过线程池的beforeExecute和afterExecute方法队线程池相关可查询参数进行监控
4、当相关的监控参数达到了告警阈值,那么就做出相关的告警操作;
三、日志监控
1. 集中式日志
收集微服务日志(应用日志、请求日志、错误日志)
统一存储和查询(ELK/EFK:Elasticsearch + Logstash/Fluentd + Kibana)
2. 日志分析
异常日志告警、错误聚合
请求追踪日志,辅助性能分析
如何做 集中日志管理?(ELK、EFK)
总结
集中日志管理 = 采集 (Filebeat/Fluentd) → 传输 (Kafka/直发) → 存储 (Elasticsearch/Loki) → 展示 (Kibana/Grafana) → 告警。
详细步骤
日志采集
每个服务写日志到本地文件(Logback / Log4j2)。
通过 Agent/采集器 收集日志
Filebeat(轻量级日志收集器,常配合 ELK)
Fluentd / Fluent Bit(CNCF 项目,性能更高)
Logstash(功能强大,但资源开销大)
日志传输
采集器将日志发送到消息队列或日志存储:
Kafka(常见缓冲层,削峰填谷)
直接推送到 Elasticsearch / Loki
日志存储
Elasticsearch:全文检索能力强,查询灵活。
日志分析与展示
Kibana(可视化查询,配合 Elasticsearch)。
或者
Grafana + Loki(轻量化日志查询、告警)。
Graylog(开源日志管理平台)。
告警与联动
日志异常 → 触发告警 → 通知(钉钉、企业微信、PagerDuty)。
结合 Prometheus + Alertmanager,实现指标与日志联动。
四、分布式追踪(Tracing)
1. 调用链跟踪
跟踪每个请求在各微服务间的调用情况
记录延迟、错误发生节点
2. 常用工具
Zipkin、SkyWalking、CAT
子主题
五、告警与自动化响应
1. 告警策略
需要自己设置告警策略
2. 告警渠道
邮件、钉钉、Slack、PagerDuty 等
3. 自动化响应
K8s 自动扩容
服务自动重启、流量熔断
六、业务指标监控
业务自定义
订单数量,支持成功数,点击次数,下载次数
0 条评论
下一页