golang实现网卡流量监控

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

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)
	}

}

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

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)
	}
}

改进版:定时任务

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)
	}
}

客户端测试代码

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

server:
  port:
    :8080
  host:
    localhost
record:
  time:
    100
test:
  name:
    en0
  time:
    2024-07-04 10:17:51

 

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mfbz.cn/a/770227.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

Redis 管道(Pipeline)是什么?有什么用?

目录 1. redis 客户端-服务端模型的不足之处 2. redis 管道是什么&#xff1f;有什么好处&#xff1f; 3. 管道的使用场景 4. 管道使用的注意事项 1. redis 客户端-服务端模型的不足之处 众所周知&#xff0c;redis 是一个客户端-服务端的模型设计&#xff0c;客户端向服务…

Zoom视颊会议软件使用

GPT-3.5 (OpenAI) Zoom是一款极受欢迎的视频会议软件。使用Zoom可以方便地进行视频会议、远程授课、在线研讨会等活动。以下是Zoom的使用步骤&#xff1a; 1. 下载Zoom客户端 可以在Zoom官网上下载对应平台的Zoom客户端。下载并完成安装后&#xff0c;双击打开客户端。 2. 创建…

大数据开发中如何计算用户留存及SQL示例

在大数据开发领域&#xff0c;用户留存是一个关键指标&#xff0c;它反映了产品吸引并保留用户的能力。 留存率的计算不仅有助于评估产品的健康状况&#xff0c;还能为产品优化和市场策略提供重要依据。 本文将详细介绍如何在大数据开发中计算用户留存&#xff0c;并附带具体…

大数据之路 读书笔记 Day2

大数据之路 读书笔记 Day2 日志采集——浏览器的页面采集 一、分类 #mermaid-svg-8c9sRexRDdSB9pWA {font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}#mermaid-svg-8c9sRexRDdSB9pWA .error-icon{fill:#552222;}#mermaid-svg-8c9…

【论文解读】CVPR2024:DUSt3R: Geometric 3D Vision Made Easy

论文“”https://openaccess.thecvf.com/content/CVPR2024/papers/Wang_DUSt3R_Geometric_3D_Vision_Made_Easy_CVPR_2024_paper.pdf 代码&#xff1a;GitHub - naver/dust3r: DUSt3R: Geometric 3D Vision Made Easy DUSt3R是一种旨在简化几何3D视觉任务的新框架。作者着重于…

002-关于Geogebra软件的介绍及与MatLab的区别

为什么要学Geogebra&#xff1f; 因为和MatLab的科学计算相比&#xff0c;GeoGebra重点突出教学展示&#xff0c;对于教师、学生人群来讲再合适不过了&#xff0c;尤其是可以融入到PPT里边呈现交互式动画&#xff0c;想想听众的表情&#xff01;这不就弥补了看到PPT播放数学公…

邮箱smtp发送邮件失败的原因?怎么做排查?

邮箱smtp发送邮件失败的解决方法&#xff1f;SMTP错误代码解析&#xff01; 在使用SMTP发送邮件时&#xff0c;我们时常会遇到各种问题&#xff0c;导致邮件发送失败。了解这些问题的根本原因可以帮助我们更好地解决它们。AoKSend将详细探讨邮箱SMTP发送邮件失败的几大原因&am…

在 WebGPU 与 Vulkan 之间做出正确的选择(Making the Right Choice between WebGPU vs Vulkan)

在 WebGPU 与 Vulkan 之间做出正确的选择&#xff08;Making the Right Choice between WebGPU vs Vulkan&#xff09; WebGPU 和 Vulkan 之间的主要区别WebGPU 是什么&#xff1f;它适合谁使用&#xff1f;Vulkan 是什么&#xff1f;它适合谁使用&#xff1f;WebGPU 和 Vulkan…

mac 上 Docker Desktop的免费开源的替代工具Colima

当谈到在macOS上运行容器时&#xff0c;Docker长期以来一直是首选。但是&#xff0c;必须解决使用适用于macOS的Docker Desktop时出现的一些限制&#xff0c;特别是对于大中型公司&#xff0c;最大的问题是需要购买许可证。另外&#xff0c;macOS 版Docker Desktop的性能问题也…

单调栈(左小大,右小大)

