golang实现网卡流量监控

获取当前时刻一分钟前的网卡流量排序

Go 复制代码
package main

import (
	"fmt"
	"github.com/mackerelio/go-osstat/network"
	"log"
	"net/http"
	"sort"
	"strconv"
	"time"
)

var arr []map[string]int
var arr2 []map[string]int

func get(w http.ResponseWriter, r *http.Request) {
	w.Header().Set("Content-Type", "text/plain;charset=UTF-8")
	//获取一分钟前数据
	var m = make(map[string]int)
	var m2 = make(map[string]int)
	for mp := range arr[0:len(arr)] {
		for key, value := range arr[mp] {
			m[key] += value
		}
	}
	for mp := range arr[0:len(arr2)] {
		for key, value := range arr2[mp] {
			m2[key] += value
		}
	}
	//按值排序
	keys := make([]string, 0, len(m))
	for key, _ := range m {
		keys = append(keys, key)
	}
	sort.Slice(keys, func(i, j int) bool {
		return m[keys[i]]+m2[keys[i]] > m[keys[j]]+m2[keys[j]]
	})
	for _, key := range keys {
		fmt.Fprintf(w, key+" 接收流量"+strconv.Itoa(m[key]/60)+"B/s"+" 发送流量"+strconv.Itoa(m2[key]/60)+
"B/S"+"\n")

	}
}

func fun() {
	var mp = make(map[string]int)
	var mp2 = make(map[string]int)
	for {
		beforeStats, _ := network.Get()
		// 等待1秒钟
		time.Sleep(1 * time.Second)
		afterStats, _ := network.Get()
		for _, item := range beforeStats {
			mp[item.Name] -= int(item.RxBytes)
			mp2[item.Name] -= int(item.TxBytes)
		}
		for _, item := range afterStats {
			mp[item.Name] += int(item.RxBytes)
			mp2[item.Name] += int(item.TxBytes)
			//fmt.Println(item.Name, item.RxBytes, mp[item.Name])
		}
		arr = append(arr, mp)
		arr2 = append(arr2, mp2)
		if len(arr) == 61 {
			arr = arr[1:61]
		}
		if len(arr2) == 61 {
			arr2 = arr2[1:61]
		}
	}

}
func main() {
	go fun()
	http.HandleFunc("/hello", get)
	if err := http.ListenAndServe(":8080", nil); err != nil {
		log.Fatal(err)
	}

}

获取指定网卡在某时刻前一分钟的网卡流量

Go 复制代码
package main

import (
	"fmt"
	"github.com/mackerelio/go-osstat/network"
	"log"
	"net/http"
	"strconv"
	"sync"
	"time"
)

type Record struct {
	arr         map[string]map[string]int
	arr2        map[string]map[string]int
	record_Time int
	mutex       sync.Mutex
}

var record = Record{
	arr:         make(map[string]map[string]int),
	arr2:        make(map[string]map[string]int),
	record_Time: 1000,
	mutex:       sync.Mutex{},
}

func get(w http.ResponseWriter, r *http.Request) {
	record.mutex.Lock()
	defer record.mutex.Unlock()
	w.Header().Set("Content-Type", "text/plain;charset=UTF-8")
	queryParams := r.URL.Query()
	queryTime := queryParams.Get("time")
	queryInterface := queryParams.Get("interface")

	//获取指定时间一秒前的流量
	in_Speed := record.arr[queryTime][queryInterface]
	out_Speed := record.arr2[queryTime][queryInterface]
	fmt.Fprintf(w, queryTime+"入口流量"+strconv.Itoa(in_Speed)+" B/s 出口流量"+strconv.Itoa(out_Speed)+"B/s\n")
}

func fun() {

	for {
		var mp = make(map[string]int)
		var mp2 = make(map[string]int)
		record.mutex.Lock()
		beforeStats, _ := network.Get()
		// 等待1秒钟
		time.Sleep(1 * time.Second)
		afterStats, _ := network.Get()
		//获取一秒内的流量
		for _, item := range beforeStats {
			mp[item.Name] -= int(item.RxBytes)
			mp2[item.Name] -= int(item.TxBytes)
		}
		for _, item := range afterStats {
			mp[item.Name] += int(item.RxBytes)
			mp2[item.Name] += int(item.TxBytes)
		}
		//记录每个时间点的流量
		now := time.Now().String()[0:19]
		record.arr[now] = mp
		record.arr2[now] = mp2
		fmt.Println(now)
		record.mutex.Unlock()
	}
}
func main() {

	go fun()
	http.HandleFunc("/get", get)
	if err := http.ListenAndServe(":8080", nil); err != nil {
		log.Fatal(err)
	}
}

改进版:定时任务

Go 复制代码
package main

import (
	"fmt"
	"github.com/mackerelio/go-osstat/network"
	"github.com/spf13/viper"
	"log"
	"net/http"
	"os"
	"strconv"
	"sync"
	"time"
)

type Record struct {
	arr      map[string]map[string]int
	arr2     map[string]map[string]int
	mutex    sync.Mutex
	stopChan chan bool
	ticker   time.Ticker
}

var record = Record{
	arr:      make(map[string]map[string]int),
	arr2:     make(map[string]map[string]int),
	mutex:    sync.Mutex{},
	stopChan: make(chan bool, 3),
	ticker:   *time.NewTicker(time.Second),
}

