一、 是什么

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 快非常多,所以使用内存缓存数据是有效的优化方法。常用的工具如 redismemcached

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

二、如何监控

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

这里采用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这些类,并不是很合适,在大量请求时,频繁创建和销毁这些类,造成内存抖动

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

Node性能如何进行监控以及优化?的更多相关文章

  1. 性能测试之mysql监控、优化

    我们在做性能测试的目的是什么,就是要测出一个系统的瓶颈在哪里,到底是哪里影响了我们系统的性能,找到问题,然后解决它.当然一个系统由很多东西一起组合到一起,应用程序.数据库.服务器.中中间件等等很多东西 ...

  2. Linux指令--性能监控和优化命令相关指令

    原文出处:http://www.cnblogs.com/peida/archive/2012/12/05/2803591.html.感谢作者无私分享 性能监控和优化命令相关指令有:top,free,v ...

  3. 性能调优之Java系统级性能监控及优化

    性能调优之Java系统级性能监控及优化   对于性能调优而言,通常我们需要经过以下三个步骤:1,性能监控:2,性能剖析:3,性能调优 性能调优:通过分析影响Application性能问题根源,进行优化 ...

  4. 通过 Informix 系统表监控和优化数据库

    Informix 数据库系统字典表简介 Informix 数据库服务器运行时的状态信息是数据库管理员 DBA 进行系统监控和优化的必需信息来源.Informix 的状态信息在内部以 2 种方式存在,如 ...

  5. 腾讯技术分享:Android版手机QQ的缓存监控与优化实践

    本文内容整理自公众号腾讯Bugly,感谢原作者的分享. 1.问题背景 对于Android应用来说,内存向来是比较重要的性能指标.内存占用过高,会影响应用的流畅度,甚至引发OOM,非常影响用户体验.因此 ...

  6. alinode与node性能测试方法与分析

    需求和技术指标整理 node服务在引入node性能监控过程中,需要使用alinode,为了对alinode与官方node各项性能指标的差异有进一步的认识,现开展以下调研.测试. 原理性分析 alino ...

  7. Unity 协程运行时的监控和优化

    我是快乐的搬运工: http://gulu-dev.com/post/perf_assist/2016-12-20-unity-coroutine-optimizing#toc_0 --------- ...

  8. 【jmeter】基于InfluxDB&Grafana的JMeter实时性能测试数据的监控和展示

    本文主要讲述如何利用JMeter监听器Backend Listener,配合使用InfluxDB+Grafana展示实时性能测试数据 关于JMeter实时测试数据 JMeter从2.11版本开始,命令 ...

  9. Node.js 数据库实时监控库 node-dbmon

    node-dbmon 是一个 Node.js 数据库实时监控库,如果你希望在数据库表数据更改后,或者是文件修改后能更新 GUI,那么这个库正好适合你. https://github.com/strap ...

随机推荐

  1. 英伟达TRTTorch

    英伟达TRTTorch PyTorch JIT的提前(AOT)编译Ahead of Time (AOT) compiling for PyTorch JIT TRTorch是PyTorch / Tor ...

  2. 激光雷达lidar与点云数据

    激光雷达lidar与点云数据 DEM是分布和显示数字地形的首个广泛使用的机制. 点云是在空间中随机放置的3D点的集合.传感器发出能量脉冲并乘以其返回行程(TWTT,双向行程时间).知道了传感器的位置以 ...

  3. CUDA 内存统一分析

    CUDA 内存统一分析 关于CUDA 编程的基本知识,如何编写一个简单的程序,在内存中分配两个可供 GPU 访问的数字数组,然后将它们加在 GPU 上. 本文介绍内存统一,这使得分配和访问系统中任何处 ...

  4. CountDownLatch原理详解

    介绍 当你看到这篇文章的时候需要先了解AQS的原理,因为本文不涉及到AQS内部原理的讲解. CountDownLatch是一种同步辅助,让我们多个线程执行任务时,需要等待线程执行完成后,才能执行下面的 ...

  5. kali2020.4中安装nessus 8.14.0

    1.下载软件包 官网下载地址:https://www.tenable.com/downloads/nessus 2.安装nessus dpkg -i /root/Nessus-8.14.0-debia ...

  6. Django框架之路由层汇总

    一 Django中路由的作用 URL配置(URLconf)就像Django 所支撑网站的目录.它的本质是URL与要为该URL调用的视图函数之间的映射表:你就是以这种方式告诉Django,对于客户端发来 ...

  7. ThreadLocal源码阅读笔记

    功能描述 ThreadLocal解决了访问共享变量的阻塞问题,并且不需要像CAS操作一样牺牲CPU资源,它为每一个线程维护了一个变量副本,每个线程在访问ThrealLocal里面的变量时实际上访问的是 ...

  8. Redis-持久化策略

    redis是一个内存数据库,一旦服务器宕机,内存中的数据将全部丢失.所以,对 Redis 来说,实现数据的持久化,避免从后端数据库中进行恢复,是至关重要的. 目前,Redis 的持久化主要有两大机制, ...

  9. zookeeper使用教程

    Zookeeper 1.       Zookeeper概述 1.1 概述 Zookeeper是一个开源的分布式的,为分布式应用提供协调服务的Apache项目. 1.2 特点 1)Zookeeper: ...

  10. jquery动画(控制动画隐藏、显示时间轴)

    <!DOCTYPE html><html> <head>    <meta http-equiv="Content-type" conte ...