1. 硬盘运维监控概述

硬盘是服务器存储的核心组件,硬盘空间不足、IO性能差、硬盘故障等问题会严重影响系统性能。本文将详细介绍硬盘监控、IO性能优化、磁盘空间管理和硬盘健康检查的完整解决方案,帮助运维人员有效管理硬盘资源。

1.1 核心挑战

  1. 硬盘使用率监控: 实时监控硬盘空间使用情况
  2. IO性能监控: 监控硬盘读写性能和IO延迟
  3. 磁盘空间管理: 自动清理和空间优化
  4. 硬盘健康检查: 检测硬盘故障和健康状态
  5. 性能优化: 优化硬盘IO性能

1.2 技术架构

1
2
3
4
5
硬盘监控 → 数据采集 → 性能分析 → 告警通知 → 自动优化
↓ ↓ ↓ ↓ ↓
磁盘空间 → 监控代理 → 数据存储 → 告警引擎 → 清理脚本
↓ ↓ ↓ ↓ ↓
IO性能 → 性能分析 → 趋势分析 → 通知推送 → 参数调整

2. 硬盘监控系统

2.1 Maven依赖配置

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
<!-- pom.xml -->
<dependencies>
<!-- Spring Boot Web -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>

<!-- Spring Boot Data Redis -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>

<!-- OSHI系统信息 -->
<dependency>
<groupId>com.github.oshi</groupId>
<artifactId>oshi-core</artifactId>
<version>6.4.0</version>
</dependency>

<!-- Apache Commons IO -->
<dependency>
<groupId>commons-io</groupId>
<artifactId>commons-io</artifactId>
<version>2.11.0</version>
</dependency>

<!-- MyBatis Plus -->
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus-boot-starter</artifactId>
<version>3.5.2</version>
</dependency>
</dependencies>

2.2 应用配置

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
# application.yml
server:
port: 8080

spring:
redis:
host: localhost
port: 6379
database: 0

# 硬盘监控配置
disk-monitor:
collection-interval: 10000 # 采集间隔(毫秒)
space-alert-threshold: 85 # 空间告警阈值(%)
space-critical-threshold: 95 # 空间严重告警阈值(%)
io-alert-threshold: 80 # IO告警阈值(%)
health-check-enabled: true # 启用健康检查
auto-cleanup-enabled: true # 启用自动清理

3. 硬盘监控服务

3.1 硬盘监控实体类

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
/**
* 硬盘监控数据实体类
*/
@Data
@TableName("disk_monitor_data")
public class DiskMonitorData {

@TableId(type = IdType.AUTO)
private Long id; // 主键ID

private String hostname; // 主机名

private String ip; // IP地址

private String deviceName; // 设备名称

private String mountPoint; // 挂载点

private Long totalSpace; // 总空间

private Long usedSpace; // 已使用空间

private Long freeSpace; // 空闲空间

private Double spaceUsage; // 空间使用率

private Long readBytes; // 读取字节数

private Long writeBytes; // 写入字节数

private Long readOps; // 读取操作数

private Long writeOps; // 写入操作数

private Double readLatency; // 读取延迟

private Double writeLatency; // 写入延迟

private Double ioUtilization; // IO利用率

private Integer temperature; // 硬盘温度

private String healthStatus; // 健康状态

private Date collectTime; // 采集时间

private Date createTime; // 创建时间
}

/**
* 硬盘告警记录实体类
*/
@Data
@TableName("disk_alert_record")
public class DiskAlertRecord {

@TableId(type = IdType.AUTO)
private Long id; // 主键ID

private String hostname; // 主机名

private String deviceName; // 设备名称

private String alertType; // 告警类型

private String alertLevel; // 告警级别

private String alertMessage; // 告警消息

private String alertStatus; // 告警状态

private Date alertTime; // 告警时间

private Date resolveTime; // 解决时间

private String resolveMessage; // 解决说明
}

