Linux监控系统磁盘IO的方法汇总
作者:Jinkxs
在现代分布式系统和高并发服务架构中,磁盘 I/O 性能往往是系统瓶颈的重要来源。无论是数据库服务器、日志收集系统,还是缓存层与持久化存储的交互,磁盘读写速度直接决定了整体响应能力。特别是在 Java 应用广泛部署的 Linux 服务器环境中,掌握磁盘 I/O 监控技巧是保障服务稳定性和性能优化的关键。
本文将从基础命令工具开始,逐步深入到 Java 程序如何集成磁盘监控,最终构建一个完整的自动化监控体系。我们将涵盖:
- Linux 原生命令行工具(iostat, iotop, sar)
- /proc 和 /sys 文件系统中的 I/O 数据
- Java 中调用系统命令获取磁盘指标
- 使用 JMX 暴露自定义磁盘监控 MBean
- Prometheus + Grafana 构建可视化大盘
- 告警策略与阈值配置建议
- 性能调优实战案例
无论你是 DevOps 工程师、Java 后端开发者,还是系统架构师,都能从本文获得实用技能。
为什么需要监控磁盘 I/O?
磁盘 I/O 是系统中最慢的操作之一。相比内存访问(纳秒级)和 CPU 运算(皮秒级),即使是 NVMe SSD 也需要微秒甚至毫秒级别的响应时间。当磁盘成为瓶颈时,会导致:
- 请求堆积、线程阻塞
- GC 频率升高(因日志刷盘慢)
- 数据库写入延迟飙升
- 服务超时、熔断触发
- 用户体验下降
根据 Google SRE 手册 中的经验法则:“如果你无法度量它,你就无法改进它。” 因此,建立有效的磁盘 I/O 监控体系,是保障系统 SLA 的第一步。
Linux 原生监控工具概览
1.iostat—— 最常用的 I/O 统计工具
iostat 属于 sysstat 包,提供设备级别的 I/O 统计信息。
# 安装 sysstat(如未安装) sudo apt install sysstat # Ubuntu/Debian sudo yum install sysstat # CentOS/RHEL # 查看每秒统计,刷新间隔2秒,共5次 iostat -x 2 5
输出示例:
Device r/s w/s rkB/s wkB/s rrqm/s wrqm/s %util sda 8.33 2.50 266.67 80.00 0.00 0.20 1.20 nvme0n1 15.40 12.80 1232.00 1024.00 0.00 0.00 8.90
关键字段解释:
r/s,w/s:每秒读/写请求数rkB/s,wkB/s:每秒读/写字节数(KB)%util:设备利用率(接近 100% 表示饱和)
提示:%util 并非绝对性能指标,SSD 多队列并发下即使 %util=100%,也可能未达性能极限。
2.iotop—— 实时进程级 I/O 监控
类似 top,但专注于 I/O:
sudo iotop -oPa
参数说明:
-o:仅显示有 I/O 活动的进程-P:仅显示进程(不显示线程)-a:累积模式(显示历史总量)
适合定位“谁在疯狂读写磁盘”。
3.sar—— 历史数据回溯利器
sar 可记录历史 I/O 数据,默认每10分钟采样一次。
# 查看昨天全天磁盘使用情况 sar -d -f /var/log/sysstat/sa$(date -d yesterday +%d) # 实时查看,每3秒一次 sar -d 3 5
从 /proc 和 /sys 获取原始数据
Linux 内核通过虚拟文件系统暴露大量运行时数据。
/proc/diskstats
每一行代表一个块设备的统计:
cat /proc/diskstats
输出格式(部分字段):
8 0 sda 12345 0 67890 123 4567 0 89012 456 0 579 579
字段含义(按顺序):
- 主设备号
- 次设备号
- 设备名
- 读完成次数
- 合并读次数
- 读扇区数(*512字节)
- 读花费毫秒数
- 写完成次数
- 合并写次数
- 写扇区数
- 写花费毫秒数
…
我们可以通过两次采样差值计算实时速率。
/sys/block/[dev]/stat
结构与 /proc/diskstats 类似,但按设备组织:
cat /sys/block/sda/stat
Java 中监控磁盘 I/O —— 基础版
下面我们用 Java 编写一个简单的磁盘监控器,调用 iostat 并解析结果。
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;
public class SimpleDiskMonitor {
public static void main(String[] args) {
ScheduledExecutorService scheduler = Executors.newScheduledThreadPool(1);
scheduler.scheduleAtFixedRate(() -> {
try {
Process process = Runtime.getRuntime().exec("iostat -x 1 1");
BufferedReader reader = new BufferedReader(new InputStreamReader(process.getInputStream()));
String line;
boolean startReading = false;
while ((line = reader.readLine()) != null) {
if (line.startsWith("Device")) {
startReading = true;
continue;
}
if (startReading && !line.trim().isEmpty()) {
String[] parts = line.split("\\s+");
if (parts.length >= 14) {
String device = parts[0];
double util = Double.parseDouble(parts[13]);
System.out.printf("[%s] Device: %-8s Utilization: %.2f%%%n",
java.time.LocalDateTime.now(), device, util);
}
}
}
process.waitFor();
} catch (Exception e) {
e.printStackTrace();
}
}, 0, 5, TimeUnit.SECONDS);
}
}
注意:生产环境慎用 Runtime.exec(),存在安全与稳定性风险。建议改用 JNI 或 JNA 调用底层 API。
使用 Sigar 库(已归档,仅作参考)
Sigar(System Information Gatherer And Reporter)曾是流行的跨平台系统监控库,现虽已停止维护,但其设计思想仍具参考价值。
Maven 依赖(若仓库仍有缓存):
<dependency>
<groupId>org.fusesource</groupId>
<artifactId>sigar</artifactId>
<version>1.6.4</version>
</dependency>
示例代码:
import org.hyperic.sigar.DiskUsage;
import org.hyperic.sigar.Sigar;
import org.hyperic.sigar.SigarException;
public class SigarDiskMonitor {
public static void main(String[] args) throws SigarException, InterruptedException {
Sigar sigar = new Sigar();
while (true) {
String[] devices = sigar.getFileSystemList();
for (String dev : devices) {
try {
DiskUsage usage = sigar.getDiskUsage(dev);
System.out.printf("Device: %s, ReadBytes: %d, WriteBytes: %d%n",
dev, usage.getReadBytes(), usage.getWriteBytes());
} catch (SigarException e) {
// 忽略不可读设备
}
}
Thread.sleep(3000);
}
}
}
替代方案:推荐使用 OSHI(Operating System and Hardware Information library),活跃维护中。
使用 OSHI 库监控磁盘(推荐)
OSHI 是当前 Java 生态中最活跃的系统信息库,支持 Linux、Windows、macOS。
添加 Maven 依赖:
<dependency>
<groupId>com.github.oshi</groupId>
<artifactId>oshi-core</artifactId>
<version>6.4.4</version>
</dependency>
完整监控示例:
import oshi.SystemInfo;
import oshi.hardware.HWDiskStore;
import oshi.hardware.HardwareAbstractionLayer;
import java.util.Arrays;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;
public class OshiDiskMonitor {
private static HWDiskStore[] previousDisks = new HWDiskStore[0];
public static void main(String[] args) {
SystemInfo si = new SystemInfo();
HardwareAbstractionLayer hal = si.getHardware();
ScheduledExecutorService scheduler = Executors.newScheduledThreadPool(1);
scheduler.scheduleAtFixedRate(() -> {
HWDiskStore[] currentDisks = hal.getDiskStores();
if (previousDisks.length == 0) {
previousDisks = currentDisks.clone();
return;
}
long now = System.currentTimeMillis();
for (int i = 0; i < currentDisks.length; i++) {
HWDiskStore curr = currentDisks[i];
HWDiskStore prev = findPreviousDisk(curr.getName());
if (prev != null) {
long timeDiff = now - prev.getTimeStamp();
if (timeDiff <= 0) continue;
double readBytesPerSec = (curr.getReadBytes() - prev.getReadBytes()) * 1000.0 / timeDiff;
double writeBytesPerSec = (curr.getWriteBytes() - prev.getWriteBytes()) * 1000.0 / timeDiff;
double transfersPerSec = (curr.getReads() + curr.getWrites() - prev.getReads() - prev.getWrites()) * 1000.0 / timeDiff;
System.out.printf("[%s] %-10s | R: %7.2f KB/s | W: %7.2f KB/s | IOPS: %.1f%n",
java.time.LocalTime.now(),
curr.getName(),
readBytesPerSec / 1024,
writeBytesPerSec / 1024,
transfersPerSec);
}
}
previousDisks = currentDisks.clone();
}, 0, 2, TimeUnit.SECONDS);
}
private static HWDiskStore findPreviousDisk(String name) {
return Arrays.stream(previousDisks)
.filter(d -> d.getName().equals(name))
.findFirst()
.orElse(null);
}
}
输出效果:
[14:23:05.123] sda | R: 128.50 KB/s | W: 64.25 KB/s | IOPS: 15.3 [14:23:07.125] sda | R: 32.10 KB/s | W: 256.80 KB/s | IOPS: 8.7 [14:23:09.127] nvme0n1 | R: 1024.00 KB/s | W: 512.00 KB/s | IOPS: 120.5
使用 JMX 暴露磁盘指标
为了让监控数据被外部系统(如 Prometheus、Zabbix)采集,我们将其封装为 JMX MBean。
首先定义接口:
public interface DiskMonitorMBean {
double getReadBytesPerSecond(String deviceName);
double getWriteBytesPerSecond(String deviceName);
double getIops(String deviceName);
String[] getDeviceNames();
}
实现类:
import oshi.SystemInfo;
import oshi.hardware.HWDiskStore;
import oshi.hardware.HardwareAbstractionLayer;
import javax.management.Notification;
import javax.management.NotificationBroadcasterSupport;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;
public class DiskMonitor extends NotificationBroadcasterSupport implements DiskMonitorMBean {
private final Map<String, HWDiskStore> previousStats = new HashMap<>();
private final HardwareAbstractionLayer hal;
private long sequenceNumber = 1;
public DiskMonitor() {
this.hal = new SystemInfo().getHardware();
startSampling();
}
private void startSampling() {
ScheduledExecutorService scheduler = Executors.newScheduledThreadPool(1);
scheduler.scheduleAtFixedRate(this::sampleDisks, 0, 2, TimeUnit.SECONDS);
}
private void sampleDisks() {
HWDiskStore[] disks = hal.getDiskStores();
long now = System.currentTimeMillis();
for (HWDiskStore disk : disks) {
HWDiskStore prev = previousStats.get(disk.getName());
if (prev != null) {
long timeDiff = now - prev.getTimeStamp();
if (timeDiff > 0) {
double rps = (disk.getReadBytes() - prev.getReadBytes()) * 1000.0 / timeDiff;
double wps = (disk.getWriteBytes() - prev.getWriteBytes()) * 1000.0 / timeDiff;
double iops = (disk.getReads() + disk.getWrites() - prev.getReads() - prev.getWrites()) * 1000.0 / timeDiff;
// 发送 JMX 通知(可选)
sendNotification(new Notification(
"disk.stats.update",
this,
sequenceNumber++,
String.format("Device %s updated: R=%.2f KB/s, W=%.2f KB/s, IOPS=%.1f",
disk.getName(), rps/1024, wps/1024, iops)));
}
}
previousStats.put(disk.getName(), disk);
}
}
@Override
public double getReadBytesPerSecond(String deviceName) {
HWDiskStore curr = getDiskByName(deviceName);
HWDiskStore prev = previousStats.get(deviceName);
if (curr == null || prev == null) return 0.0;
long timeDiff = curr.getTimeStamp() - prev.getTimeStamp();
if (timeDiff <= 0) return 0.0;
return (curr.getReadBytes() - prev.getReadBytes()) * 1000.0 / timeDiff;
}
@Override
public double getWriteBytesPerSecond(String deviceName) {
HWDiskStore curr = getDiskByName(deviceName);
HWDiskStore prev = previousStats.get(deviceName);
if (curr == null || prev == null) return 0.0;
long timeDiff = curr.getTimeStamp() - prev.getTimeStamp();
if (timeDiff <= 0) return 0.0;
return (curr.getWriteBytes() - prev.getWriteBytes()) * 1000.0 / timeDiff;
}
@Override
public double getIops(String deviceName) {
HWDiskStore curr = getDiskByName(deviceName);
HWDiskStore prev = previousStats.get(deviceName);
if (curr == null || prev == null) return 0.0;
long timeDiff = curr.getTimeStamp() - prev.getTimeStamp();
if (timeDiff <= 0) return 0.0;
return (curr.getReads() + curr.getWrites() - prev.getReads() - prev.getWrites()) * 1000.0 / timeDiff;
}
@Override
public String[] getDeviceNames() {
return hal.getDiskStores().stream()
.map(HWDiskStore::getName)
.toArray(String[]::new);
}
private HWDiskStore getDiskByName(String name) {
return Arrays.stream(hal.getDiskStores())
.filter(d -> d.getName().equals(name))
.findFirst()
.orElse(null);
}
}
注册 MBean:
import javax.management.MBeanServer;
import javax.management.ObjectName;
import java.lang.management.ManagementFactory;
public class JmxRegistration {
public static void main(String[] args) throws Exception {
MBeanServer mbs = ManagementFactory.getPlatformMBeanServer();
ObjectName name = new ObjectName("com.example.monitoring:type=DiskMonitor");
DiskMonitor monitor = new DiskMonitor();
mbs.registerMBean(monitor, name);
System.out.println("JMX Disk Monitor registered. Attach with JConsole or VisualVM.");
Thread.sleep(Long.MAX_VALUE); // keep alive
}
}
启动后,可用 jconsole 连接本地 JVM,查看磁盘指标。
集成 Prometheus + Grafana
Prometheus 是当前最流行的时序数据库,Grafana 是强大的可视化工具。我们将 Java 应用暴露的 JMX 指标通过 JMX Exporter 导出为 Prometheus 格式。
步骤 1:下载 jmx_exporter
从 Prometheus JMX Exporter 页面 下载 jmx_prometheus_javaagent.jar(请自行搜索最新官方发布页)。
步骤 2:编写 config.yaml
rules: - pattern: ".*"
(简单起见,导出所有指标;生产环境应精细化配置)
步骤 3:启动 Java 应用时附加 Agent
java -javaagent:/path/to/jmx_prometheus_javaagent.jar=8081:/path/to/config.yaml \
-jar your-application.jar
此时访问 http://localhost:8081/metrics 可看到类似:
# HELP com_example_monitoring_DiskMonitor_ReadBytesPerSecond
# TYPE com_example_monitoring_DiskMonitor_ReadBytesPerSecond gauge
com_example_monitoring_DiskMonitor_ReadBytesPerSecond{deviceName="sda",} 131072.0
com_example_monitoring_DiskMonitor_WriteBytesPerSecond{deviceName="sda",} 65536.0
步骤 4:配置 Prometheus 抓取
在 prometheus.yml 中添加:
scrape_configs:
- job_name: 'java-disk-monitor'
static_configs:
- targets: ['localhost:8081']
重启 Prometheus。
步骤 5:Grafana 创建仪表盘
添加 Prometheus 数据源,创建新面板,使用 PromQL 查询:
com_example_monitoring_DiskMonitor_ReadBytesPerSecond{deviceName="sda"} / 1024
单位设为 KB/s,即可看到实时曲线图。
mermaid 图表:磁盘监控架构流程

