Node性能如何进行监控以及优化?

devtools/2024/11/15 8:33:16/

在这里插入图片描述

一、 是什么

Node作为一门服务端语言,性能方面尤为重要,其衡量指标一般有如下:

  • CPU
  • 内存
  • I/O
  • 网络

CPU

主要分成了两部分:

  • CPU负载:在某个时间段内,占用以及等待CPU的进程总数
  • CPU使用率:CPU时间占用状况,等于 1 - 空闲CPU时间(idle time) / CPU总时间

这两个指标都是用来评估系统当前CPU的繁忙程度的量化指标

Node应用一般不会消耗很多的CPU,如果CPU占用率高,则表明应用存在很多同步操作,导致异步任务回调被阻塞

内存指标

内存是一个非常容易量化的指标。 内存占用率是评判一个系统的内存瓶颈的常见指标。 对于Node来说,内部内存堆栈的使用状态也是一个可以量化的指标

// /app/lib/memory.js
const os = require('os');
// 获取当前Node内存堆栈情况
const { rss, heapUsed, heapTotal } = process.memoryUsage();
// 获取系统空闲内存
const sysFree = os.freemem();
// 获取系统总内存
const sysTotal = os.totalmem();module.exports = {memory: () => {return {sys: 1 - sysFree / sysTotal,  // 系统内存占用率heap: heapUsed / headTotal,   // Node堆内存占用率node: rss / sysTotal,         // Node占用系统内存的比例}}
}
  • rss:表示node进程占用的内存总量。
  • heapTotal:表示堆内存的总量。
  • heapUsed:实际堆内存的使用量。
  • external :外部程序的内存使用量,包含Node核心的C++程序的内存使用量

在Node中,一个进程的最大内存容量为1.5GB。因此我们需要减少内存泄露

磁盘 I/O

硬盘的IO 开销是非常昂贵的,硬盘 IO 花费的 CPU 时钟周期是内存的 164000 倍

内存 IO比磁盘IO 快非常多,所以使用内存缓存数据是有效的优化方法。常用的工具如 redis、memcached等

并不是所有数据都需要缓存,访问频率高,生成代价比较高的才考虑是否缓存,也就是说影响你性能瓶颈的考虑去缓存,并且而且缓存还有缓存雪崩、缓存穿透等问题要解决

二、如何监控

关于性能方面的监控,一般情况都需要借助工具来实现

这里采用Easy-Monitor 2.0,其是轻量级的 Node.js 项目内核性能监控 + 分析工具,在默认模式下,只需要在项目入口文件 require 一次,无需改动任何业务代码即可开启内核级别的性能监控分析

使用方法如下:

在你的项目入口文件中按照如下方式引入,当然请传入你的项目名称:

const easyMonitor = require('easy-monitor');
easyMonitor('你的项目名称');

打开你的浏览器,访问 http://localhost:12333 ,即可看到进程界面

关于定制化开发、通用配置项以及如何动态更新配置项详见官方文档

三、如何优化

关于Node的性能优化的方式有:

  • 使用最新版本Node.js
  • 正确使用流 Stream
  • 代码层面优化
  • 内存管理优化

使用最新版本Node.js

每个版本的性能提升主要来自于两个方面:

  • V8 的版本更新
  • Node.js 内部代码的更新优化

正确使用流 Stream

在Node中,很多对象都实现了流,对于一个大文件可以通过流的形式发送,不需要将其完全读入内存

const http = require('http');
const fs = require('fs');// bad
http.createServer(function (req, res) {fs.readFile(__dirname + '/data.txt', function (err, data) {res.end(data);});
});// good
http.createServer(function (req, res) {const stream = fs.createReadStream(__dirname + '/data.txt');stream.pipe(res);
});

代码层面优化

合并查询,将多次查询合并一次,减少数据库的查询次数

// bad
for user_id in userIds let account = user_account.findOne(user_id)// good
const user_account_map = {}   // 注意这个对象将会消耗大量内存。
user_account.find(user_id in user_ids).forEach(account){user_account_map[account.user_id] =  account
}
for user_id in userIds var account = user_account_map[user_id]

内存管理优化

在 V8 中,主要将内存分为新生代和老生代两代:

  • 新生代:对象的存活时间较短。新生对象或只经过一次垃圾回收的对象
  • 老生代:对象存活时间较长。经历过一次或多次垃圾回收的对象

若新生代内存空间不够,直接分配到老生代

通过减少内存占用,可以提高服务器的性能。如果有内存泄露,也会导致大量的对象存储到老生代中,服务器性能会大大降低

如下面情况:

const buffer = fs.readFileSync(__dirname + '/source/index.htm');app.use(mount('/', async (ctx) => {ctx.status = 200;ctx.type = 'html';ctx.body = buffer;leak.push(fs.readFileSync(__dirname + '/source/index.htm'));})
);const leak = [];

leak的内存非常大,造成内存泄露,应当避免这样的操作,通过减少内存使用,是提高服务性能的手段之一

而节省内存最好的方式是使用池,其将频用、可复用对象存储起来,减少创建和销毁操作

例如有个图片请求接口,每次请求,都需要用到类。若每次都需要重新new这些类,并不是很合适,在大量请求时,频繁创建和销毁这些类,造成内存抖动

使用对象池的机制,对这种频繁需要创建和销毁的对象保存在一个对象池中。每次用到该对象时,就取对象池空闲的对象,并对它进行初始化操作,从而提高框架的性能

参考文献

  • https://segmentfault.com/a/1190000039327565
  • https://zhuanlan.zhihu.com/p/50055740
  • https://segmentfault.com/a/1190000010231628

如果对您有所帮助,欢迎您点个关注,我会定时更新技术文档,大家一起讨论学习,一起进步。

在这里插入图片描述


http://www.ppmy.cn/devtools/43881.html

相关文章

CV大作业29期-使用YOLOv10快速实现海上红外目标检测

使用YOLOv10做红外海洋目标识别 完整的视频教程将会于28号发布,敬请期待! Hi,大家好!这里是肆十二! 视频教程地址:【2024毕设系列】Anaconda和Pycharm如何使用_哔哩哔哩 过去几年的时间中,YOL…

【论文解读】Modular Blind Video Quality Assessment

原文下载地址:Modular Blind Video Quality Assessment 时间:2024 年 级别:arxiv 作者与机构:香港城市大学、香港中文大学(深圳)、字节跳动公司 git地址:https://github.com/winwinwenwen77/ModularBVQA 摘要 论文提出了一种模块化的盲视频质量评估(Blind Video Quali…

论文《Sensor and Sensor Fusion Technology in Autonomous Vehicles: A Review》详细解析

论文《Sensor and Sensor Fusion Technology in Autonomous Vehicles: A Review》详细解析 摘要 该论文对自动驾驶汽车中的传感器和传感器融合技术进行了全面回顾。它评估了各种传感器(如相机、LiDAR、雷达)的能力和技术性能,并讨论了多传感…

运维笔记:流编辑器sed命令用法解析

运维笔记 sed命令用法解析 - 文章信息 - Author: 李俊才 (jcLee95) Visit me at CSDN: https://jclee95.blog.csdn.netMy WebSite:http://thispage.tech/Email: 291148484163.com. Shenzhen ChinaAddress of this article:https://blog.csdn.net/qq_28550263/arti…

反转!Greenplum 还在,快去 Fork 源码

↑ 关注“少安事务所”公众号,欢迎⭐收藏,不错过精彩内容~ 今早被一条消息刷爆群聊,看到知名开源数仓 Greenplum 的源码仓“删库跑路”了。 要知道 GP 新东家 Broadcom 前几日才刚刚免费开放了 VMware Workstation PRO 17 和 VMware Fusion P…

开源DMS文档管理系统 Nuxeo Vs Alfresco对比及 API 使用概述

1. 文档管理系统是什么 文档管理系统(DMS:Document Management System)是一种软件系统,用于组织、存储、检索和管理电子文档和文件。这些文件可以是各种格式的电子文档,如文本文档、电子表格、图像、音频或视频文件等…

【JavaScript脚本宇宙】从jQuery到Popmotion:DOM操作和动画库

揭秘流行JavaScript库:从简单操作到复杂动画 前言 随着Web技术的发展,JavaScript库已成为开发人员日常工作中不可或缺的工具。本文将探讨六种流行的JavaScript库,涵盖其概述、主要特性、使用示例及使用场景等多个方面。 欢迎订阅专栏&#…

SpringBoot——基于Spring Task实现定时任务

目录 定时任务 项目总结 新建一个SpringBoot项目 pom.xml无需引入依赖 SpringTaskDemo SpringbootSpringtaskApplication启动类 定时任务 在日常的项目开发中,往往会涉及一些需要做到定时执行的代码,例如自动将超过24小时的未付款的订单改为取消状…