3.2 硬盘监控服务

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
/**
* 硬盘监控服务
* 负责硬盘数据的采集、存储和分析
*/
@Service
public class DiskMonitorService {

@Autowired
private DiskMonitorDataMapper diskMonitorDataMapper;

@Autowired
private DiskAlertRecordMapper diskAlertRecordMapper;

@Autowired
private RedisTemplate<String, Object> redisTemplate;

@Autowired
private AlertService alertService;

/**
* 采集硬盘数据
* 定期采集硬盘使用情况和IO性能
*/
@Scheduled(fixedRate = 10000) // 每10秒执行一次
public void collectDiskData() {
try {
// 1. 获取所有硬盘信息
List<DiskInfo> diskInfos = getDiskInfos();

// 2. 采集每个硬盘的数据
for (DiskInfo diskInfo : diskInfos) {
collectDiskInfoData(diskInfo);
}

// 3. 分析硬盘性能
analyzeDiskPerformance();

} catch (Exception e) {
log.error("采集硬盘数据失败: {}", e.getMessage(), e);
}
}

/**
* 获取硬盘信息列表
*/
private List<DiskInfo> getDiskInfos() {
List<DiskInfo> diskInfos = new ArrayList<>();

try {
// 使用OSHI获取硬盘信息
SystemInfo systemInfo = new SystemInfo();
HardwareAbstractionLayer hal = systemInfo.getHardware();
List<HWDiskStore> diskStores = hal.getDiskStores();

for (HWDiskStore diskStore : diskStores) {
DiskInfo diskInfo = new DiskInfo();
diskInfo.setName(diskStore.getName());
diskInfo.setModel(diskStore.getModel());
diskInfo.setSerial(diskStore.getSerial());
diskInfo.setSize(diskStore.getSize());
diskInfo.setTemperature(diskStore.getTemperature());

diskInfos.add(diskInfo);
}

// 获取文件系统信息
List<OSFileStore> fileStores = hal.getFileStores();
for (OSFileStore fileStore : fileStores) {
DiskInfo diskInfo = new DiskInfo();
diskInfo.setName(fileStore.getName());
diskInfo.setMountPoint(fileStore.getMount());
diskInfo.setTotalSpace(fileStore.getTotalSpace());
diskInfo.setFreeSpace(fileStore.getUsableSpace());
diskInfo.setUsedSpace(fileStore.getTotalSpace() - fileStore.getUsableSpace());
diskInfo.setSpaceUsage((double) diskInfo.getUsedSpace() / diskInfo.getTotalSpace() * 100);

diskInfos.add(diskInfo);
}

} catch (Exception e) {
log.error("获取硬盘信息失败: {}", e.getMessage(), e);
}

return diskInfos;
}

/**
* 采集单个硬盘数据
*/
private void collectDiskInfoData(DiskInfo diskInfo) {
try {
// 1. 创建硬盘监控数据
DiskMonitorData diskData = createDiskMonitorData(diskInfo);

// 2. 保存到数据库
diskMonitorDataMapper.insert(diskData);

// 3. 更新缓存
updateDiskCache(diskData);

// 4. 检查硬盘告警
checkDiskAlert(diskData);

log.debug("采集硬盘数据: deviceName={}, spaceUsage={}%",
diskData.getDeviceName(), diskData.getSpaceUsage());

} catch (Exception e) {
log.error("采集硬盘数据失败: deviceName={}, error={}",
diskInfo.getName(), e.getMessage(), e);
}
}

/**
* 创建硬盘监控数据
*/
private DiskMonitorData createDiskMonitorData(DiskInfo diskInfo) {
DiskMonitorData diskData = new DiskMonitorData();

// 设置基本信息
diskData.setHostname(getHostname());
diskData.setIp(getLocalIpAddress());
diskData.setDeviceName(diskInfo.getName());
diskData.setMountPoint(diskInfo.getMountPoint());
diskData.setCollectTime(new Date());
diskData.setCreateTime(new Date());

// 设置空间信息
diskData.setTotalSpace(diskInfo.getTotalSpace());
diskData.setUsedSpace(diskInfo.getUsedSpace());
diskData.setFreeSpace(diskInfo.getFreeSpace());
diskData.setSpaceUsage(diskInfo.getSpaceUsage());

// 设置IO信息
diskData.setReadBytes(diskInfo.getReadBytes());
diskData.setWriteBytes(diskInfo.getWriteBytes());
diskData.setReadOps(diskInfo.getReadOps());
diskData.setWriteOps(diskInfo.getWriteOps());
diskData.setReadLatency(diskInfo.getReadLatency());
diskData.setWriteLatency(diskInfo.getWriteLatency());
diskData.setIoUtilization(diskInfo.getIoUtilization());

// 设置健康信息
diskData.setTemperature(diskInfo.getTemperature());
diskData.setHealthStatus(diskInfo.getHealthStatus());

return diskData;
}

/**
* 更新硬盘缓存
*/
private void updateDiskCache(DiskMonitorData diskData) {
try {
String cacheKey = "disk:realtime:" + diskData.getHostname() + ":" + diskData.getDeviceName();
redisTemplate.opsForValue().set(cacheKey, diskData, Duration.ofMinutes(5));

// 更新历史数据缓存
String historyKey = "disk:history:" + diskData.getHostname() + ":" + diskData.getDeviceName();
redisTemplate.opsForList().leftPush(historyKey, diskData);
redisTemplate.opsForList().trim(historyKey, 0, 99);
redisTemplate.expire(historyKey, Duration.ofHours(1));

} catch (Exception e) {
log.warn("更新硬盘缓存失败: {}", e.getMessage());
}
}

/**
* 检查硬盘告警
*/
private void checkDiskAlert(DiskMonitorData diskData) {
try {
String alertType = null;
String alertLevel = null;
String alertMessage = null;

// 检查空间使用率告警
if (diskData.getSpaceUsage() >= 95) {
alertType = "DISK_SPACE_CRITICAL";
alertLevel = "CRITICAL";
alertMessage = String.format("硬盘空间严重不足: %s 使用率 %.2f%%",
diskData.getDeviceName(), diskData.getSpaceUsage());
} else if (diskData.getSpaceUsage() >= 85) {
alertType = "DISK_SPACE_HIGH";
alertLevel = "WARNING";
alertMessage = String.format("硬盘空间不足: %s 使用率 %.2f%%",
diskData.getDeviceName(), diskData.getSpaceUsage());
}

// 检查IO性能告警
if (diskData.getIoUtilization() >= 90) {
alertType = "DISK_IO_HIGH";
alertLevel = "WARNING";
alertMessage = String.format("硬盘IO性能差: %s IO利用率 %.2f%%",
diskData.getDeviceName(), diskData.getIoUtilization());
}

// 检查硬盘温度告警
if (diskData.getTemperature() != null && diskData.getTemperature() > 60) {
alertType = "DISK_TEMPERATURE_HIGH";
alertLevel = "WARNING";
alertMessage = String.format("硬盘温度过高: %s 温度 %d°C",
diskData.getDeviceName(), diskData.getTemperature());
}

// 检查硬盘健康状态
if ("FAILED".equals(diskData.getHealthStatus())) {
alertType = "DISK_HEALTH_FAILED";
alertLevel = "CRITICAL";
alertMessage = String.format("硬盘健康状态异常: %s", diskData.getDeviceName());
}

// 发送告警
if (alertType != null) {
sendDiskAlert(diskData, alertType, alertLevel, alertMessage);
}

} catch (Exception e) {
log.error("检查硬盘告警失败: {}", e.getMessage(), e);
}
}

/**
* 发送硬盘告警
*/
private void sendDiskAlert(DiskMonitorData diskData, String alertType, String alertLevel, String alertMessage) {
try {
// 检查是否已经发送过相同告警
String alertKey = "disk:alert:" + diskData.getHostname() + ":" + diskData.getDeviceName() + ":" + alertType;
Boolean hasAlert = redisTemplate.hasKey(alertKey);

if (hasAlert == null || !hasAlert) {
// 创建告警记录
DiskAlertRecord alertRecord = new DiskAlertRecord();
alertRecord.setHostname(diskData.getHostname());
alertRecord.setDeviceName(diskData.getDeviceName());
alertRecord.setAlertType(alertType);
alertRecord.setAlertLevel(alertLevel);
alertRecord.setAlertMessage(alertMessage);
alertRecord.setAlertStatus("ACTIVE");
alertRecord.setAlertTime(new Date());

// 发送告警通知
alertService.sendDiskAlert(alertRecord);

// 设置告警缓存
redisTemplate.opsForValue().set(alertKey, "1", Duration.ofMinutes(5));

log.warn("发送硬盘告警: hostname={}, deviceName={}, type={}, level={}",
diskData.getHostname(), diskData.getDeviceName(), alertType, alertLevel);
}

} catch (Exception e) {
log.error("发送硬盘告警失败: {}", e.getMessage(), e);
}
}

/**
* 分析硬盘性能
*/
private void analyzeDiskPerformance() {
try {
// 获取所有硬盘的实时数据
List<DiskMonitorData> diskDataList = getRealTimeDiskData();

// 分析整体性能
analyzeOverallPerformance(diskDataList);

// 分析IO性能
analyzeIoPerformance(diskDataList);

} catch (Exception e) {
log.error("分析硬盘性能失败: {}", e.getMessage(), e);
}
}

/**
* 分析整体性能
*/
private void analyzeOverallPerformance(List<DiskMonitorData> diskDataList) {
try {
// 计算平均空间使用率
double avgSpaceUsage = diskDataList.stream()
.mapToDouble(DiskMonitorData::getSpaceUsage)
.average()
.orElse(0.0);

// 计算平均IO利用率
double avgIoUtilization = diskDataList.stream()
.mapToDouble(DiskMonitorData::getIoUtilization)
.average()
.orElse(0.0);

// 更新性能统计
updatePerformanceStats(avgSpaceUsage, avgIoUtilization);

log.debug("硬盘整体性能分析: avgSpaceUsage={}%, avgIoUtilization={}%",
avgSpaceUsage, avgIoUtilization);

} catch (Exception e) {
log.error("分析整体性能失败: {}", e.getMessage(), e);
}
}

/**
* 分析IO性能
*/
private void analyzeIoPerformance(List<DiskMonitorData> diskDataList) {
try {
// 找出IO性能最差的硬盘
DiskMonitorData worstIoDisk = diskDataList.stream()
.max(Comparator.comparing(DiskMonitorData::getIoUtilization))
.orElse(null);

if (worstIoDisk != null && worstIoDisk.getIoUtilization() > 80) {
log.warn("发现IO性能差的硬盘: deviceName={}, ioUtilization={}%",
worstIoDisk.getDeviceName(), worstIoDisk.getIoUtilization());
}

} catch (Exception e) {
log.error("分析IO性能失败: {}", e.getMessage(), e);
}
}

/**
* 更新性能统计
*/
private void updatePerformanceStats(double avgSpaceUsage, double avgIoUtilization) {
try {
String statsKey = "disk:performance:" + getHostname();

Map<String, Object> stats = new HashMap<>();
stats.put("avgSpaceUsage", avgSpaceUsage);
stats.put("avgIoUtilization", avgIoUtilization);
stats.put("lastUpdateTime", System.currentTimeMillis());

redisTemplate.opsForValue().set(statsKey, stats, Duration.ofMinutes(10));

} catch (Exception e) {
log.warn("更新性能统计失败: {}", e.getMessage());
}
}

/**
* 获取实时硬盘数据
*/
public List<DiskMonitorData> getRealTimeDiskData() {
List<DiskMonitorData> diskDataList = new ArrayList<>();

try {
String hostname = getHostname();
String pattern = "disk:realtime:" + hostname + ":*";

Set<String> keys = redisTemplate.keys(pattern);
if (keys != null) {
for (String key : keys) {
DiskMonitorData diskData = (DiskMonitorData) redisTemplate.opsForValue().get(key);
if (diskData != null) {
diskDataList.add(diskData);
}
}
}

} catch (Exception e) {
log.error("获取实时硬盘数据失败: {}", e.getMessage(), e);
}

return diskDataList;
}

/**
* 获取硬盘历史数据
*/
public List<DiskMonitorData> getDiskHistoryData(String hostname, String deviceName, Date startTime, Date endTime) {
return diskMonitorDataMapper.selectByHostnameAndDeviceNameAndTimeRange(hostname, deviceName, startTime, endTime);
}

/**
* 获取硬盘性能统计
*/
public Map<String, Object> getDiskPerformanceStats(String hostname) {
String statsKey = "disk:performance:" + hostname;
return (Map<String, Object>) redisTemplate.opsForValue().get(statsKey);
}

/**
* 获取活跃告警
*/
public List<DiskAlertRecord> getActiveAlerts(String hostname) {
return diskAlertRecordMapper.selectActiveAlertsByHostname(hostname);
}

/**
* 获取主机名
*/
private String getHostname() {
try {
return InetAddress.getLocalHost().getHostName();
} catch (UnknownHostException e) {
return "unknown";
}
}

/**
* 获取本地IP地址
*/
private String getLocalIpAddress() {
try {
return InetAddress.getLocalHost().getHostAddress();
} catch (UnknownHostException e) {
return "127.0.0.1";
}
}
}

