暂无图片
暂无图片
暂无图片
暂无图片
暂无图片

Web端系统资源实时监控

BugProvider 2021-08-01
1184

系统资源实时监控

1.目的

  1. 实现web端显示服务器的资源使用情况
    1. cpu使用率
    2. 内存使用率
    3. 上传下载速度
    4. 硬盘使用率
    5. 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。其显示的效果如下:

image-20210801145953786

这是常用的监控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. 总结

没有总结,简单的小工具使用。感兴趣的在公众号发送消息"资源监控",即可获取源码地址。


下次见。


文章转载自BugProvider,如果涉嫌侵权,请发送邮件至:contact@modb.pro进行举报,并提供相关证据,一经查实,墨天轮将立刻删除相关内容。

评论