系统资源实时监控
1.目的
实现web端显示服务器的资源使用情况
cpu使用率 内存使用率 上传下载速度 硬盘使用率 ip
浏览器显示效果,每过2秒显示当前资源情况:

Json数据:
{
"bootTime":"5天21时3分21秒", // 开机时间
"cpuInfo":{ // cpu信息
"cpuCount":8, //cpu核数
"usePercent":[ // 每个核的当前使用率
98.4375,
96.875,
100,
100,
95.38461538461539,
93.75,
95.3125,
93.75
],
"totalPercent":"96.69%", // cpu的总使用率
"mhz":"1.801GHz"//cpu的赫兹数
},
"memoryInfo":{ // 内存信息
"freeMemory":"241.21MB", // 空闲内存
"totalMemory":"7.89GB", // 总内存
"usedPercent":"97%"//内存使用率
},
"ip":"192.168.99.177",// 设备ip
"netIoInfo":{// 网络情况
"sentSpc":"481.18KB/S", // 发送速度
"recvSpc":"22.62MB/S"// 接收速度
}
}
2.工具选择
2.1 wmi_exporter
wmi_exporter是windows的资源的采集器,主要搭配prometheus + grafana 来实现系统运维,所以这一套搭配也是固定的prometheus + grafana + wmi_exporter。其显示的效果如下:

这是常用的监控windows资源的路线,优点是不用编码,使用工具部署即可。缺点是需要和prometheus + grafana搭配,如果是只想有一个简单的程序来获取当前系统的数据,具体的显示样式就可以自己随意控制的需求就看下面,如果grafana 就已经满足则使用该方案即可。
2.2 psutil
psutil在各个编程语言中都有实现,psutil = process and system utilities,它不仅可以通过一两行代码实现系统监控,还可以跨平台使用,支持Linux/UNIX/OSX/Windows等,是系统管理员和运维小伙伴不可或缺的必备模块。比如python中使用 pip install psutil 即可使用该模块。gopsutil则是Golang中对psutil的实现,我们也以此为例gopsutil来做介绍。
3.gopsutil
3.1 api使用示例
通过简单的api即可获得信息,以下用获取cpu信息为示例,
// GetCpuPercent cpu使用率
func GetCpuPercent() CpuInfo {
//cpu 核数
counts, _ := cpu.Counts(true)
log.Println("cpu核数:", counts)
percent, _ := cpu.Percent(time.Second, true)
log.Println("cpu各个核使用率:", percent)
var usePercent []string
total := 0.0
for _, value := range percent {
total += value
usePercentItem := util.Float642String(value)
usePercent = append(usePercent, usePercentItem)
}
// 总核数
totalPercent := len(percent) * 100
f := (total / float64(totalPercent)) * 100
e := util.Decimal(f)
strTotalPercent := util.Float642String(e) + "%"
log.Println("cpu总使用率:", strTotalPercent)
infoStats, _ := cpu.Info()
decimal := infoStats[0].Mhz / 1000
strMhz := util.Float642String(decimal) + "GHz"
log.Println("cpu赫兹: ", strMhz)
cpuInfo := CpuInfo{
CpuCount: counts,
UsePercent: usePercent,
TotalPercent: strTotalPercent,
Mhz: strMhz,
}
return cpuInfo
}
返回cpu信息:
{
"code": 200,
"message": "获取cpu信息",
"data": {
"cpuCount": 8,
"usePercent": [
"62.5",
"37.5",
"75",
"53.84615384615385",
"62.5",
"18.75",
"64.0625",
"46.875"
],
"totalPercent": "52.63%",
"mhz": "1.801GHz"
}
}
说明:
counts, _ := cpu.Counts(true) //获取cpu核数percent, _ := cpu.Percent(time.Second, true) // cpu各个核使用率infoStats, _ := cpu.Info()
decimal := infoStats[0].Mhz / 1000
log.Println("cpu赫兹: ", strMhz)其他内存 ip 也类似
3.2 下载、上传速度
// GetNetIO 网络下载速度
func GetNetIO() NetIoInfo {
counters, _ := net.IOCounters(false)
log.Println("发送数据大小:", util.FormatByteSize(int64(counters[0].BytesSent)))
log.Println("接收数据大小:", util.FormatByteSize(int64(counters[0].BytesRecv)))
time.Sleep(time.Second * 1)
newCounters, _ := net.IOCounters(false)
log.Println("发送数据大小:", util.FormatByteSize(int64(newCounters[0].BytesSent)))
log.Println("接收数据大小:", util.FormatByteSize(int64(newCounters[0].BytesRecv)))
spcSent := util.FormatByteSize(int64(newCounters[0].BytesSent - counters[0].BytesSent))
spcRecv := util.FormatByteSize(int64(newCounters[0].BytesRecv - counters[0].BytesRecv))
log.Println("1秒内上传的差值:", spcSent, "/S")
log.Println("1秒内下载的差值:", spcRecv, "/S")
spcSentStr := fmt.Sprintf("%s/S", spcSent)
spcRecvStr := fmt.Sprintf("%s/S", spcRecv)
netIoInfo := NetIoInfo{
SentSpc: spcSentStr,
RecvSpc: spcRecvStr,
}
return netIoInfo
}
说明:
BytesSent:= net.IOCounters(false).[0].BytesSent) 获取当前发送的字节数 -- 对应上传
BytesRecv:= net.IOCounters(false).[0].BytesRecv) 获取当前接收的字节数 -- 对应下载// 通过睡眠一秒
time.Sleep(time.Second * 1)
// 计算下一秒和上一秒的差值,即可得到上传、下载速度
newCounters[0].BytesSent - counters[0].BytesSent
newCounters[0].BytesRecv - counters[0].BytesRecv
3.3 主动推送数据
想在web端实时显示数据,我们选择websocket。大致思路是:当有一个ws客户端连接上来,就开始定时任务每2秒获取资源数据,广播给所有的ws客户端;当没有一个客户端连接时就停止定时任务。
3.3.1 定时任务
// SystemMonitorCron 定时获取信息资源
func SystemMonitorCron() {
// 有ws的任一连接启动定时获取任务,ws中0个连接则停止定时任务
c := rcron.New()
// 定时任务执行间隔时间
timeInterval := config.Config.Cron.TimeInterval
time := "@every " + timeInterval + "s"
log.Println("定时任务间隔是:", timeInterval, "s")
// 执行任务
c.AddFunc(time, func() {
fmt.Println("tick every " + timeInterval + " second")
// 获取资源信息
systemInfo := system.WsGetSystemInfo()
jsonData, _ := json.Marshal(systemInfo)
// 发送到所有ws连接
Manager.Broadcast <- jsonData
if len(Manager.Clients) == 0 {
// 停止定时任务
log.Println("ws没有任何连接,停止定时任务")
c.Stop()
}
})
c.Start()
}
使用定时包github.com/robfig/cron/v3
使用方法:
c := cron.New()
c.AddFunc("@every 1s", func() {
fmt.Println("tick every 1 second")
})
c.Start()控制台每隔1秒会打印:
tick every 1 second
tick every 1 second
tick every 1 second
tick every 1 second正如看见的AddFunc中指定定时器的间隔,传入执行任务的方法,调用c.Start()即可开始执行任务。
停止定时任务,只需在添加的方法中调用c.Stop()即可
3.3.2 WebSocket
使用到库github.com/gorilla/websocket,具体案例就不在这里赘述。
4. 总结
没有总结,简单的小工具使用。感兴趣的在公众号发送消息"资源监控",即可获取源码地址。
下次见。