该架构实现了从应用层到告警通道的全链路监控闭环。
告警策略与阈值建议
合理的告警能避免“狼来了”效应。以下是针对磁盘 I/O 的典型告警规则(Prometheus AlertManager 配置):
groups:
- name: disk-alerts
rules:
- alert: HighDiskUtilization
expr: com_example_monitoring_DiskMonitor_Utilization{deviceName=~"sd.*"} > 85
for: 5m
labels:
severity: warning
annotations:
summary: "High disk utilization on {{ $labels.deviceName }}"
description: "Disk {{ $labels.deviceName }} has been over 85% utilization for 5 minutes."
- alert: DiskIOPSLimitApproaching
expr: com_example_monitoring_DiskMonitor_IOPS{deviceName="nvme0n1"} > 50000
for: 2m
labels:
severity: critical
annotations:
summary: "NVMe drive approaching IOPS limit"
description: "Device nvme0n1 is sustaining >50K IOPS, may impact latency."
- alert: ZeroDiskActivitySuspicious
expr: com_example_monitoring_DiskMonitor_ReadBytesPerSecond{deviceName="sdb"} == 0
for: 10m
labels:
severity: warning
annotations:
summary: "Disk sdb has zero activity for 10m"
description: "This may indicate failure or misconfiguration."
告警黄金法则:
- 相关性:确保告警与业务影响强相关
- 可操作性:收到告警后知道该做什么
- 分级制:区分 Warning / Critical
- 抑制机制:避免重复轰炸
性能调优实战案例
案例一:日志写入导致 %util 飙升
现象:某 Java 服务每隔 5 分钟 %util 达到 95%,GC 暂停时间增加。
诊断:
# 使用 iotop 定位进程 sudo iotop -oPa # 发现 Java 进程在刷日志 Total DISK READ: 0.00 B/s | Total DISK WRITE: 45.23 M/s PID PRIO USER DISK READ DISK WRITE COMMAND 1234 be/4 appuser 0.00 B/s 45.23 M/s java -jar app.jar
解决方案:
- 将日志框架从同步改为异步(Logback AsyncAppender)
- 增加日志缓冲区大小
- 使用更快的存储介质(如 SSD 专用日志盘)
调整后 Logback 配置:
<appender name="ASYNC" class="ch.qos.logback.classic.AsyncAppender">
<appender-ref ref="FILE"/>
<queueSize>8192</queueSize>
<discardingThreshold>0</discardingThreshold>
<includeCallerData>false</includeCallerData>
</appender>
案例二:数据库写入延迟高
现象:MySQL INSERT 延迟从 2ms 升至 50ms。
排查步骤:
# 查看设备详细统计 iostat -xmt 1 # 输出显示 await 很高 Device: rrqm/s wrqm/s r/s w/s rMB/s wMB/s avgrq-sz avgqu-sz await r_await w_await svctm %util sdb 0.00 5.00 0.00 200.00 0.00 8.00 81.92 8.00 40.00 0.00 40.00 5.00 100.00
await=40ms 表示平均 I/O 等待时间,远高于正常值(<5ms)。
根因分析:
- 磁盘队列深度(avgqu-sz=8)过高
- 服务时间(svctm=5ms)尚可,说明是排队导致延迟
优化措施:
- 调整 I/O Scheduler:
echo deadline > /sys/block/sdb/queue/scheduler - 增大 nr_requests:
echo 1024 > /sys/block/sdb/queue/nr_requests - 应用层批量提交事务,减少小 I/O
自动化脚本:生成每日磁盘报告
结合 Java 与 Shell,我们可以每天凌晨生成磁盘健康报告。
Java 部分(生成 JSON 数据):
import com.fasterxml.jackson.databind.ObjectMapper;
import oshi.hardware.HWDiskStore;
import oshi.hardware.HardwareAbstractionLayer;
import oshi.SystemInfo;
import java.io.FileWriter;
import java.time.LocalDate;
import java.util.Arrays;
import java.util.List;
import java.util.stream.Collectors;
public class DailyDiskReportGenerator {
public static void main(String[] args) throws Exception {
SystemInfo si = new SystemInfo();
HardwareAbstractionLayer hal = si.getHardware();
HWDiskStore[] disks = hal.getDiskStores();
List<DiskSummary> summaries = Arrays.stream(disks)
.map(disk -> new DiskSummary(
disk.getName(),
disk.getSize(),
disk.getReadBytes(),
disk.getWriteBytes(),
disk.getReads(),
disk.getWrites()))
.collect(Collectors.toList());
ObjectMapper mapper = new ObjectMapper();
String json = mapper.writerWithDefaultPrettyPrinter().writeValueAsString(summaries);
String filename = String.format("/var/log/disk-report-%s.json", LocalDate.now());
try (FileWriter fw = new FileWriter(filename)) {
fw.write(json);
}
System.out.println("Report written to: " + filename);
}
static class DiskSummary {
public String name;
public long size;
public long totalReadBytes;
public long totalWriteBytes;
public long totalReads;
public long totalWrites;
public DiskSummary(String name, long size, long totalReadBytes, long totalWriteBytes, long totalReads, long totalWrites) {
this.name = name;
this.size = size;
this.totalReadBytes = totalReadBytes;
this.totalWriteBytes = totalWriteBytes;
this.totalReads = totalReads;
this.totalWrites = totalWrites;
}
}
}
Shell 脚本(/etc/cron.daily/disk-report):
#!/bin/bash # 设置 Java 环境 export JAVA_HOME=/usr/lib/jvm/java-11-openjdk-amd64 export PATH=$JAVA_HOME/bin:$PATH cd /opt/disk-monitor java -cp "lib/*:target/*" DailyDiskReportGenerator # 可选:发送邮件或上传到对象存储 # mail -s "Daily Disk Report" admin@company.com < /var/log/disk-report-$(date +%Y-%m-%d).json
赋予执行权限:
sudo chmod +x /etc/cron.daily/disk-report
单元测试你的监控逻辑
良好的监控代码也应具备可测试性。
import org.junit.jupiter.api.Test;
import org.mockito.Mockito;
import static org.junit.jupiter.api.Assertions.assertTrue;
public class DiskMonitorTest {
@Test
public void testCalculateReadRate() {
HWDiskStore mockPrev = Mockito.mock(HWDiskStore.class);
HWDiskStore mockCurr = Mockito.mock(HWDiskStore.class);
Mockito.when(mockPrev.getReadBytes()).thenReturn(1024L);
Mockito.when(mockCurr.getReadBytes()).thenReturn(5120L); // +4096 bytes
Mockito.when(mockPrev.getTimeStamp()).thenReturn(1000L);
Mockito.when(mockCurr.getTimeStamp()).thenReturn(3000L); // 2 seconds later
double rate = (mockCurr.getReadBytes() - mockPrev.getReadBytes()) * 1000.0 /
(mockCurr.getTimeStamp() - mockPrev.getTimeStamp());
assertTrue(Math.abs(rate - 2048.0) < 0.01); // 2048 bytes/sec
}
@Test
public void testZeroTimeDiffReturnsZero() {
HWDiskStore mockPrev = Mockito.mock(HWDiskStore.class);
HWDiskStore mockCurr = Mockito.mock(HWDiskStore.class);
Mockito.when(mockPrev.getTimeStamp()).thenReturn(1000L);
Mockito.when(mockCurr.getTimeStamp()).thenReturn(1000L);
double rate = (mockCurr.getReadBytes() - mockPrev.getReadBytes()) * 1000.0 /
(mockCurr.getTimeStamp() - mockPrev.getTimeStamp());
assertTrue(Double.isNaN(rate) || rate == 0.0);
}
}
云端环境注意事项
在 AWS EC2、阿里云 ECS 等云主机上,磁盘 I/O 行为略有不同:
- EBS 卷:有基准 IOPS 限制,突发型实例使用积分制
- 实例存储:高性能但临时性,重启即丢失
- 网络延迟:云盘本质是网络存储,延迟高于本地 SSD
监控建议:
- 同时监控
CloudWatch或云厂商原生监控 - 关注 BurstBalance(突发积分余额)
- 对比
iostat与云监控数据,验证一致性
AWS CLI 示例:
aws cloudwatch get-metric-statistics \
--namespace AWS/EBS \
--metric-name VolumeReadBytes \
--dimensions Name=VolumeId,Value=vol-1234567890abcdef0 \
--start-time $(date -u -d '1 hour ago' '+%Y-%m-%dT%H:%M:%SZ') \
--end-time $(date -u '+%Y-%m-%dT%H:%M:%SZ') \
--period 300 \
--statistics Sum
未来演进方向
随着 eBPF、io_uring 等新技术普及,磁盘监控也在进化:
- eBPF:无需修改内核即可追踪 I/O 路径,开销极低
- io_uring:异步 I/O 新接口,需适配监控工具
- OpenTelemetry:统一观测性标准,未来可能替代部分 JMX/Prometheus
总结
磁盘 I/O 监控不是一次性任务,而是持续优化的过程。我们从基础命令出发,逐步构建了:
- 实时监控(iostat/iotop)
- 程序集成(Java + OSHI)
- 标准化暴露(JMX → Prometheus)
- 可视化与告警(Grafana + AlertManager)
- 自动化报告
- 性能调优闭环
记住几个关键原则:
🔹 监控一切,但只告警重要的事
🔹 指标要可聚合、可对比、可预测
🔹 与业务指标联动(如“磁盘延迟上升 → 订单处理变慢”)
🔹 定期回顾告警有效性,删除噪音规则
以上就是Linux监控系统磁盘IO的方法汇总的详细内容,更多关于Linux监控系统磁盘IO的资料请关注脚本之家其它相关文章!
