Skip to content

系统监控

CmdAdmin 提供完善的系统监控功能,包括服务器监控和 Redis 缓存监控。

服务器监控

实时监控服务器的运行状态,包括 CPU、内存、磁盘和 JVM。

监控指标

CPU 监控

指标说明
系统负载系统整体 CPU 使用率
用户使用率用户进程 CPU 使用率
系统使用率系统进程 CPU 使用率
平均负载1分钟/5分钟/15分钟平均负载

内存监控

指标说明
总内存服务器总内存
已用内存已使用的内存
剩余内存可用内存
使用率内存使用百分比

磁盘监控

指标说明
总空间磁盘总容量
已用空间已使用的空间
剩余空间可用空间
使用率磁盘使用百分比

JVM 监控

指标说明
JVM 名称Java 虚拟机名称
JVM 版本Java 版本信息
启动时间JVM 启动时间
运行时长JVM 已运行时间
堆内存堆内存使用情况
非堆内存非堆内存使用情况

API 接口

java
@RestController
@RequestMapping("/system/monitor")
public class ServerMonitorController {
    
    /**
     * 获取服务器基本信息
     */
    @GetMapping("/info")
    public Result<ServerInfo> getServerInfo() {
        ServerInfo info = new ServerInfo();
        info.setOsName(System.getProperty("os.name"));
        info.setOsVersion(System.getProperty("os.version"));
        info.setJavaVersion(System.getProperty("java.version"));
        info.setJvmName(System.getProperty("java.vm.name"));
        info.setJvmVersion(System.getProperty("java.vm.version"));
        info.setJvmStartTime(new Date(ManagementFactory.getRuntimeMXBean().getStartTime()));
        return Result.ok(info);
    }
    
    /**
     * 获取服务器负载信息
     */
    @GetMapping("/load")
    public Result<ServerLoad> getServerLoad() {
        ServerLoad load = new ServerLoad();
        
        // CPU 信息
        OperatingSystemMXBean osBean = ManagementFactory.getOperatingSystemMXBean();
        load.setCpuUsage(getCpuUsage());
        load.setCpuLoad(osBean.getSystemLoadAverage());
        
        // 内存信息
        MemoryMXBean memoryBean = ManagementFactory.getMemoryMXBean();
        MemoryUsage heapUsage = memoryBean.getHeapMemoryUsage();
        load.setJvmMemoryUsed(heapUsage.getUsed());
        load.setJvmMemoryMax(heapUsage.getMax());
        
        // 磁盘信息
        File root = new File("/");
        load.setDiskTotal(root.getTotalSpace());
        load.setDiskFree(root.getFreeSpace());
        
        return Result.ok(load);
    }
}

前端展示

vue
<template>
  <div class="monitor-container">
    <!-- CPU 监控卡片 -->
    <el-card class="monitor-card">
      <template #header>
        <span>CPU 监控</span>
      </template>
      <div class="cpu-info">
        <el-progress 
          :percentage="cpuUsage" 
          :color="cpuColor"
          type="dashboard"
        />
        <div class="detail">
          <p>系统负载:{{ systemLoad }}%</p>
          <p>用户负载:{{ userLoad }}%</p>
          <p>平均负载:{{ avgLoad }}</p>
        </div>
      </div>
    </el-card>
    
    <!-- 内存监控卡片 -->
    <el-card class="monitor-card">
      <template #header>
        <span>内存监控</span>
      </template>
      <div class="memory-info">
        <el-progress 
          :percentage="memoryUsage" 
          :color="memoryColor"
          type="dashboard"
        />
        <div class="detail">
          <p>总内存:{{ formatSize(memoryTotal) }}</p>
          <p>已用:{{ formatSize(memoryUsed) }}</p>
          <p>剩余:{{ formatSize(memoryFree) }}</p>
        </div>
      </div>
    </el-card>
    
    <!-- 磁盘监控卡片 -->
    <el-card class="monitor-card">
      <template #header>
        <span>磁盘监控</span>
      </template>
      <div class="disk-info">
        <el-progress 
          :percentage="diskUsage" 
          :color="diskColor"
          type="dashboard"
        />
        <div class="detail">
          <p>总空间:{{ formatSize(diskTotal) }}</p>
          <p>已用:{{ formatSize(diskUsed) }}</p>
          <p>剩余:{{ formatSize(diskFree) }}</p>
        </div>
      </div>
    </el-card>
    
    <!-- JVM 监控卡片 -->
    <el-card class="monitor-card">
      <template #header>
        <span>JVM 监控</span>
      </template>
      <div class="jvm-info">
        <p>JVM 名称:{{ jvmName }}</p>
        <p>JVM 版本:{{ jvmVersion }}</p>
        <p>启动时间:{{ jvmStartTime }}</p>
        <p>运行时长:{{ jvmUptime }}</p>
        <p>堆内存:{{ formatSize(jvmHeapUsed) }} / {{ formatSize(jvmHeapMax) }}</p>
      </div>
    </el-card>
  </div>
</template>

<script setup>
import { ref, onMounted, onUnmounted } from 'vue'
import { getServerInfo, getServerLoad } from '@/api/monitor'

const cpuUsage = ref(0)
const memoryUsage = ref(0)
const diskUsage = ref(0)

// 定时刷新数据
let timer = null

const fetchData = async () => {
  const { data } = await getServerLoad()
  cpuUsage.value = data.cpuUsage
  memoryUsage.value = data.memoryUsage
  diskUsage.value = data.diskUsage
}

onMounted(() => {
  fetchData()
  timer = setInterval(fetchData, 5000) // 每5秒刷新
})

onUnmounted(() => {
  clearInterval(timer)
})
</script>

Redis 缓存监控

监控 Redis 连接状态和缓存使用情况。

监控指标

指标说明
连接状态Redis 是否连接正常
版本信息Redis 服务器版本
运行模式单机/集群/哨兵模式
已用内存Redis 使用的内存
内存峰值内存使用峰值
Key 数量当前数据库 Key 数量
命中率缓存命中率
已连接客户端当前连接数

缓存管理

java
@RestController
@RequestMapping("/system/cache")
public class SysCacheController {
    
    @Autowired
    private RedisTemplate<String, Object> redisTemplate;
    
    /**
     * 获取缓存列表
     */
    @GetMapping("/list")
    public Result<List<CacheInfo>> list() {
        Properties info = redisTemplate.execute(
            connection -> connection.serverCommands().info()
        );
        
        List<CacheInfo> list = new ArrayList<>();
        // 解析 Redis info 信息...
        
        return Result.ok(list);
    }
    
    /**
     * 获取缓存详情
     */
    @GetMapping("/info")
    public Result<CacheDetail> info(@RequestParam String key) {
        CacheDetail detail = new CacheDetail();
        detail.setKey(key);
        detail.setType(redisTemplate.type(key).name());
        detail.setTtl(redisTemplate.getExpire(key));
        detail.setValue(redisTemplate.opsForValue().get(key));
        return Result.ok(detail);
    }
    
    /**
     * 删除缓存
     */
    @DeleteMapping("/delete")
    public Result<Void> delete(@RequestParam String key) {
        redisTemplate.delete(key);
        return Result.ok();
    }
    
    /**
     * 批量删除缓存
     */
    @DeleteMapping("/batchDelete")
    public Result<Void> batchDelete(@RequestBody List<String> keys) {
        redisTemplate.delete(keys);
        return Result.ok();
    }
    
    /**
     * 清空所有缓存
     */
    @DeleteMapping("/clear")
    public Result<Void> clear() {
        Set<String> keys = redisTemplate.keys("*");
        if (keys != null && !keys.isEmpty()) {
            redisTemplate.delete(keys);
        }
        return Result.ok();
    }
}

前端缓存管理界面

vue
<template>
  <div class="cache-container">
    <!-- 缓存统计 -->
    <el-row :gutter="20">
      <el-col :span="6">
        <el-statistic title="Key 数量" :value="cacheStats.keyCount" />
      </el-col>
      <el-col :span="6">
        <el-statistic title="已用内存" :value="formatSize(cacheStats.usedMemory)" />
      </el-col>
      <el-col :span="6">
        <el-statistic title="命中率" :value="cacheStats.hitRate" suffix="%" />
      </el-col>
      <el-col :span="6">
        <el-statistic title="连接数" :value="cacheStats.connectedClients" />
      </el-col>
    </el-row>
    
    <!-- 缓存列表 -->
    <el-table :data="cacheList" v-loading="loading">
      <el-table-column prop="key" label="Key" show-overflow-tooltip />
      <el-table-column prop="type" label="类型" width="100" />
      <el-table-column prop="ttl" label="过期时间" width="150">
        <template #default="{ row }">
          {{ row.ttl > 0 ? formatDuration(row.ttl) : '永不过期' }}
        </template>
      </el-table-column>
      <el-table-column prop="size" label="大小" width="100">
        <template #default="{ row }">
          {{ formatSize(row.size) }}
        </template>
      </el-table-column>
      <el-table-column label="操作" width="200" fixed="right">
        <template #default="{ row }">
          <el-button type="primary" link @click="viewDetail(row)">查看</el-button>
          <el-button type="danger" link @click="deleteCache(row)">删除</el-button>
        </template>
      </el-table-column>
    </el-table>
    
    <!-- 批量操作 -->
    <div class="batch-actions">
      <el-button type="danger" @click="clearAll">清空所有缓存</el-button>
    </div>
  </div>
</template>

在线用户监控

查看当前在线用户列表,支持强制下线。

java
@RestController
@RequestMapping("/system/online")
public class OnlineUserController {
    
    @Autowired
    private RedisTemplate<String, Object> redisTemplate;
    
    /**
     * 获取在线用户列表
     */
    @GetMapping("/list")
    public Result<List<OnlineUser>> list() {
        Set<String> keys = redisTemplate.keys("login_token:*");
        List<OnlineUser> list = new ArrayList<>();
        
        for (String key : keys) {
            LoginUser user = (LoginUser) redisTemplate.opsForValue().get(key);
            if (user != null) {
                OnlineUser online = new OnlineUser();
                online.setUserId(user.getUserId());
                online.setUsername(user.getUsername());
                online.setLoginTime(user.getLoginTime());
                online.setLoginIp(user.getLoginIp());
                online.setLoginLocation(user.getLoginLocation());
                online.setBrowser(user.getBrowser());
                online.setOs(user.getOs());
                list.add(online);
            }
        }
        
        return Result.ok(list);
    }
    
    /**
     * 强制下线
     */
    @DeleteMapping("/kickout/{token}")
    public Result<Void> kickout(@PathVariable String token) {
        redisTemplate.delete("login_token:" + token);
        return Result.ok();
    }
}

监控告警

可以配置告警规则,当指标超过阈值时发送通知:

java
@Component
public class MonitorAlertJob implements Job {
    
    @Autowired
    private ServerMonitorService monitorService;
    
    @Override
    public void execute(JobExecutionContext context) {
        ServerLoad load = monitorService.getServerLoad();
        
        // CPU 告警
        if (load.getCpuUsage() > 80) {
            sendAlert("CPU 使用率超过 80%: " + load.getCpuUsage() + "%");
        }
        
        // 内存告警
        if (load.getMemoryUsage() > 85) {
            sendAlert("内存使用率超过 85%: " + load.getMemoryUsage() + "%");
        }
        
        // 磁盘告警
        if (load.getDiskUsage() > 90) {
            sendAlert("磁盘使用率超过 90%: " + load.getDiskUsage() + "%");
        }
    }
    
    private void sendAlert(String message) {
        // 发送邮件/短信/钉钉通知...
    }
}

注意事项

  1. 性能影响:监控数据采集会消耗少量系统资源,建议合理设置采集频率
  2. 数据安全:缓存管理接口需要严格权限控制,防止误删重要数据
  3. 告警阈值:根据实际业务场景调整告警阈值
  4. 历史数据:考虑将监控历史数据持久化,便于趋势分析

基于 MIT 许可发布