当前位置: 首页 > news >正文

流量监控前端不显示问题

现象描述

前端界面显示上下行速率有问题,明明有流量,有时候是0有时候有数字。

通过接口定位到以下代码:

.h文件

#ifndef __TRAN_MONITOR__ #define __TRANS_MONITOR__ #include "hv/HttpServer.h" int NetSpeedMonitor_Init(const std::string &usbname); hv::Json UpDownloadGet(); #endif

Cpp文件:

#include <iostream> #include <stdio.h> #include <fstream> #include <thread> #include <chrono> #include <sys/stat.h> #include "Comport/TransMonitor.h" #include "hv/hlog.h" #include "hv/HttpServer.h" using namespace std; string upload_speed = "0 bytes/s"; // ❗❗❗❗❗❗❗❗❗❗后台线程不停写,HTTP线程不停读,没有mutex,没有atomic,没有内存屏障 string download_speed = "0 bytes/s"; // ❗❗❗❗❗❗❗❗❗❗导致:读到旧值,空字符串,读到一半的内容 static bool directoryExists(const string& path) { struct stat info; return stat(path.c_str(), &info) == 0 && S_ISDIR(info.st_mode); } static void readNetworkStatistics(const string &usbname) { const string basePath = "/sys/class/net/" + usbname + "/statistics/"; uint64_t prevRxBytes = 0, prevTxBytes = 0; while(true) { if (directoryExists(basePath)) { ifstream rxFile(basePath + "rx_bytes"); ifstream txFile(basePath + "tx_bytes"); uint64_t rxBytes = 0, txBytes = 0; char upspeed[32]; char downspeed[32]; if (rxFile >> rxBytes && txFile >> txBytes) { uint64_t rxDiff = rxBytes - prevRxBytes; // ❗❗❗❗❗❗❗计算的不是速率,只是差值❗❗❗❗❗❗❗❗❗❗ uint64_t txDiff = txBytes - prevTxBytes; //❗❗❗❗❗❗❗第一次diff极大,之后立刻归零❗❗❗❗❗❗❗ string rxUnit = "bytes/s", txUnit = "bytes/s"; double rxValue = rxDiff, txValue = txDiff; if (rxDiff > 1024) { // ❗❗❗❗❗❗❗❗❗❗1.两个 if 都会进l,前面的 KB 计算被后面的 MB 覆盖,逻辑可读性极差,不工程化 rxValue = static_cast<double>(rxDiff) / 1024; rxUnit = "KB/s"; } if (txDiff > 1024) { txValue = static_cast<double>(txDiff) / 1024; txUnit = "KB/s"; } if (rxDiff > 1024 * 1024) { // 2 rxValue = static_cast<double>(rxDiff) / (1024 * 1024); rxUnit = "MB/s"; } if (txDiff > 1024 * 1024) { txValue = static_cast<double>(txDiff) / (1024 * 1024); txUnit = "MB/s"; } if(txValue < 0) txValue = 0; if(rxValue < 0) rxValue = 0; sprintf(upspeed, "%.2f %s", txValue, txUnit.c_str()); sprintf(downspeed, "%.2f %s", rxValue, rxUnit.c_str()); upload_speed = upspeed; download_speed = downspeed; prevRxBytes = rxBytes; prevTxBytes = txBytes; } else { hloge("Read error at network transfer speed"); } rxFile.close(); txFile.close(); } else { sleep(5); } sleep(1); // ❗❗❗❗❗❗❗❗❗❗Linux sleep(1):≥1 秒 } } int NetSpeedMonitor_Init(const std::string &usbname) { thread networkThread(readNetworkStatistics, usbname); networkThread.detach(); return 0; } hv::Json UpDownloadGet() { hv::Json j; j["upstream"] = upload_speed; // ❗❗❗❗❗❗❗❗❗❗后端不建议返回字符串速率 j["downstream"] = download_speed; return j; }

看代码后问题显而易见:

只有在以下条件同时满足时,才会看到非 0:

  • 网卡此刻刚好有流量

  • 线程刚好按近似 1 秒跑

  • HTTP 线程刚好没读到写一半的 string

在demo里能跑,但是在生产环境必出问题。

解决问题