/**
* 硬盘信息实体类
*/
@Data
public class DiskInfo {
private String name; // 设备名称
private String model; // 硬盘型号
private String serial; // 序列号
private String mountPoint; // 挂载点
private Long size; // 硬盘大小
private Long totalSpace; // 总空间
private Long usedSpace; // 已使用空间
private Long freeSpace; // 空闲空间
private Double spaceUsage; // 空间使用率
private Long readBytes; // 读取字节数
private Long writeBytes; // 写入字节数
private Long readOps; // 读取操作数
private Long writeOps; // 写入操作数
private Double readLatency; // 读取延迟
private Double writeLatency; // 写入延迟
private Double ioUtilization; // IO利用率
private Integer temperature; // 硬盘温度
private String healthStatus; // 健康状态
}

4. 硬盘优化服务

4.1 硬盘优化服务

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
/**
* 硬盘优化服务
* 提供硬盘优化和空间管理功能
*/
@Service
public class DiskOptimizationService {

@Autowired
private DiskMonitorService diskMonitorService;

@Autowired
private AlertService alertService;

/**
* 自动硬盘优化
* 根据硬盘使用情况自动进行优化
*/
@Scheduled(fixedRate = 300000) // 每5分钟执行一次
public void autoOptimizeDisk() {
try {
String hostname = getHostname();
List<DiskMonitorData> diskDataList = diskMonitorService.getRealTimeDiskData();

// 检查每个硬盘的使用情况
for (DiskMonitorData diskData : diskDataList) {
if (diskData.getSpaceUsage() > 90) {
// 硬盘空间严重不足,执行紧急优化
executeEmergencyOptimization(diskData);
} else if (diskData.getSpaceUsage() > 80) {
// 硬盘空间不足,执行预防性优化
executePreventiveOptimization(diskData);
}
}

} catch (Exception e) {
log.error("自动硬盘优化失败: {}", e.getMessage(), e);
}
}

/**
* 执行紧急优化
*/
private void executeEmergencyOptimization(DiskMonitorData diskData) {
log.warn("执行紧急硬盘优化: deviceName={}, spaceUsage={}%",
diskData.getDeviceName(), diskData.getSpaceUsage());

try {
// 1. 清理临时文件
cleanupTempFiles(diskData.getMountPoint());

// 2. 清理日志文件
cleanupLogFiles(diskData.getMountPoint());

// 3. 清理缓存文件
cleanupCacheFiles(diskData.getMountPoint());

// 4. 清理旧文件
cleanupOldFiles(diskData.getMountPoint());

// 5. 发送优化通知
sendOptimizationNotification(diskData, "EMERGENCY_OPTIMIZATION");

} catch (Exception e) {
log.error("执行紧急优化失败: {}", e.getMessage(), e);
}
}

/**
* 执行预防性优化
*/
private void executePreventiveOptimization(DiskMonitorData diskData) {
log.info("执行预防性硬盘优化: deviceName={}, spaceUsage={}%",
diskData.getDeviceName(), diskData.getSpaceUsage());

try {
// 1. 清理临时文件
cleanupTempFiles(diskData.getMountPoint());

// 2. 清理日志文件
cleanupLogFiles(diskData.getMountPoint());

// 3. 优化文件系统
optimizeFileSystem(diskData.getMountPoint());

// 4. 发送优化通知
sendOptimizationNotification(diskData, "PREVENTIVE_OPTIMIZATION");

} catch (Exception e) {
log.error("执行预防性优化失败: {}", e.getMessage(), e);
}
}

/**
* 清理临时文件
*/
private void cleanupTempFiles(String mountPoint) {
log.info("清理临时文件: mountPoint={}", mountPoint);

try {
// 清理系统临时目录
cleanupDirectory(mountPoint + "/tmp");
cleanupDirectory(mountPoint + "/var/tmp");

// 清理用户临时目录
cleanupDirectory(mountPoint + "/home/*/tmp");

} catch (Exception e) {
log.error("清理临时文件失败: {}", e.getMessage(), e);
}
}

/**
* 清理日志文件
*/
private void cleanupLogFiles(String mountPoint) {
log.info("清理日志文件: mountPoint={}", mountPoint);

try {
// 清理系统日志
cleanupDirectory(mountPoint + "/var/log");

// 清理应用日志
cleanupDirectory(mountPoint + "/var/log/*");

} catch (Exception e) {
log.error("清理日志文件失败: {}", e.getMessage(), e);
}
}

/**
* 清理缓存文件
*/
private void cleanupCacheFiles(String mountPoint) {
log.info("清理缓存文件: mountPoint={}", mountPoint);

try {
// 清理系统缓存
cleanupDirectory(mountPoint + "/var/cache");

// 清理应用缓存
cleanupDirectory(mountPoint + "/home/*/.cache");

} catch (Exception e) {
log.error("清理缓存文件失败: {}", e.getMessage(), e);
}
}

/**
* 清理旧文件
*/
private void cleanupOldFiles(String mountPoint) {
log.info("清理旧文件: mountPoint={}", mountPoint);

try {
// 清理7天前的文件
cleanupOldFilesInDirectory(mountPoint + "/tmp", 7);
cleanupOldFilesInDirectory(mountPoint + "/var/log", 30);

} catch (Exception e) {
log.error("清理旧文件失败: {}", e.getMessage(), e);
}
}

/**
* 清理目录
*/
private void cleanupDirectory(String directoryPath) {
try {
Path path = Paths.get(directoryPath);
if (Files.exists(path) && Files.isDirectory(path)) {
Files.walk(path)
.filter(Files::isRegularFile)
.forEach(file -> {
try {
Files.delete(file);
log.debug("删除文件: {}", file);
} catch (IOException e) {
log.warn("删除文件失败: {}", file);
}
});
}
} catch (Exception e) {
log.warn("清理目录失败: {}", directoryPath);
}
}

/**
* 清理目录中的旧文件
*/
private void cleanupOldFilesInDirectory(String directoryPath, int days) {
try {
Path path = Paths.get(directoryPath);
if (Files.exists(path) && Files.isDirectory(path)) {
Instant cutoffTime = Instant.now().minus(days, ChronoUnit.DAYS);

Files.walk(path)
.filter(Files::isRegularFile)
.filter(file -> {
try {
return Files.getLastModifiedTime(file).toInstant().isBefore(cutoffTime);
} catch (IOException e) {
return false;
}
})
.forEach(file -> {
try {
Files.delete(file);
log.debug("删除旧文件: {}", file);
} catch (IOException e) {
log.warn("删除旧文件失败: {}", file);
}
});
}
} catch (Exception e) {
log.warn("清理旧文件失败: {}", directoryPath);
}
}

/**
* 优化文件系统
*/
private void optimizeFileSystem(String mountPoint) {
log.info("优化文件系统: mountPoint={}", mountPoint);

try {
// 执行文件系统检查
checkFileSystem(mountPoint);

// 执行文件系统优化
optimizeFileSystemPerformance(mountPoint);

} catch (Exception e) {
log.error("优化文件系统失败: {}", e.getMessage(), e);
}
}

/**
* 检查文件系统
*/
private void checkFileSystem(String mountPoint) {
try {
// 检查文件系统错误
ProcessBuilder pb = new ProcessBuilder("fsck", "-n", mountPoint);
Process process = pb.start();

int exitCode = process.waitFor();
if (exitCode != 0) {
log.warn("文件系统检查发现问题: mountPoint={}", mountPoint);
}

} catch (Exception e) {
log.error("检查文件系统失败: {}", e.getMessage(), e);
}
}

/**
* 优化文件系统性能
*/
private void optimizeFileSystemPerformance(String mountPoint) {
try {
// 执行文件系统碎片整理
defragmentFileSystem(mountPoint);

// 优化文件系统参数
optimizeFileSystemParameters(mountPoint);

} catch (Exception e) {
log.error("优化文件系统性能失败: {}", e.getMessage(), e);
}
}

/**
* 执行文件系统碎片整理
*/
private void defragmentFileSystem(String mountPoint) {
// 实现文件系统碎片整理逻辑
log.info("执行文件系统碎片整理: mountPoint={}", mountPoint);
}

/**
* 优化文件系统参数
*/
private void optimizeFileSystemParameters(String mountPoint) {
// 实现文件系统参数优化逻辑
log.info("优化文件系统参数: mountPoint={}", mountPoint);
}

/**
* 发送优化通知
*/
private void sendOptimizationNotification(DiskMonitorData diskData, String optimizationType) {
try {
AlertMessage alert = new AlertMessage();
alert.setType("DISK_OPTIMIZATION");
alert.setLevel("INFO");
alert.setMessage(String.format("硬盘优化完成: 类型=%s, 设备=%s, 空间使用率=%.2f%%",
optimizationType, diskData.getDeviceName(), diskData.getSpaceUsage()));
alert.setTimestamp(new Date());

alertService.sendAlert(alert);

} catch (Exception e) {
log.error("发送优化通知失败: {}", e.getMessage(), e);
}
}

/**
* 获取主机名
*/
private String getHostname() {
try {
return InetAddress.getLocalHost().getHostName();
} catch (UnknownHostException e) {
return "unknown";
}
}
}

