java诊断与链路追踪监控
2023-03-25 22:12:01 2 举报
AI智能生成
java代码链路追踪,系统APM,系统级别监控如何实现
作者其他创作
大纲/内容
链路追踪
链路追踪工具
cat
产品定位
CAT(Central Application Tracking)是一个实时和接近全量的监控系统
侧重于Java应用的监控
应用场景
mvc框架
rpc框架
持久层框架
分布式缓存框架
提供各项性能监控,健康检查,自动报警
cat系统的设计要求
实时处理
时间越久,监控的信息价值会锐减
全量数据
监控的是所有的请求数据
高可用
应用服务挂了,监控还在,可以辅助排查定位问题
高吞吐
全量数据的接收和处理能力
故障容忍
监控本身的故障不会影响业务代码的正常运行
可扩展
支持分布式,跨IDC部署,横向扩展的监控系统
不保证可靠
cat监控系统的可靠性可以做到四个九
cat整体设计
主要分为三个模块
CAT-client
应用应用埋点的底层sdk,的客户端
CAT-consumer
实时消费,处理客户端提供的数据
CAT-home
给用户展示的控制端平台
结构展示
客户端信息收集
1、为每一个线程创建一个ThreadLocal(线程局部变量);
2、执行业务逻辑的时候,就把请求对应的监控信息存储在线程的局部变量中
请求对应的上下文其实是一个监控树的结构
3、业务线程执行结束之后,将监控对象放入一个异步内存队列中;
4、cat会有一个消费线程将异步队列中的信息发送给服务端;
核心监控对象
Transaction
一段代码运行时间,次数
Event
一行代码的执行次数
Heartbeat
jvm内部的一些状态信息,Memory.Thread等
Metric
一个请求调用的链路统计
序列化和通信设计
序列化
cat序列化协议是cat自己自定义的协议
通信
netty来实现nio
存储设计
cat报表数据
cat原始logview数据
整体架构设计图
设计图
子主题
流程说明
1、客户端向服务端发送消息基于netty-nio实现
2、服务端接受消息放入内存队列,开起一个线程消费来分发这个内存队列中的消息
3、消息解析完成站会,存入本地磁盘,然后再异步上传到HDFS
实时分析
总个数
总和
均值
最大,最小
吞吐
95线,99线,999线
分布式日志系统
ELK
通俗来讲,ELK就是
诊断工具
arthas-阿尔萨斯
产品自我定位
线上监控诊断产品
大大提升线上问题排查效率
新名词学习
Perf
性能剖析(performance profiling)和代码优化
指标参数说明参考文档
https://blog.csdn.net/web18224617243/article/details/123953692
https://blog.csdn.net/Cr1556648487/article/details/126816451
https://docs.oracle.com/javase/8/docs/platform/jvmti/jvmti.html
https://arthas.aliyun.com/doc/getstatic.html
统计指标项目学习
java.ci.totalTime
jit编译花费的总时间
命令列表
常用命令
查看 logger 信息,更新 logger level
logger
logger
查看当前 JVM 的 Perf Counter 信息
perfcounter
子主题
生成发放火焰图
profiler
内存相关
下载当前内存信息
heapdump
heapdump /tmp/dump.hprof
下载当前内存信息到某个目录下
子主题
查看jvm当前内存信息
jvm
jvm
查看当前 JVM 信息
查看 JVM 内存信息
memory
memory
查看当前线程信息,查看线程的堆栈
最忙的几个
子主题
所有
子主题
编译文件相关
dump 已加载类的 bytecode 到特定目录
子主题
dump
反编译指定已加载类的源码
子主题
编译.java文件生成.class
子主题
查看 JVM 已加载的类信息
sc
子主题
查看已加载类的方法信息
sm
子主题
vmtool 利用JVMTI接口,实现查询内存对象,强制 GC 等功能。
子主题
方法监控
方法执行监控
monitor
输出当前方法被调用的调用路径
stack
方法内部调用路径,并输出方法路径上的每个节点上耗时
trace
方法执行数据的时空隧道,记录下指定方法每次调用的入参和返回信息,并能对这些不同的时间下调用进行观测
tt
函数执行数据观测
watch
参数查看
查看当前 JVM 的环境属性
子主题
查看当前 JVM 的系统属性
子主题
查看,更新 VM 诊断相关的参数
vmoption
子主题
查看指定参数
更新指定的 option
子主题
子主题
预览命令
当前系统的实时数据面板
dashboard
dashboard
子主题
当前系统的实时数据面板,按 ctrl+c 退出
查看当前类静态属性
getstatic
预览
子主题
查看 classloader 的继承树,urls,类加载信息
输出当前目标 Java 进程所加载的 Arthas 版本号
文件相关
打印文件内容,和 linux 里的 cat 命令类似
子主题
打印命令历史
history
实现原理
cpu 使用率是如何统计出来的?
一段采样间隔时间内,当前 JVM 里各个线程的增量 cpu 时间与采样间隔时间的比例
和linux系统类似
具体步骤
首先第一次采样,获取所有线程的 CPU 时间(调用的是java.lang.management.ThreadMXBean#getThreadCpuTime()及sun.management.HotspotThreadMBean.getInternalThreadCpuTimes()接口)
然后睡眠等待一个间隔时间(默认为 200ms,可以通过-i指定间隔时间)
再次第二次采样,获取所有线程的 CPU 时间,对比两次采样数据,计算出每个线程的增量 CPU 时间
线程 CPU 使用率 = 线程增量 CPU 时间 / 采样间隔时间 * 100%
注意事项
命令本身也是需要消耗时间的,会对结果有一定干扰
把统计的时间拉长可以降低命令本身执行的时间损耗
功能概述
1:查看应用 load、内存、gc、线程的状态信息
2:可在不修改应用代码的情况下,对业务问题进行诊断
查看方法调用的出入参
查看方法异常
监测方法执行耗时
类加载信息
子主题
监控系统
监控系统的要求
1、快速发现故障
2、快速定位故障
3、辅助进行程序性能优化
监控维度
基础资源监控
jvm监控
Overview
Threading
GC
CPU
Heap
应用监控
接口调用
接口路径
调用总数
最大并发
平均QPS
总耗时
平均耗时
99线
95线
999线
最快
最慢
错误数
接口链路
接口入参回参
数据源监控
连接池中链接数
连接池链接数峰值
池中连接数峰值时间
活跃连接数
活跃连接数峰值
JDBC访问监控
SQL语句
执行数
执行时间
错误数
读取行数
更行行数
慢SQL
Exception监控
异常类型
异常方法:
异常时间
异常数量
堆栈信息
业务监控
业务自定义
订单数量,支持成功数,点击次数,下载次数
Cache命中率
队列大小
监控方案设计
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问题。
同时要考虑同步和异步接口
监控系统实现底层技术总结
redis监控实现原理
redis自带的info命令和monitor命令的相关信息
链路追踪实现原理
java agent技术
应用
zipkin,skywalking,pinpoint链路追踪等都是由这个来实现的
历史
jdk1.5版本之后引入的特性
jdk1.6可以支持更加强大的Instrument
作用
在class被加载之前对其进行拦截,然后插入自定义的监听代码
无需对原有的应用做出任何代码修改,可以实现对类的动态修改和增强
可以理解是jvm级别的AOP
java-agent实现监听流程
详细流程
1、jvm启动的时候会伴随一个java-agent的jar包附加程序启动
2、这个java agent保中的配置文件中指定代理类,代理类中会有一个premain方法
3、jvm在类加载的时候会执行代理类的premain方法,再执行java程序本身的main方法
4、prmain方法可以对加载前的class文件进行修改
详细流程图
子主题
java-agent实现
1、通过Java Instrumentation 接口进行变成
2、Instrumentation接口的实现是通过jvm虚拟机提供的native接口来实现
实战demo
https://blog.csdn.net/m0_69305074/article/details/124504419
jvm内存监控实现原理
JMX
概述
全称Java Management Extensions,jdk5引进的技术
java.management包下提供接口
接口功能
ClassLoadingMXBean
获取类装载信息,已装载、已卸载量
CompilationMXBean
获取编译器信息
GarbageCollectionMXBean
获取GC信息,但他仅仅提供了GC的次数和GC花费总时间
MemoryManagerMXBean
提供了内存管理和内存池的名字信息
MemoryMXBean
提供整个虚拟机中内存的使用情况
MemoryPoolMXBean
提供获取各个内存池的使用信息
OperatingSystemMXBean
提供操作系统的简单信息
RuntimeMXBean
提供运行时当前JVM的详细信息
ThreadMXBean
提供对线程使用的状态信息
JMX 提供了简单、标准的监控和管理资源的方式
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
参考文档
https://blog.csdn.net/weixin_35346265/article/details/114064440
https://blog.csdn.net/SunnyYoona/article/details/125154198
https://blog.csdn.net/weixin_42741805/article/details/116855285
https://blog.csdn.net/vincentff7zg/article/details/54582549
消息队列监控实现原理
rabbitMq
监控工具实现
RabbitMq自带管理平台
公开了节点、连接、队列、消息速率等的RabbitMQ指标
限制
监控系统与被监控系统交织在一起
占用系统一定的开销
它只存储最近的数据(最多一天,不是几天天或几个月)
它有一个基本的用户界面
它的设计强调易用性,而不是最佳可用性
管理UI访问通过RabbitMQ权限标记系统(或JWT令牌作用域的约定)进行控制
rabbitmqctl命令
后端命令行工具
REST API
直接通过接口查询各种相关的监控信息
RocketMQ
mqadmin–提供一套命令行工具
开源监控系统
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
各种应用监控
jvm监控
监控相关工具
Java Profiler
jvm监控
MAT
java内存分析
VisualVM
偏向jvm监控
Oracle Java Mission Control
Java Mission Control与Java Flight Recorder一起,允许分析和事件收集有关Java虚拟机(JVM)和Java应用程序行为的低级信息。与Oracle JDK一起打包的这组工具还提供了对收集的数据的详细分析。
消息中间件监控
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秒
频率太高,容易对系统产生负面影响
监控工具实现
RabbitMq自带管理平台
公开了节点、连接、队列、消息速率等的RabbitMQ指标
限制
监控系统与被监控系统交织在一起
占用系统一定的开销
它只存储最近的数据(最多一天,不是几天天或几个月)
它有一个基本的用户界面
它的设计强调易用性,而不是最佳可用性
管理UI访问通过RabbitMQ权限标记系统(或JWT令牌作用域的约定)进行控制
rabbitmqctl命令
后端命令行工具
REST API
Http接口
监控工具
Prometheus & Grafana
优点
监控系统与被监控系统分离
降低服务开销
长期存储指标
方便关联聚合对比各个相关指标
更强大和可定制的用户界面
易于分享的指标数据
更健全的访问权限
针对不同节点的数据收集更具弹性
RabbitMQ自带的(Management插件
Rocketmq监控
rocketMq监控
监控系统不是很完善,目前主要依赖rokcetMq mqadmin命令行工具
监控工具
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.
监控指标
资源类型监控
实例监控
实例消息生产流量(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
数据库监控
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
缓存监控
redis监控
监控的实现
redis自带的info命令和monitor命令的相关信息
redis监控平台
redis-faina
redis自带命令monitor的输出结果做分析的python脚本
redis-live
RedisLive是一款用Python编写的Redis图形监控工具
原理
监控脚本来利用Redis提供的MONITOR命令从被监控Redis实例中获取数据并存储到Redis的监控实例中来做数据分析
RedisLive以可视化的方式展示了Redis实例中的数据,分析查询模式和峰值
监控插件
Munin插件
nagios
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对应的value值非常大
监控方式
redis自带的redis-cli --bigkeys
作用
可以找出五种数据类型中各自最大的key;
缺点
不能帮助我们找到整个数据里的最大的key
一般不适用该种方式监控
通过脚本或者命令扫描所有的key
缺点
结果的准确性不高,集合类型的扫描只能扫描出集合的长度,而不是value的大小
还会阻塞redis正常的执行
解析rdb文件
通过解析工具解析rdb文件,获取大key
常用解析工具
很多第三方的解析工具
通过代码aop的方式,异步每一次key的大小
热key
监控方式
redis自带的redis-cli --hotkeys命令
缺点
必须使用Least Frequently Used 最近最少使用的缓存淘汰策略
执行命令的途中肯定会阻塞正常的redis命令的执行
自建对热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、当相关的监控参数达到了告警阈值,那么就做出相关的告警操作;
0 条评论
下一页