#include <iostream> #include <stdio.h> #include <fstream> #include <thread> #include <chrono> #include <sys/stat.h> #include "Comport/TransMonitor.h" #include "hv/hlog.h" #include "hv/HttpServer.h" #include <atomic> using namespace std; static std::atomic<uint64_t> g_rx_bps{0}; static std::atomic<uint64_t> g_tx_bps{0}; static void readNetworkStatistics(const string& ifname) { const string base = "/sys/class/net/" + ifname + "/statistics/"; uint64_t prevRx = 0, prevTx = 0; auto prevTime = chrono::steady_clock::now(); while (true) { ifstream rx(base + "rx_bytes"); ifstream tx(base + "tx_bytes"); uint64_t rxBytes = 0, txBytes = 0; if (!(rx >> rxBytes && tx >> txBytes)) { sleep(1); continue; } auto now = chrono::steady_clock::now(); double seconds = chrono::duration_cast<chrono::milliseconds>(now - prevTime).count() / 1000.0; if (prevRx != 0 && seconds > 0.2) { g_rx_bps = (rxBytes - prevRx) / seconds; g_tx_bps = (txBytes - prevTx) / seconds; } prevRx = rxBytes; prevTx = txBytes; prevTime = now; sleep(1); } } int NetSpeedMonitor_Init(const std::string &usbname) { thread networkThread(readNetworkStatistics, usbname); networkThread.detach(); return 0; } static std::string formatSpeed(uint64_t bps) { char buf[32]; if (bps < 1024) { snprintf(buf, sizeof(buf), "%lu B/s", bps); } else if (bps < 1024 * 1024) { snprintf(buf, sizeof(buf), "%.2f KB/s", bps / 1024.0); } else { snprintf(buf, sizeof(buf), "%.2f MB/s", bps / (1024.0 * 1024.0)); } return std::string(buf); } hv::Json UpDownloadGet() { uint64_t tx = g_tx_bps.load(); uint64_t rx = g_rx_bps.load(); hv::Json j; j["upstream"] = formatSpeed(tx); j["downstream"] = formatSpeed(rx); return j; }

1.atomic<uint64_t>存速率,避免了 string 竞争,HTTP线程读安全,后台线程安全

static std::atomic<uint64_t> g_rx_bps{0}; static std::atomic<uint64_t> g_tx_bps{0};

2.steady_clock+ 时间差算速率,不依赖sleep(1)精度,线程调度抖动不会把速率压成 0

double seconds = chrono::duration_cast<chrono::milliseconds>(now - prevTime).count() / 1000.0;

3.第一次采样不算速率,避免第一次巨大 diff,避免刚启动速率乱跳

if (prevRx != 0 && seconds > 0.2) {
http://www.jsqmd.com/news/99940/

相关文章:

  • 2025纸盘机设备全景名录:纸盘机、纸杯机、制杯机及全伺服纸杯机厂家全涵盖 - 品牌2026
  • 因为研究平台arm,RK3588交叉编译误把我笔记本X86平台的/x86_64-linux-gnu文件删除,导致联想拯救者笔记本中的ubuntu系统损坏
  • 星巴克、库迪等大牌点餐如何对接api接口?
  • 弹论:为投资者打造稳定投资之路
  • 利用Proxifier、Burp Suite和亮数据高效抓包
  • 【LLM基础教程】语言模型基础
  • YOLO-v5论文的10个核心创新点解析
  • ComfyUI入门与插件使用全指南
  • C语言:枚举体
  • 小程序管理后台项目
  • 【LLM基础教程】统计语言模型N-gram
  • Nigx配置
  • 【赵渝强老师】OceanBase租户的资源管理
  • gpt-oss-20b RESTful API设计与集成指南
  • 教育场景适用吗?LobeChat作为教学辅助工具的潜力
  • 【玩转全栈】----Django根本设置和介绍
  • 2025/12/16英语打卡
  • GPT-SoVITS音色相似度优化技巧:提升克隆真实感
  • 项目实践11—全球证件智能识别系统(切换为PostgreSQL数据库)
  • PaddlePaddle语音识别套件实践:集成github镜像提升模块加载效率
  • 2025 年纸碗成型设备实力厂家推荐 (12 月更新):纸杯机、制杯机、全伺服纸杯机、纸碗机、杯盖机等全品类制造商盘点 - 品牌2026
  • Java集合操作(List、Set、Map)
  • MiniCPM-V2.5微调中的CUDA依赖问题解决
  • LobeChat能否支持图表生成?数据可视化回答呈现
  • 2025 托福培训机构优选攻略:从选课逻辑到高分案例全解析 - 品牌测评鉴赏家
  • Windows下Python安装失败?换用清华源重试TensorFlow安装
  • DeepSeek-OCR本地部署:CUDA升级与vLLM配置
  • 2025年托福培训机构怎么选?这5家口碑好的机构帮你高效提分 - 品牌测评鉴赏家
  • Qwen3-32B大模型调用与鉴权指南
  • FPGA 和 IC 岗位前景、薪资对比