打开APP
userphoto
未登录

开通VIP,畅享免费电子书等14项超值服

开通VIP
Node.js 应用高 CPU 占用率的分析方法
userphoto

2022.09.02 四川

关注

我们在本地运行 Node.js 应用,使用 --inspect 标志启动应用程序,再次执行负载测试,在 Chrome 浏览器中打开 chrome://inspect:

单击应用下方的 inspect 按钮,然后开始 CPU 占用率分析:

等待一段时间后,就能看到 CPU profile 的结果:

如何采集生产系统上的 Node.js 应用性能数据呢?

在大多数情况下,如果性能问题只能在生产系统重现,那么这种问题分析起来确实很棘手,因为我们需要相同的环境配置、相同的数据库、缓存等数据。 性能问题可能只针对某些类别的用户,因为他们有特定的数据。

在生产环境开启调试模式?这不是一个好的选择,因为在调试模式下 Node.js 进程会消耗更多资源,而且不安全。

但是有一个更好的方法,使用检查器模块 https://nodejs.org/api/inspector.html 按需获取配置文件。 它是一个 Node.js 内置模块,开发人员不必安装任何额外的依赖项,但建议使用 inspector-api .

它是一个带有 Promise 支持的简单包装器。 让我们创建一个记录 CPU 配置文件的端点。

下面是为 NestJS 创建一个示例,对于其他框架,它看起来非常相似:

代码如下:

import { Controller, Post } from '@nestjs/common'import { promisify } from 'util'import Inspector from 'inspector-api'const profileRecordTime = 10000@Controller('/profile')export class ProfileController {
  @Post('/cpu')
  async cpu() {
 // don't wait till recording is finished setImmediate(async () => {
   // cpu profile will be saved in temp dir   const inspector = new Inspector({ storage: { type: 'fs' } })
   // enabling and starting profiling   await inspector.profiler.enable()
   await inspector.profiler.start()
   // wait for 10 seconds and stop   await promisify(setTimeout)(profileRecordTime)
   await inspector.profiler.stop()
   console.log('CPU profile has been written')
   await inspector.profiler.disable()
 })

 return true
  }}

所有代码都用 setImmediate 包裹,因为我们不需要等到录制结束。 让我们用 curl 测试一下:

curl -X POST http://127.0.0.1/profile/cpu

10 秒之后,我们在 temp 文件夹得到了 CPU profile 的采集结果:

如果不想将此功能添加为 HTTP 端点,则可以将它们包装在进程信号处理程序中,如下所示:

import { promisify } from 'util'import Inspector from 'inspector-api'const profileRecordTime = 10000process.on('SIGUSR1', async () => {
  const inspector = new Inspector({ storage: { type: 'fs' } })
  await inspector.profiler.enable()
  await inspector.profiler.start()
  await promisify(setTimeout)(profileRecordTime)
  await inspector.profiler.stop()
  console.log('CPU profile has been written')
  await inspector.profiler.disable()})process.on('SIGUSR2', async () => {
  const inspector = new Inspector({ storage: { type: 'fs' } })
  await inspector.heap.enable()
  await inspector.heap.startSampling()
  await promisify(setTimeout)(profileRecordTime)
  await inspector.heap.stopSampling()
  console.log('CPU profile has been written')
  await inspector.heap.disable()})

然后使用 kill 命令发送信号:

  • kill -USR1 ${pid} // for CPU

  • kill -USR2 ${pid} // for Heap

本站仅提供存储服务,所有内容均由用户发布,如发现有害或侵权内容,请点击举报
打开APP,阅读全文并永久保存 查看更多类似文章
猜你喜欢
类似文章
只使用async 不使用await,在微信小程序中使用async/await
NodeJs-promise和async_await语法
写 Node.js 代码,从学会调试开始
Node.js 调试 GC 以及内存暴涨的分析
centos下使用puppeteer进行网页截图截图常见问题:
微软开源Node.js浏览器自动化库——playwright
更多类似文章 >>
生活服务
热点新闻
分享 收藏 导长图 关注 下载文章
绑定账号成功
后续可登录账号畅享VIP特权!
如果VIP功能使用有故障,
可点击这里联系客服!

联系客服