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 许可发布