5. 硬盘健康检查服务

5.1 硬盘健康检查服务

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
/**
* 硬盘健康检查服务
* 负责硬盘健康状态检查和故障预测
*/
@Service
public class DiskHealthCheckService {

@Autowired
private DiskMonitorService diskMonitorService;

@Autowired
private AlertService alertService;

/**
* 硬盘健康检查
* 定期检查硬盘健康状态
*/
@Scheduled(fixedRate = 3600000) // 每1小时执行一次
public void checkDiskHealth() {
try {
String hostname = getHostname();
List<DiskMonitorData> diskDataList = diskMonitorService.getRealTimeDiskData();

// 检查每个硬盘的健康状态
for (DiskMonitorData diskData : diskDataList) {
checkSingleDiskHealth(diskData);
}

} catch (Exception e) {
log.error("硬盘健康检查失败: {}", e.getMessage(), e);
}
}

/**
* 检查单个硬盘健康状态
*/
private void checkSingleDiskHealth(DiskMonitorData diskData) {
try {
// 1. 检查硬盘温度
checkDiskTemperature(diskData);

// 2. 检查硬盘IO性能
checkDiskIoPerformance(diskData);

// 3. 检查硬盘空间使用
checkDiskSpaceUsage(diskData);

// 4. 检查硬盘错误
checkDiskErrors(diskData);

// 5. 预测硬盘故障
predictDiskFailure(diskData);

} catch (Exception e) {
log.error("检查硬盘健康状态失败: deviceName={}, error={}",
diskData.getDeviceName(), e.getMessage(), e);
}
}

/**
* 检查硬盘温度
*/
private void checkDiskTemperature(DiskMonitorData diskData) {
if (diskData.getTemperature() != null) {
if (diskData.getTemperature() > 70) {
// 硬盘温度过高
sendHealthAlert(diskData, "DISK_TEMPERATURE_HIGH", "WARNING",
String.format("硬盘温度过高: %d°C", diskData.getTemperature()));
} else if (diskData.getTemperature() > 60) {
// 硬盘温度较高
sendHealthAlert(diskData, "DISK_TEMPERATURE_WARNING", "INFO",
String.format("硬盘温度较高: %d°C", diskData.getTemperature()));
}
}
}

/**
* 检查硬盘IO性能
*/
private void checkDiskIoPerformance(DiskMonitorData diskData) {
if (diskData.getIoUtilization() > 95) {
// IO利用率过高
sendHealthAlert(diskData, "DISK_IO_CRITICAL", "CRITICAL",
String.format("硬盘IO利用率过高: %.2f%%", diskData.getIoUtilization()));
} else if (diskData.getIoUtilization() > 80) {
// IO利用率较高
sendHealthAlert(diskData, "DISK_IO_HIGH", "WARNING",
String.format("硬盘IO利用率较高: %.2f%%", diskData.getIoUtilization()));
}

// 检查IO延迟
if (diskData.getReadLatency() > 100) {
sendHealthAlert(diskData, "DISK_READ_LATENCY_HIGH", "WARNING",
String.format("硬盘读取延迟过高: %.2fms", diskData.getReadLatency()));
}

if (diskData.getWriteLatency() > 100) {
sendHealthAlert(diskData, "DISK_WRITE_LATENCY_HIGH", "WARNING",
String.format("硬盘写入延迟过高: %.2fms", diskData.getWriteLatency()));
}
}

/**
* 检查硬盘空间使用
*/
private void checkDiskSpaceUsage(DiskMonitorData diskData) {
if (diskData.getSpaceUsage() > 95) {
// 空间使用率过高
sendHealthAlert(diskData, "DISK_SPACE_CRITICAL", "CRITICAL",
String.format("硬盘空间严重不足: %.2f%%", diskData.getSpaceUsage()));
} else if (diskData.getSpaceUsage() > 85) {
// 空间使用率较高
sendHealthAlert(diskData, "DISK_SPACE_HIGH", "WARNING",
String.format("硬盘空间不足: %.2f%%", diskData.getSpaceUsage()));
}
}

/**
* 检查硬盘错误
*/
private void checkDiskErrors(DiskMonitorData diskData) {
try {
// 检查硬盘SMART信息
checkSmartInfo(diskData);

// 检查硬盘错误日志
checkDiskErrorLogs(diskData);

} catch (Exception e) {
log.error("检查硬盘错误失败: {}", e.getMessage(), e);
}
}

/**
* 检查SMART信息
*/
private void checkSmartInfo(DiskMonitorData diskData) {
try {
// 使用smartctl命令检查SMART信息
ProcessBuilder pb = new ProcessBuilder("smartctl", "-H", diskData.getDeviceName());
Process process = pb.start();

int exitCode = process.waitFor();
if (exitCode != 0) {
sendHealthAlert(diskData, "DISK_SMART_ERROR", "WARNING",
"硬盘SMART检查失败");
}

} catch (Exception e) {
log.error("检查SMART信息失败: {}", e.getMessage(), e);
}
}

/**
* 检查硬盘错误日志
*/
private void checkDiskErrorLogs(DiskMonitorData diskData) {
try {
// 检查系统日志中的硬盘错误
ProcessBuilder pb = new ProcessBuilder("dmesg", "|", "grep", "-i", "error");
Process process = pb.start();

BufferedReader reader = new BufferedReader(new InputStreamReader(process.getInputStream()));
String line;
int errorCount = 0;

while ((line = reader.readLine()) != null) {
if (line.contains(diskData.getDeviceName()) && line.contains("error")) {
errorCount++;
}
}

if (errorCount > 10) {
sendHealthAlert(diskData, "DISK_ERROR_LOG_HIGH", "WARNING",
String.format("硬盘错误日志过多: %d条", errorCount));
}

} catch (Exception e) {
log.error("检查硬盘错误日志失败: {}", e.getMessage(), e);
}
}

/**
* 预测硬盘故障
*/
private void predictDiskFailure(DiskMonitorData diskData) {
try {
// 获取硬盘历史数据
Date endTime = new Date();
Date startTime = new Date(endTime.getTime() - 7 * 24 * 60 * 60 * 1000); // 7天前

List<DiskMonitorData> historyData = diskMonitorService.getDiskHistoryData(
diskData.getHostname(), diskData.getDeviceName(), startTime, endTime);

// 分析故障趋势
analyzeFailureTrend(diskData, historyData);

} catch (Exception e) {
log.error("预测硬盘故障失败: {}", e.getMessage(), e);
}
}

/**
* 分析故障趋势
*/
private void analyzeFailureTrend(DiskMonitorData diskData, List<DiskMonitorData> historyData) {
try {
// 计算平均IO利用率
double avgIoUtilization = historyData.stream()
.mapToDouble(DiskMonitorData::getIoUtilization)
.average()
.orElse(0.0);

// 计算平均温度
double avgTemperature = historyData.stream()
.filter(data -> data.getTemperature() != null)
.mapToInt(DiskMonitorData::getTemperature)
.average()
.orElse(0.0);

// 计算空间使用率趋势
double spaceUsageTrend = calculateSpaceUsageTrend(historyData);

// 评估故障风险
int riskLevel = evaluateFailureRisk(avgIoUtilization, avgTemperature, spaceUsageTrend);

if (riskLevel > 7) {
sendHealthAlert(diskData, "DISK_FAILURE_RISK_HIGH", "WARNING",
String.format("硬盘故障风险较高: 风险等级%d", riskLevel));
} else if (riskLevel > 5) {
sendHealthAlert(diskData, "DISK_FAILURE_RISK_MEDIUM", "INFO",
String.format("硬盘故障风险中等: 风险等级%d", riskLevel));
}

} catch (Exception e) {
log.error("分析故障趋势失败: {}", e.getMessage(), e);
}
}

/**
* 计算空间使用率趋势
*/
private double calculateSpaceUsageTrend(List<DiskMonitorData> historyData) {
if (historyData.size() < 2) {
return 0.0;
}

// 计算空间使用率的变化趋势
double firstUsage = historyData.get(0).getSpaceUsage();
double lastUsage = historyData.get(historyData.size() - 1).getSpaceUsage();

return lastUsage - firstUsage;
}

/**
* 评估故障风险
*/
private int evaluateFailureRisk(double avgIoUtilization, double avgTemperature, double spaceUsageTrend) {
int riskLevel = 0;

// IO利用率风险
if (avgIoUtilization > 90) {
riskLevel += 3;
} else if (avgIoUtilization > 70) {
riskLevel += 2;
} else if (avgIoUtilization > 50) {
riskLevel += 1;
}

// 温度风险
if (avgTemperature > 65) {
riskLevel += 3;
} else if (avgTemperature > 55) {
riskLevel += 2;
} else if (avgTemperature > 45) {
riskLevel += 1;
}

// 空间使用率趋势风险
if (spaceUsageTrend > 5) {
riskLevel += 2;
} else if (spaceUsageTrend > 2) {
riskLevel += 1;
}

return Math.min(riskLevel, 10); // 最高风险等级为10
}

/**
* 发送健康告警
*/
private void sendHealthAlert(DiskMonitorData diskData, String alertType, String alertLevel, String alertMessage) {
try {
// 创建告警记录
DiskAlertRecord alertRecord = new DiskAlertRecord();
alertRecord.setHostname(diskData.getHostname());
alertRecord.setDeviceName(diskData.getDeviceName());
alertRecord.setAlertType(alertType);
alertRecord.setAlertLevel(alertLevel);
alertRecord.setAlertMessage(alertMessage);
alertRecord.setAlertStatus("ACTIVE");
alertRecord.setAlertTime(new Date());

// 发送告警通知
alertService.sendDiskAlert(alertRecord);

log.warn("发送硬盘健康告警: hostname={}, deviceName={}, type={}, level={}",
diskData.getHostname(), diskData.getDeviceName(), alertType, alertLevel);

} catch (Exception e) {
log.error("发送健康告警失败: {}", e.getMessage(), e);
}
}

/**
* 获取主机名
*/
private String getHostname() {
try {
return InetAddress.getLocalHost().getHostName();
} catch (UnknownHostException e) {
return "unknown";
}
}
}

6. 总结

本文详细介绍了硬盘运维监控与优化的完整解决方案,包括:

6.1 核心技术点

  1. 硬盘监控: 实时监控硬盘空间使用率、IO性能、温度等指标
  2. 性能分析: 分析硬盘IO性能、空间使用趋势
  3. 自动优化: 自动清理临时文件、日志文件、缓存文件
  4. 健康检查: 检查硬盘健康状态、预测故障风险
  5. 告警通知: 多级告警、智能通知

6.2 架构优势

  1. 实时监控: 10秒间隔的实时硬盘数据采集
  2. 智能告警: 基于阈值的智能告警机制
  3. 自动优化: 自动化的硬盘空间优化
  4. 健康预测: 基于历史数据的故障预测

6.3 最佳实践

  1. 监控策略: 设置合理的硬盘监控阈值
  2. 优化策略: 根据空间使用情况执行针对性优化
  3. 健康检查: 定期检查硬盘健康状态
  4. 预防措施: 提前预防硬盘故障和空间不足

通过以上架构设计,可以构建完善的硬盘运维监控系统,实现硬盘资源的有效管理和性能优化。