①寻找每个数左边第一个比它小的数 给定一个长度为 N 的整数数列&#xff0c;输出每个数左边第一个比它小的数&#xff0c;如果不存在则输出 −1。 输入样例&#xff1a; 3 4 2 7 5 输出样例&#xff1a; -1 3 -1 2 2 从左到右遍历&#xff0c;用单调递增&#xff08;栈底到栈顶…

c->c++(二):class

本文主要探讨C类的相关知识。 构造和析构函数 构造函数(可多个)&#xff1a;对象产生时调用初始化class属性、分配class内部需要的动态内存 析构函数&#xff08;一个&#xff09;&#xff1a;对对象消亡时调用回收分配动态内存 C提供默认构造和析构,…

行人检测技术:思通数科大模型在自动驾驶安全中的应用

在自动驾驶技术飞速发展的今天&#xff0c;行人检测已成为确保道路交通安全的关键技术之一。本文将探讨如何结合思通数科大模型和计算机视觉技术&#xff0c;实现在城市交通环境中对行人的高效检测&#xff0c;为自动驾驶车辆提供必要的行人安全保障。 引言 行人检测技术是利…

Dubbo内部通信流程

我当时在学习的过程中搭建过demo&#xff0c;具体流程就是&#xff0c;我先定义了一个api接口模块&#xff0c;还定义一个服务提供者模块&#xff0c;然后服务提供方实现该接口&#xff0c;定义该方法具体的实现impl类&#xff0c;服务提供方启动时&#xff0c;将要暴露的服务和…

【架构-20】死锁

什么是死锁&#xff1f; 死锁(Deadlock)是指两个或多个线程/进程在执行过程中,由于资源的互相占用和等待,而陷入一种互相等待的僵局,无法继续往下执行的情况。 产生死锁的四个必要条件: &#xff08;1&#xff09;互斥条件(Mutual Exclusion)&#xff1a;至少有一个资源是非共享…

跨阻放大器

#创作灵感# 最近涉及到微电流的监测项目&#xff0c;而里面的核心就是跨阻放大器&#xff0c;所以这里做一个简单的介绍&#xff0c;后续等项目完成了&#xff0c;再做一个实例的介绍。 #正文# 跨阻放大器&#xff08;Transimpedance Amplifier, TIA&#xff09;是一种将输入电…

Windows编程之多线程事件对象(Event Object)用法详解

目录 一、前言 二、基础用法 三、API详解 1.创建事件对象 2控制事件状态 3.等待事件对象&#xff1a; 四、实战案例 1.案例描述 2.代码设计 3.总设计代码 4.运行结果 一、前言 事件对象&#xff08;Event Object&#xff09;是我们在大型项目中&#xff0c;进行多线…

股价持续低迷,业绩颓势不减,冀光恒难救平安银行?

文&#xff5c;新熔财经 作者&#xff5c;宏一 周一一上班&#xff0c;就听到旁边的同事感慨今年股市行情很不错&#xff0c;尤其是银行股&#xff0c;上半年累计上涨了17.02%&#xff0c;是涨幅最大的板块。 听到这里&#xff0c;我美滋滋地打开自己的账户&#xff0c;结…

如何对低代码平台进行分类?

现在市面上的低代码平台就像雨后春笋一样冒出来&#xff0c;而且源源不绝&#xff0c;但总结下来&#xff0c;大致的也就以下三类。 一、 aPaaS多引擎类&#xff08;有很多成熟引擎、做好东西要一起用&#xff09; 这类产品包括&#xff1a;织信Informat&#xff08;国内&…

照明物联网:基于网关的智能照明云监控系统解决方案

智能照明系统就是利用物联网技术&#xff0c;将同一空间的照明、空调、新风、排风等系统共同接入物联网平台&#xff0c;实现了“设备互联、数据互通”的智慧物联能力。照明数据、环境监测数据通过网关上传云端&#xff0c;在云端进行统计分析并将结果通过各种终端共享&#xf…

MySQL—常用的数据类型

数据类型 整型 1.创建一个含有无符号/有符号整型的字段的表 CREATE TABLE L1(id tinyint unsigned #无符号 ) CREATE TABLE L2(id tinyint #默认为有符号 ) 数值型(bit) 2.数值型(bit)的使用 小数 3.数值型(小数)的基本使用 字符串 4.字符串的基本使用 #演示字符串类型…