登录
注册
开源
企业版
高校版
搜索
帮助中心
使用条款
关于我们
开源
企业版
高校版
私有云
模力方舟
AI 队友
登录
注册
Gitee 2025 年度开源项目评选中
代码拉取完成,页面将自动刷新
捐赠
捐赠前请先登录
取消
前往登录
扫描微信二维码支付
取消
支付完成
支付提示
将跳转至支付宝完成支付
确定
取消
Watch
不关注
关注所有动态
仅关注版本发行动态
关注但不提醒动态
3
Star
45
Fork
21
DreamCoders
/
CoderGuide
代码
Issues
1169
Pull Requests
0
Wiki
统计
流水线
服务
JavaDoc
PHPDoc
质量分析
Jenkins for Gitee
腾讯云托管
腾讯云 Serverless
悬镜安全
阿里云 SAE
Codeblitz
SBOM
我知道了,不再自动展开
更新失败,请稍后重试!
移除标识
内容风险标识
本任务被
标识为内容中包含有代码安全 Bug 、隐私泄露等敏感信息,仓库外成员不可访问
Node性能如何进行监控以及优化?
待办的
#IAG9KP
陌生人
拥有者
创建于
2024-07-29 16:04
<h3>一、 是什么</h3><p><code>Node</code>作为一门服务端语言,性能方面尤为重要,其衡量指标一般有如下:</p><ul><li>CPU</li><li>内存</li><li>I/O</li><li>网络</li></ul><h4>CPU</h4><p>主要分成了两部分:</p><ul><li>CPU负载:在某个时间段内,占用以及等待CPU的进程总数</li><li>CPU使用率:CPU时间占用状况,等于 1 - 空闲CPU时间(idle time) / CPU总时间</li></ul><p>这两个指标都是用来评估系统当前CPU的繁忙程度的量化指标</p><p><code>Node</code>应用一般不会消耗很多的<code>CPU</code>,如果<code>CPU</code>占用率高,则表明应用存在很多同步操作,导致异步任务回调被阻塞</p><h4>内存指标</h4><p>内存是一个非常容易量化的指标。 内存占用率是评判一个系统的内存瓶颈的常见指标。 对于Node来说,内部内存堆栈的使用状态也是一个可以量化的指标</p><pre><code class="language-js">// /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占用系统内存的比例 } } }</code></pre><ul><li>rss:表示node进程占用的内存总量。</li><li>heapTotal:表示堆内存的总量。</li><li>heapUsed:实际堆内存的使用量。</li><li>external :外部程序的内存使用量,包含Node核心的C++程序的内存使用量</li></ul><p>在<code>Node</code>中,一个进程的最大内存容量为1.5GB。因此我们需要减少内存泄露</p><h4>磁盘 I/O</h4><p>硬盘的<code>IO</code> 开销是非常昂贵的,硬盘 IO 花费的 CPU 时钟周期是内存的 164000 倍</p><p>内存 <code>IO</code>比磁盘<code>IO</code> 快非常多,所以使用内存缓存数据是有效的优化方法。常用的工具如 <code>redis</code>、<code>memcached</code>等</p><p>并不是所有数据都需要缓存,访问频率高,生成代价比较高的才考虑是否缓存,也就是说影响你性能瓶颈的考虑去缓存,并且而且缓存还有缓存雪崩、缓存穿透等问题要解决</p><h3>二、如何监控</h3><p>关于性能方面的监控,一般情况都需要借助工具来实现</p><p>这里采用<code>Easy-Monitor 2.0</code>,其是轻量级的 <code>Node.js</code> 项目内核性能监控 + 分析工具,在默认模式下,只需要在项目入口文件 <code>require</code> 一次,无需改动任何业务代码即可开启内核级别的性能监控分析</p><p>使用方法如下:</p><p>在你的项目入口文件中按照如下方式引入,当然请传入你的项目名称:</p><pre><code class="language-js">const easyMonitor = require('easy-monitor'); easyMonitor('你的项目名称');</code></pre><p>打开你的浏览器,访问 <code>http://localhost:12333</code> ,即可看到进程界面</p><p>关于定制化开发、通用配置项以及如何动态更新配置项详见官方文档</p><h3>三、如何优化</h3><p>关于<code>Node</code>的性能优化的方式有:</p><ul><li>使用最新版本Node.js</li><li>正确使用流 Stream</li><li>代码层面优化</li><li>内存管理优化</li></ul><h3>使用最新版本Node.js</h3><p>每个版本的性能提升主要来自于两个方面:</p><ul><li>V8 的版本更新</li><li>Node.js 内部代码的更新优化</li></ul><h4>正确使用流 Stream</h4><p>在<code>Node</code>中,很多对象都实现了流,对于一个大文件可以通过流的形式发送,不需要将其完全读入内存</p><pre><code class="language-js">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); });</code></pre><h4>代码层面优化</h4><p>合并查询,将多次查询合并一次,减少数据库的查询次数</p><pre><code class="language-js">// 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]</code></pre><h4>内存管理优化</h4><p>在 V8 中,主要将内存分为新生代和老生代两代:</p><ul><li>新生代:对象的存活时间较短。新生对象或只经过一次垃圾回收的对象</li><li>老生代:对象存活时间较长。经历过一次或多次垃圾回收的对象</li></ul><p>若新生代内存空间不够,直接分配到老生代</p><p>通过减少内存占用,可以提高服务器的性能。如果有内存泄露,也会导致大量的对象存储到老生代中,服务器性能会大大降低</p><p>如下面情况:</p><pre><code class="language-js">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 = [];</code></pre><p><code>leak</code>的内存非常大,造成内存泄露,应当避免这样的操作,通过减少内存使用,是提高服务性能的手段之一</p><p>而节省内存最好的方式是使用池,其将频用、可复用对象存储起来,减少创建和销毁操作</p><p>例如有个图片请求接口,每次请求,都需要用到类。若每次都需要重新new这些类,并不是很合适,在大量请求时,频繁创建和销毁这些类,造成内存抖动</p><p>使用对象池的机制,对这种频繁需要创建和销毁的对象保存在一个对象池中。每次用到该对象时,就取对象池空闲的对象,并对它进行初始化操作,从而提高框架的性能</p>
<h3>一、 是什么</h3><p><code>Node</code>作为一门服务端语言,性能方面尤为重要,其衡量指标一般有如下:</p><ul><li>CPU</li><li>内存</li><li>I/O</li><li>网络</li></ul><h4>CPU</h4><p>主要分成了两部分:</p><ul><li>CPU负载:在某个时间段内,占用以及等待CPU的进程总数</li><li>CPU使用率:CPU时间占用状况,等于 1 - 空闲CPU时间(idle time) / CPU总时间</li></ul><p>这两个指标都是用来评估系统当前CPU的繁忙程度的量化指标</p><p><code>Node</code>应用一般不会消耗很多的<code>CPU</code>,如果<code>CPU</code>占用率高,则表明应用存在很多同步操作,导致异步任务回调被阻塞</p><h4>内存指标</h4><p>内存是一个非常容易量化的指标。 内存占用率是评判一个系统的内存瓶颈的常见指标。 对于Node来说,内部内存堆栈的使用状态也是一个可以量化的指标</p><pre><code class="language-js">// /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占用系统内存的比例 } } }</code></pre><ul><li>rss:表示node进程占用的内存总量。</li><li>heapTotal:表示堆内存的总量。</li><li>heapUsed:实际堆内存的使用量。</li><li>external :外部程序的内存使用量,包含Node核心的C++程序的内存使用量</li></ul><p>在<code>Node</code>中,一个进程的最大内存容量为1.5GB。因此我们需要减少内存泄露</p><h4>磁盘 I/O</h4><p>硬盘的<code>IO</code> 开销是非常昂贵的,硬盘 IO 花费的 CPU 时钟周期是内存的 164000 倍</p><p>内存 <code>IO</code>比磁盘<code>IO</code> 快非常多,所以使用内存缓存数据是有效的优化方法。常用的工具如 <code>redis</code>、<code>memcached</code>等</p><p>并不是所有数据都需要缓存,访问频率高,生成代价比较高的才考虑是否缓存,也就是说影响你性能瓶颈的考虑去缓存,并且而且缓存还有缓存雪崩、缓存穿透等问题要解决</p><h3>二、如何监控</h3><p>关于性能方面的监控,一般情况都需要借助工具来实现</p><p>这里采用<code>Easy-Monitor 2.0</code>,其是轻量级的 <code>Node.js</code> 项目内核性能监控 + 分析工具,在默认模式下,只需要在项目入口文件 <code>require</code> 一次,无需改动任何业务代码即可开启内核级别的性能监控分析</p><p>使用方法如下:</p><p>在你的项目入口文件中按照如下方式引入,当然请传入你的项目名称:</p><pre><code class="language-js">const easyMonitor = require('easy-monitor'); easyMonitor('你的项目名称');</code></pre><p>打开你的浏览器,访问 <code>http://localhost:12333</code> ,即可看到进程界面</p><p>关于定制化开发、通用配置项以及如何动态更新配置项详见官方文档</p><h3>三、如何优化</h3><p>关于<code>Node</code>的性能优化的方式有:</p><ul><li>使用最新版本Node.js</li><li>正确使用流 Stream</li><li>代码层面优化</li><li>内存管理优化</li></ul><h3>使用最新版本Node.js</h3><p>每个版本的性能提升主要来自于两个方面:</p><ul><li>V8 的版本更新</li><li>Node.js 内部代码的更新优化</li></ul><h4>正确使用流 Stream</h4><p>在<code>Node</code>中,很多对象都实现了流,对于一个大文件可以通过流的形式发送,不需要将其完全读入内存</p><pre><code class="language-js">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); });</code></pre><h4>代码层面优化</h4><p>合并查询,将多次查询合并一次,减少数据库的查询次数</p><pre><code class="language-js">// 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]</code></pre><h4>内存管理优化</h4><p>在 V8 中,主要将内存分为新生代和老生代两代:</p><ul><li>新生代:对象的存活时间较短。新生对象或只经过一次垃圾回收的对象</li><li>老生代:对象存活时间较长。经历过一次或多次垃圾回收的对象</li></ul><p>若新生代内存空间不够,直接分配到老生代</p><p>通过减少内存占用,可以提高服务器的性能。如果有内存泄露,也会导致大量的对象存储到老生代中,服务器性能会大大降低</p><p>如下面情况:</p><pre><code class="language-js">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 = [];</code></pre><p><code>leak</code>的内存非常大,造成内存泄露,应当避免这样的操作,通过减少内存使用,是提高服务性能的手段之一</p><p>而节省内存最好的方式是使用池,其将频用、可复用对象存储起来,减少创建和销毁操作</p><p>例如有个图片请求接口,每次请求,都需要用到类。若每次都需要重新new这些类,并不是很合适,在大量请求时,频繁创建和销毁这些类,造成内存抖动</p><p>使用对象池的机制,对这种频繁需要创建和销毁的对象保存在一个对象池中。每次用到该对象时,就取对象池空闲的对象,并对它进行初始化操作,从而提高框架的性能</p>
评论 (
0
)
登录
后才可以发表评论
状态
待办的
待办的
进行中
已完成
已关闭
负责人
未设置
标签
Node
未设置
标签管理
里程碑
未关联里程碑
未关联里程碑
Pull Requests
未关联
未关联
关联的 Pull Requests 被合并后可能会关闭此 issue
分支
未关联
未关联
master
开始日期   -   截止日期
-
置顶选项
不置顶
置顶等级:高
置顶等级:中
置顶等级:低
优先级
不指定
严重
主要
次要
不重要
参与者(1)
1
https://gitee.com/DreamCoders/CoderGuide.git
git@gitee.com:DreamCoders/CoderGuide.git
DreamCoders
CoderGuide
CoderGuide
点此查找更多帮助
搜索帮助
Git 命令在线学习
如何在 Gitee 导入 GitHub 仓库
Git 仓库基础操作
企业版和社区版功能对比
SSH 公钥设置
如何处理代码冲突
仓库体积过大,如何减小?
如何找回被删除的仓库数据
Gitee 产品配额说明
GitHub仓库快速导入Gitee及同步更新
什么是 Release(发行版)
将 PHP 项目自动发布到 packagist.org
评论
仓库举报
回到顶部
登录提示
该操作需登录 Gitee 帐号,请先登录后再操作。
立即登录
没有帐号,去注册