func get(w http.ResponseWriter, r *http.Request) {
	//加互斥锁
	record.mutex.Lock()
	defer record.mutex.Unlock()
	w.Header().Set("Content-Type", "text/plain;charset=UTF-8")
	queryParams := r.URL.Query()
	queryTime := queryParams.Get("time")
	queryInterface := queryParams.Get("name")

	//获取指定时间一秒前的流量
	in_Speed := record.arr[queryTime][queryInterface]
	out_Speed := record.arr2[queryTime][queryInterface]
	fmt.Fprintf(w, queryTime+"入口流量"+strconv.Itoa(in_Speed)+" B/s 出口流量"+strconv.Itoa(out_Speed)+"B/s\n")
}

func fun() {
	//读取配置
	viper.SetConfigName("config")
	viper.SetConfigType("yml")
	viper.AddConfigPath(".")
	viper.ReadInConfig()
	//日志输出位置
	f, err := os.OpenFile("log.log", os.O_CREATE|os.O_APPEND|os.O_RDWR, os.ModePerm)
	if err != nil {
		return
	}
	defer func() {
		f.Close()
	}()
	log.SetOutput(f)
	beforeStats, _ := network.Get()
	for {
		//非阻塞通道读取
		select {
		case <-record.stopChan:
			log.Println("停止记录网卡流量")
			return
		case <-record.ticker.C:
			var mp = make(map[string]int)
			var mp2 = make(map[string]int)
			//互斥锁
			record.mutex.Lock()

			afterStats, _ := network.Get()
			for _, item := range beforeStats {
				mp[item.Name] -= int(item.RxBytes)
				mp2[item.Name] -= int(item.TxBytes)
			}
			for _, item := range afterStats {
				mp[item.Name] += int(item.RxBytes)
				mp2[item.Name] += int(item.TxBytes)
			}
			beforeStats = afterStats

			now := time.Now().String()[0:19]
			//超出后删除最久的元素
			if len(record.arr) > viper.GetInt("record.time") {
				lastTime, _ := time.Parse("2006-01-02 15:04:05", now)
				last := lastTime.Add(-time.Second * time.Duration(viper.GetInt("record.time"))).String()[0:19]
				delete(record.arr, last)
				log.Println("删除时间点:" + last)
			}
			record.arr[now] = mp
			record.arr2[now] = mp2
			log.Println("已记录时间点:" + now + "入口流量:" + strconv.Itoa(mp["en0"]) + "出口流量:" + strconv.Itoa(mp2["en0"]))
			record.mutex.Unlock()
		}
	}
}
func main() {

	//多线程
	go fun()
	http.HandleFunc("/get", get)
	//开启服务器
	if err := http.ListenAndServe(viper.GetString("server.port"), nil); err != nil {
		log.Fatal(err)
	}
}

客户端测试代码

Go 复制代码
package main_test

import (
	"fmt"
	"github.com/spf13/viper"
	"io"
	"net/http"
	"net/url"
	"testing"
)

func Test(t *testing.T) {
	//配置日志
	viper.SetConfigName("config")
	viper.SetConfigType("yml")
	viper.AddConfigPath(".")
	viper.ReadInConfig()
	//拼接url
	targetUrl := "http://" +
		viper.GetString("server.host") +
		viper.GetString("server.port") + "/get"
	u, _ := url.ParseRequestURI(targetUrl)
	data := url.Values{}
	data.Set("name", viper.GetString("test.name"))
	data.Set("time", viper.GetString("test.time")[0:19])
	u.RawQuery = data.Encode()

	req, _ := http.NewRequest("GET", u.String(), nil)
	//设置user-agent
	req.Header.Set("User-Agent", "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/126.0.0.0 Safari/537.36")
	client := &http.Client{}
	resp, _ := client.Do(req)
	defer resp.Body.Close()
	//获取返回结果
	body, _ := io.ReadAll(resp.Body)
	fmt.Println(string(body))
}

config.yml

Go 复制代码
server:
  port:
    :8080
  host:
    localhost
record:
  time:
    100
test:
  name:
    en0
  time:
    2024-07-04 10:17:51
相关推荐
Envyᥫᩣ13 分钟前
C#语言:从入门到精通
开发语言·c#
童先生34 分钟前
Go 项目中实现类似 Java Shiro 的权限控制中间件?
开发语言·go
lulu_gh_yu35 分钟前
数据结构之排序补充
c语言·开发语言·数据结构·c++·学习·算法·排序算法
Re.不晚1 小时前
Java入门15——抽象类
java·开发语言·学习·算法·intellij-idea
老秦包你会1 小时前
Qt第三课 ----------容器类控件
开发语言·qt
凤枭香1 小时前
Python OpenCV 傅里叶变换
开发语言·图像处理·python·opencv
ULTRA??1 小时前
C加加中的结构化绑定(解包,折叠展开)
开发语言·c++
远望清一色1 小时前
基于MATLAB的实现垃圾分类Matlab源码
开发语言·matlab
confiself2 小时前
大模型系列——LLAMA-O1 复刻代码解读
java·开发语言
XiaoLeisj2 小时前
【JavaEE初阶 — 多线程】Thread类的方法&线程生命周期
java·开发语言·java-ee