We read every piece of feedback, and take your input very seriously.
To see all available qualifiers, see our documentation.
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
目前许多业务开始往前端进行迁移,BFF(backends for frontends)的概念很多团队已开始逐渐尝试。让后端专注于提供统一的数据模型,将业务逻辑迁移到基于 Node 的 BFF 层中,让前端提供 API 接口,节省前后端联调成本,促使后端提供的 RPC 或者 HTTP 接口更加通用,减少修改后端工程,加快开发的效率。
但在 BFF 架构中,非常依赖 Node 端的稳定性,一旦 Node 端发生错误导致阻塞,造成很严重的后果,所以 Node 端的性能监控越来越有必要。
可以结合一些传统平台比如 sentry、 zabbix 可以帮助构建稳定的前端实时监控部署环境。
// http://nodejs.cn/api/os.html const os = require("os") os.tmpdir() // 返回操作系统的默认临时文件夹 os.endianness() // 返回 CPU 的字节序,可能的是 "BE" 或 "LE" os.hostname() // 返回操作系统的主机名 os.type() // 返回操作系统名 os.platform() // 返回编译时的操作系统名 os.arch() // 返回操作系统 CPU 架构,可能的值有 "x64"、"arm" 和 "ia32" os.release() // 返回操作系统的发行版本 os.uptime() // 返回操作系统运行的时间,以秒为单位 os.loadavg() // 返回一个包含 1、5、15 分钟平均负载的数组, os.loadavg()可以获取系统的CPU使用率 os.totalmem() // 返回系统内存总量,单位为字节,RAM os.freemem() // 返回操作系统空闲内存量,单位是字节 os.cpus() // 返回一个对象数组,包含所安装的每个 CPU/内核的信息 os.networkInterfaces() // 获得网络接口列表
一个 CPU,多个内核,CPU 内核有两个概念: CPU核心数 NumberOfCores CPU线程数 NumberOfLogicalProcessors CPU 内核常会被分成两个线程是一种超线程技术,就是串代码,操作系统会认为一个线程也是一个内核,有点欺骗操作系统的感觉
一个 CPU,多个内核,CPU 内核有两个概念:
CPU 内核常会被分成两个线程是一种超线程技术,就是串代码,操作系统会认为一个线程也是一个内核,有点欺骗操作系统的感觉
返回V8堆空间,就是组成 V8 堆的片段的统计信息。通过 V8的 GetHeapSpaceStatistics 函数获得的堆空间的顺序或者堆空间的可用信息都不能保证可以作为可靠的统计信息,因为但 V8 的版本发生改变时它们也可能改变。
详见:node v8 模块
详见
如果要查看 V8 的 JavaScript 字节码,可以使用在命令行参数中添加 --print-bytecode 运行 D8 或Node.js(8.3 或更高版本)来打印。对于 Chrome,请从命令行启动 Chrome,使用 --js-flags="--print-bytecode",请参考 Run Chromium with flags。
在 Node.js 环境里提供了 process.memoryUsage 方法用来查看当前进程内存使用情况,单位为字节
process.memoryUsage
rss(resident set size)
RAM是随机存储器(俗称:内存),ROM是只读存储器(俗称:硬盘)
heapTotal:堆中总共申请到的内存量。
heapTotal
heapUsed:堆中目前用到的内存量,判断内存泄漏我们主要以这个字段为准。
heapUsed
external:V8 引擎内部的 C++ 对象占用的内存。
external
arrayBuffers :指分配给 ArrayBuffer 和 SharedArrayBuffer 的内存,包括所有的 Node.js Buffer。
arrayBuffers
ArrayBuffer
SharedArrayBuffer
Buffer
// 调整内存限制大小 node --max-nex-space-size=1024 app.js // 单位为KB node --max-old-space-size=2000 app.js // 单位为MB process.cpuUsage() // 查看 CPU 使用情况
// 调整内存限制大小
node --max-nex-space-size=1024 app.js // 单位为KB node --max-old-space-size=2000 app.js // 单位为MB
process.cpuUsage() // 查看 CPU 使用情况
Node 优势适用于处理高并发、 I/O密集的场景,不适用于 CPU 密集的场景。我们了解服务性能要分两方面看:一方面是 I/O 性能,一方面是 CPU 计算性能。而 Node 安身立命的就是 I/O 爆表,事件驱动的特性使得 Node 的 I/O 十分卓越。
Node.js 软肋之 CPU 密集型任务
CPU 密集型任务计算性能的确是 Node 的软肋,跟 Java/C# 自然是不能比,但是 web 开发大多数情况下要命的是 I/O,且 Node 的性能比 Java/C# 差,但并不比其他语言差比 Ruby/Python 还是快出很多倍,而且可以调用 C/C++ 模块来处理 CPU 密集型任务。总而言之 Node 在 I/O 有其卓越的方面,CPU 密集型任务是 Node 的软肋但不致命。
CPU 密集: 涉及大量的逻辑计算,如图形计算、压缩、解压、加密、解密等 I/O 密集: 文件操作,网络操作,数据库操作等
服务器的性能瓶颈通常为以下几个:
CPU
内存
磁盘
I/O
响应时间RT(Response Time)
吞吐量(Throughput)
每秒查询率 QPS(Query Per Second)
每秒事务处理率 TPS (Transactions Per Second)
并发用户数
tips 知识:在 Linux 服务器上可以使用 top 命令常用的性能分析工具,能够实时显示系统中各个进程的资源占用状况,类似于 Windows 的任务管理器。top是一个动态显示过程,即可以通过用户按键来不断刷新当前状态。
不同场景下 Node 性能考虑指标,可能不尽兴相同。如 Node用于前端 SSR,CPU和网络为主要的性能瓶颈指标;如使用 Node 来进行数据持久化相关密集运算,I/O、磁盘、CPU占用负载率会很高。
目前来看,很少团队会用 Node 作为业务数据的支撑(涉及到CPU 密集型任务),而通常会用 Node 做 BFF 层,因此大多数场景下,CPU、内存以及网络可以说是 Node 的主要性能瓶颈。
CPU 使用率与CPU 负载,这两个从一定程度上都可以反映一台机器的繁忙程度。
CPU 使用率是运行的程序占用的 CPU 资源,表示机器在某个时间点的运行程序的情况。使用率越高,说明机器在这个时间上运行了很多程序,反之较少。使用率的高低与 CPU 强弱有直接关系。
CPU利用率(CPU utilization),量化CPU时间占用状况,我们一般表示为:CPU利用率 = 1 - 空闲CPU时间(idle time) / CPU总的执行时间, 或 CPU利用率 = CPU执行非系统空闲进程的时间 / CPU总的执行时间。
const os = require('os'); const sleep = ms => new Promise(resolve => setTimeout(resolve, ms)); class OSUtils { constructor() { this.cpuUsageMSDefault = 1000; // CPU 利用率默认时间段 } /** * 获取某时间段 CPU 利用率 * @param { Number } Options.ms [时间段,默认是 1000ms,即 1 秒钟] * @param { Boolean } Options.percentage [true(以百分比结果返回)|false] * @returns { Promise } */ async getCPUUsage(options={}) { const that = this; let { cpuUsageMS, percentage } = options; cpuUsageMS = cpuUsageMS || that.cpuUsageMSDefault; const t1 = that._getCPUInfo(); // t1 时间点 CPU 信息 await sleep(cpuUsageMS); const t2 = that._getCPUInfo(); // t2 时间点 CPU 信息 const idle = t2.idle - t1.idle; const total = t2.total - t1.total; let usage = 1 - idle / total; if (percentage) usage = (usage * 100.0).toFixed(2) + "%"; return usage; } /** * 获取 CPU 瞬时时间信息 * @returns { Object } CPU 信息 * user <number> CPU 在用户模式下花费的毫秒数。 * nice <number> CPU 在良好模式下花费的毫秒数。 * sys <number> CPU 在系统模式下花费的毫秒数。 * idle <number> CPU 在空闲模式下花费的毫秒数。 * irq <number> CPU 在中断请求模式下花费的毫秒数。 */ _getCPUInfo() { const cpus = os.cpus(); let user = 0, nice = 0, sys = 0, idle = 0, irq = 0, total = 0; for (let cpu in cpus) { const times = cpus[cpu].times; user += times.user; nice += times.nice; sys += times.sys; idle += times.idle; irq += times.irq; } total += user + nice + sys + idle + irq; return { user, sys, idle, total, } } } const cpuUsage = await osUtils.getCPUUsage({ percentage: true }); console.log('CPU 利用率:', cpuUsage) // CPU 利用率: 13.72%
CPU的负载(loadavg)很好理解,指某段时间内占用 CPU 时间的进程和等待 CPU 时间的进程数为平均负载(load average),这里等待CPU 时间的进程是指等待被唤醒的进程,不包括处于wait状态进程。
const os = require('os'); // CPU线程数 const length = os.cpus().length; // 单核CPU的平均负载,返回一个包含 1、5、15 分钟平均负载的数组 os.loadavg().map(load => load / length);
内存是一个非常容易量化的指标。 内存占用率是评判一个系统的内存瓶颈的常见指标。 对于Node来说,内部内存堆栈的使用状态也是一个可以量化的指标。
const os = require('os'); // 查看当前 Node 进程内存使用情况 const { rss, heapUsed, heapTotal } = process.memoryUsage(); // 获取系统空闲内存 const systemFree = os.freemem(); // 获取系统总内存 const systemTotal = os.totalmem(); module.exports = { memory: () => { return { system: 1 - systemFree / systemTotal, // 系统内存占用率 heap: heapUsed / headTotal, // 当前 Node 进程内存占用率 node: rss / systemTotal, // 当前 Node 进程内存占用系统内存的比例 } } }
Node 无法直接获取系统磁盘信息,这里我们可以借助 child_process 子进程,执行 Linux 查看磁盘空间 df 命令来进行获取。
child_process
df
const exec = require('child_process').exec function diskMetrics () { return new Promise((resolve, reject)=> { exec('df -k', (error, stdout, stderr) => { let total = 0; let used = 0; let free = 0; if (error) { reject({}); return; } let lines = stdout.split("\n"); let str_disk_info = lines[1].replace( /[\s\n\r]+/g,' '); let disk_info = str_disk_info.split(' '); total = Math.ceil((disk_info[1] * 1024)/ Math.pow(1024,2)); used = Math.ceil(disk_info[2] * 1024 / Math.pow(1024,2)) ; free = Math.ceil(disk_info[3] * 1024 / Math.pow(1024,2)) ; resolve({ total, free, used, }) }) }) }
IO实际上是计算机用语,也写作I/O,指输入/输出(Input/Output)。硬盘IO就是指对字节的读取速度,即硬盘的读写能力。服务器硬盘IO的性能也是服务器稳定性需要考虑的问题,IO瓶颈往往是我们可能会忽略的地方(我们常会看top、free、netstat等等,但经常会忽略IO的负载情况)。
// 每隔1s查询一次 共查询10次 iostat 1 10 // 查看磁盘 iostat -d 1 10
可以通过 autocannon、wrk、loadtest、siege 等工具获取相关压测指标, 如:
{ "transactions": 0, "availability": 0.00, "elapsed_time": 0.01, "data_transferred": 0.00, "response_time": 0.00, "transaction_rate": 0.00, "throughput": 0.00, "concurrency": 0.00, "successful_transactions": 0, "failed_transactions": 50, "longest_transaction": 0.00, "shortest_transaction": 0.00 }
日志对于 Web 开发的重要性毋庸置疑,对应用的运行状态监控、问题排查等都有非常重要的意义。比较推荐的方案有:
重点看下 egg-logger 框架内置了强大的企业级日志支持,包含主要特性:
对于前端 Node.js 应用来说,根据项目的框架和部署架构,可选择不同的日志切割方案,例如: 基于 pm2 部署的 Node.js 应用,可采用 pm2-logrotate 实现日志切割。 基于 Egg.js 框架的 Node.js 应用,可采用 egg-logrotator 实现日志切割。
对于前端 Node.js 应用来说,根据项目的框架和部署架构,可选择不同的日志切割方案,例如:
pm2-logrotate
egg-logrotator
节点应用程序指标仪表板(appmetrics-dash)提供了一个非常易于使用的基于 Web 的仪表板,以显示正在运行的 Node.js 应用程序的性能指标。
appmetrics-dash 依赖 appmetrics
QPS、TPS、并发用户数、吞吐量关系
Node.js 应用故障排查手册
NodeJS中被忽略的内存
深入 Nodejs 源码探究 CPU 信息的获取与利用率计算
appmetrics-dash
v8-gc-log-parser
os-utils
sentry 跨端实时监控平台
Prometheus 监控系统
App Metrics
Grafana度量分析与可视化套件
Easy-Monitor 2.0
Node.js环境性能监控
BFF 知识
node相比传统服务端技术栈差在哪里?
node.js应用高并发高性能本质
使用 Node.js 的优势和劣势都有哪些?
SSR VS CSR ,一次讲个通透
容器监控实践—K8S常用指标分析
Memeye 是一个轻量级的 NodeJS 进程监控工具
node-usage 跨端获取内存信息
prometheus-book
如何处理 Node.js 中出现的未捕获异常?
Node 报警设置
了解 V8 的字节码
NodeJS运维: 从 0 开始 Prometheus + Grafana 业务性能指标监控
The text was updated successfully, but these errors were encountered:
No branches or pull requests
目前许多业务开始往前端进行迁移,BFF(backends for frontends)的概念很多团队已开始逐渐尝试。让后端专注于提供统一的数据模型,将业务逻辑迁移到基于 Node 的 BFF 层中,让前端提供 API 接口,节省前后端联调成本,促使后端提供的 RPC 或者 HTTP 接口更加通用,减少修改后端工程,加快开发的效率。
但在 BFF 架构中,非常依赖 Node 端的稳定性,一旦 Node 端发生错误导致阻塞,造成很严重的后果,所以 Node 端的性能监控越来越有必要。
Node 系统操作
OS 模块获取系统信息
Node V8 模块
返回V8堆空间,就是组成 V8 堆的片段的统计信息。通过 V8的 GetHeapSpaceStatistics 函数获得的堆空间的顺序或者堆空间的可用信息都不能保证可以作为可靠的统计信息,因为但 V8 的版本发生改变时它们也可能改变。
详见
:node v8 模块进程内存查看
在 Node.js 环境里提供了
process.memoryUsage
方法用来查看当前进程内存使用情况,单位为字节rss(resident set size)
:RAM 中保存的进程占用的内存部分,包括代码本身、栈、堆。heapTotal
:堆中总共申请到的内存量。heapUsed
:堆中目前用到的内存量,判断内存泄漏我们主要以这个字段为准。external
:V8 引擎内部的 C++ 对象占用的内存。arrayBuffers
:指分配给ArrayBuffer
和SharedArrayBuffer
的内存,包括所有的 Node.jsBuffer
。Node 性能
Node 优势适用于处理高并发、 I/O密集的场景,不适用于 CPU 密集的场景。我们了解服务性能要分两方面看:一方面是 I/O 性能,一方面是 CPU 计算性能。而 Node 安身立命的就是 I/O 爆表,事件驱动的特性使得 Node 的 I/O 十分卓越。
Node.js 软肋之 CPU 密集型任务
CPU 密集型任务计算性能的确是 Node 的软肋,跟 Java/C# 自然是不能比,但是 web 开发大多数情况下要命的是 I/O,且 Node 的性能比 Java/C# 差,但并不比其他语言差比 Ruby/Python 还是快出很多倍,而且可以调用 C/C++ 模块来处理 CPU 密集型任务。总而言之 Node 在 I/O 有其卓越的方面,CPU 密集型任务是 Node 的软肋但不致命。
性能指标
服务器的性能瓶颈通常为以下几个:
CPU
内存
磁盘
I/O
响应时间RT(Response Time)
吞吐量(Throughput)
每秒查询率 QPS(Query Per Second)
每秒事务处理率 TPS (Transactions Per Second)
并发用户数
不同场景下 Node 性能考虑指标,可能不尽兴相同。如 Node用于前端 SSR,CPU和网络为主要的性能瓶颈指标;如使用 Node 来进行数据持久化相关密集运算,I/O、磁盘、CPU占用负载率会很高。
目前来看,很少团队会用 Node 作为业务数据的支撑(涉及到CPU 密集型任务),而通常会用 Node 做 BFF 层,因此大多数场景下,CPU、内存以及网络可以说是 Node 的主要性能瓶颈。
CPU 指标
CPU 使用率与CPU 负载,这两个从一定程度上都可以反映一台机器的繁忙程度。
CPU 使用率是运行的程序占用的 CPU 资源,表示机器在某个时间点的运行程序的情况。使用率越高,说明机器在这个时间上运行了很多程序,反之较少。使用率的高低与 CPU 强弱有直接关系。
CPU利用率(CPU utilization),量化CPU时间占用状况,我们一般表示为:CPU利用率 = 1 - 空闲CPU时间(idle time) / CPU总的执行时间, 或 CPU利用率 = CPU执行非系统空闲进程的时间 / CPU总的执行时间。
CPU的负载(loadavg)很好理解,指某段时间内占用 CPU 时间的进程和等待 CPU 时间的进程数为平均负载(load average),这里等待CPU 时间的进程是指等待被唤醒的进程,不包括处于wait状态进程。
内存指标
内存是一个非常容易量化的指标。 内存占用率是评判一个系统的内存瓶颈的常见指标。 对于Node来说,内部内存堆栈的使用状态也是一个可以量化的指标。
磁盘指标
Node 无法直接获取系统磁盘信息,这里我们可以借助
child_process
子进程,执行 Linux 查看磁盘空间df
命令来进行获取。I/O 指标
IO实际上是计算机用语,也写作I/O,指输入/输出(Input/Output)。硬盘IO就是指对字节的读取速度,即硬盘的读写能力。服务器硬盘IO的性能也是服务器稳定性需要考虑的问题,IO瓶颈往往是我们可能会忽略的地方(我们常会看top、free、netstat等等,但经常会忽略IO的负载情况)。
其他指标
可以通过 autocannon、wrk、loadtest、siege 等工具获取相关压测指标, 如:
日志监控
日志对于 Web 开发的重要性毋庸置疑,对应用的运行状态监控、问题排查等都有非常重要的意义。比较推荐的方案有:
重点看下 egg-logger 框架内置了强大的企业级日志支持,包含主要特性:
推荐工具
appmetrics-dash 工具
节点应用程序指标仪表板(appmetrics-dash)提供了一个非常易于使用的基于 Web 的仪表板,以显示正在运行的 Node.js 应用程序的性能指标。
Other Resource
QPS、TPS、并发用户数、吞吐量关系
Node.js 应用故障排查手册
NodeJS中被忽略的内存
深入 Nodejs 源码探究 CPU 信息的获取与利用率计算
appmetrics-dash
v8-gc-log-parser
os-utils
sentry 跨端实时监控平台
Prometheus 监控系统
App Metrics
Grafana度量分析与可视化套件
Easy-Monitor 2.0
Node.js环境性能监控
BFF 知识
node相比传统服务端技术栈差在哪里?
node.js应用高并发高性能本质
使用 Node.js 的优势和劣势都有哪些?
SSR VS CSR ,一次讲个通透
容器监控实践—K8S常用指标分析
Memeye 是一个轻量级的 NodeJS 进程监控工具
node-usage 跨端获取内存信息
prometheus-book
如何处理 Node.js 中出现的未捕获异常?
Node 报警设置
了解 V8 的字节码
NodeJS运维: 从 0 开始 Prometheus + Grafana 业务性能指标监控
The text was updated successfully, but these errors were encountered: