对node工程进行压力测试与性能分析

在系统上线前,为了看下系统能承受多大的并发和并发下的负载情况,进行了一轮压测。在压测过程中,发现服务器的cpu飚的的非常高,而tps,接口耗时、服务可用等都是正常的,卧槽,这就奇了怪了,自己想了半天也没想出为啥,不得已求助了大佬,大佬说先查看 cpu processor  what?这是啥??虽然听不懂,但可以查嘛╭(╯^╰)╮,可还没等我查出来,大佬直接上手,一顿骚操作,便找出了原因~ 这着实让自己汗颜啊,内功远远不足啊,回来网上找了资料,恶补一把如何分析node工程中的性能问题。

在开发过程中,因为过于只关注了业务逻辑的实现,一些可能出现性能的点被忽略掉,而且这些点只能在量稍微大些的并发场景下才会出现,忘了在哪看到一句话 可能会出问题的点,便一定会出问题  性能问题进行分析必不可少。

样例项目

为了便于演示,写了个简单的小例子:

  1. // app.js

  2.   const crypto = require('crypto')

  3.   const Koa = require('koa')

  4.   const Router = require('koa-router');

  5.   const app = new Koa();

  6.   const router = new Router();

  7.   router.get('/crypto', async(ctx, next) => {

  8.       const salt = crypto.randomBytes(128).toString('base64')

  9.       const hash = crypto.pbkdf2Sync('crypto', salt, 10000, 64, 'sha512').toString('hex')

  10.       ctx.body = { hash: hash }

  11.       console.log(hash)

  12.       ctx.status = 200

  13.       next()

  14.   });

  15.   let reqNum = 0

  16.   router.get('/empty', async(ctx, next) => {

  17.       ctx.body = { hash: 'empty' }

  18.       reqNum++;

  19.       ctx.status = 200

  20.       next()

  21.   });

  22.   app.use(router.routes()).use(router.allowedMethods());

  23.   app.listen(3000, () => {

  24.       console.log("listen 3000")

  25.   })

基于koa2,有两个路由,一个/crypto,其中的业务逻辑是,使用crypto库对字符串加密;一个是 /empty,没有业务逻辑的接口,就是个空接口。

压力测试

压力测试工具市面上有很多种,就不一一列举了,在社区看到有人推荐 autocannon ,就对这个工具做个介绍,官方的简介是 fast HTTP/1.1 benchmarking tool written in Node.js ,使用node编写的压测工具,能比wrk生成更多负载。
install

npm i autocannon -g
  npm i autocannon --save


use

提供两种使用方式:
1. 命令行 autocannon -c 100 -d 5 -p 2 http://127.0.0.1:3000/test 简单快速。
2. api调用 autocannon(opts[, cb]) 便于编写脚本。

关键参数有这么几个:

-c/--connections NUM 并发连接的数量,默认10。

-p/--pipelining NUM 每个连接的流水线请求请求数。默认1。

-d/--duration SEC 执行的时间,单位秒。

-m/--method METHOD 请求类型 默认GET。

-b/--body BODY 请求报文体。

还有很多参数,大家可以查看官网文档。

这个库目前只能支持一个接口压测,我写了个脚本,可以支持批量压测和生成测试报告,具体代码见文末。

report

下图是对 /empty 接口压测 autocannon -c 100 -d 5 -p 1 http://127.0.0.1:3000/empty 结果如下:

可看到,每秒有100个链接,每个链接一个请求,持续5秒,一共产生 31k 次请求。

报告分三部分,第一行表示接口的延迟,第二行表示每秒的请求数(tps),第三行表示每秒返回的字节数。那么,延迟越低,tps越高,就表示接口性能越好,因为empty 是个空接口,所以它的tps=6221还不错,响应时间也很快,我们换成 /crypto 接口在试试。

立马看出差距了,这个接口tps只有77,接口耗时达到了1100ms,说明这个接口有很大的优化空间啊。

生成性能文件与分析

通过压测工具我们找到了有问题的接口,那接下来,就要对接口进行剖析了,可是光看接口代码,不好分析啊,毕竟没有说服力,我们就需要一份性能报告,用数据说话,下面介绍这个两个方法给大家。

V8 Profiler

V8 官方已经为大家考虑到这点了,提供了Profiler工具 使用方式也很快捷,步骤如下。以app.js为例)
 

生成报告

在启动命令中加上 --prof ,如 node --prof app.js ,在项目根目录会生成isolate-xxxxxxx-v8.log格式的文件,用来记录运行期间的调用栈和时间等信息,其中内容如下。(文件较大,就截取最顶端一小截)

  1. v8-version,6,1,534,47,0

  2.   shared-library,"C:\Program Files\nodejs\node.exe",0x7ff7505f0000,0x7ff751c0f000,0

  3.   shared-library,"C:\WINDOWS\SYSTEM32\ntdll.dll",0x7ff8718a0000,0x7ff871a61000,0

  4.   shared-library,"C:\WINDOWS\system32\KERNEL32.DLL",0x7ff870590000,0x7ff87063d000,0

  5.   shared-library,"C:\WINDOWS\system32\KERNELBASE.dll",0x7ff86e830000,0x7ff86ea18000,0

  6.   shared-library,"C:\WINDOWS\system32\WS2_32.dll",0x7ff86ee00000,0x7ff86ee6b000,0

分析报告
  对刚刚生成的log文件分析,还是使用官方提供的工具 node --prof-process isolate-xxxxxxxx-v8.log,生成结果如下。(去掉无用的部分)

  1. Statistical profiling result from isolate-00000209B99A60A0-v8.log, (17704 ticks, 8 unaccounted, 0 excluded).

  2.    [Shared libraries]:

  3.    ticks total nonlib name

  4.    13795 77.9% C:\WINDOWS\SYSTEM32\ntdll.dll

  5.    ...

  6.    [JavaScript]:

  7.    ticks total nonlib name

  8.    12 0.1% 11.3% Builtin: CallFunction_ReceiverIsAny

  9.    ...

  10.    [C++]:

  11.    ticks total nonlib name

  12.    [Summary]:

  13.    ticks total nonlib name

  14.    94 0.5% 88.7% JavaScript

  15.    0 0.0% 0.0% C++

  16.    8 0.0% 7.5% GC

  17.    17598 99.4% Shared libraries

  18.    8 0.0% Unaccounted

  19.    [C++ entry points]:

  20.    ticks cpp total name

  21.    [Bottom up (heavy) profile]:

  22.    Note: percentage shows a share of a particular caller in the total

  23.    amount of its parent calls.

  24.    Callers occupying less than 1.0% are not shown.

  25.    ticks parent name

  26.    13795 77.9% C:\WINDOWS\SYSTEM32\ntdll.dll

  27.    3795 21.4% C:\Program Files\nodejs\node.exe

  28.    3768 99.3% C:\Program Files\nodejs\node.exe

  29.    3287 87.2% Function: ~pbkdf2 crypto.js:633:16

  30.    3287 100.0% Function: ~exports.pbkdf2Sync crypto.js:628:30

  31.    3287 100.0% Function: ~router.get D:\github\webapp\js\usen\app.js:8:23

  32.    3287 100.0% Function: ~dispatch D:\github\webapp\js\usen\node_modules\_koa-compose@3.2.1@koa-compose\index.js:37:23

  33.    ...

报告包含六部分:Shared libraries、JavaScript、C++、Summary、C++ entry points 和 Bottom up (heavy) profile,[JavaScript] 部分列出了 JavaScript 代码执行所占用的 CPU ticks(CPU 时钟周期),[C++] 部分列出了 C++ 代码执行所占用的 CPU ticks,[Summary] 列出了各个部分的占比,[Bottom up] 列出了所有 CPU 占用时间从大到小的函数及堆栈信息。

根据 3287 87.2% Function: ~pbkdf2 crypto.js:633:16 可看出这个函数消耗了 87.2% 的cpu。

文件的方式不直观,那我们换个UI界面的,步骤如下:

·先clone v8的仓库下来 git clone GitHub - v8/v8: The official mirror of the V8 Git repository

· 将日志文件转换成 json格式 node --prof-process --preprocess isolate-xxxxxxxxxx-v8.log > v8.json

· 打开 v8/tools/profview/index.html 文件,是个静态界面,在界面中心选择刚生成的 v8.json文件,文件解析成功后,界面如下:

具体的功能就不一一解释啦,我们逐层展开,寻找耗时的点,很快便找到耗cpu的地方,如下图:

node占比是45%,其中 pbkdf2 crypto.js便占用了92%。

v8-profiler

除了官方提供之外,我们还可以选择开源大佬的库,v8-profiler ,这个库的创建的时间比较早,6年前便创建了,最近一次更是在一年半前,社区评价还是不错的。

生成报告

生成方式很简单,不足的是,需要硬编码在项目中,如下:

  1. profiler.startProfiling('', true);

  2.   setTimeout(function() {

  3.    var profile = profiler.stopProfiling('');

  4.    profile.export()

  5.    .pipe(fs.createWriteStream(`cpuprofile-${Date.now()}.cpuprofile`))

  6.    .on('finish', () => profile.delete())

  7.   }, 1000);

解析报告

·Chrome

我们的大Chrome要出马啦,在Chrome的控制台,有一栏 JavaScript Profile 如下图:

点击load,选择刚刚生成的文件,解析后如下:

逐层查看,便了然。

· flamegraph-火焰图

使用 flamegraph 生成酷炫的火焰图,用在报告那是酷炫的一逼,官网图如下:

使用方式就不细说啦。

· v8-analytics

这个是社区大佬们,写的一个开源库 v8-analytics,官方介绍如下

解析v8-profiler和heapdump等工具输出的cpu & heap-memory日志,可以提供:

1)v8引擎逆优化或者优化失败的函数标红展示以及优化失败原因展示;

2)函数执行时长超过预期标红展示;

3)当前项目中可疑的内存泄漏点展示。

对应的命令如下:

va test bailout --only 这个命令可以只把那些v8引擎逆优化的函数列出来展示。

va test timeout 200 --only 这个命令可以只把那些执时长超过200ms的函数列出来展示。

va test leak 可疑展示出测试的heapsnapshot文件中可疑的内存泄漏点。

这个库的好处是,省的我们一个个去点开查找,这样可以更加便于我们筛选问题啦~

批量压力测试及生成报告

autocannon 只能运行一个接口,要想在测试下一个接口,就得修改代码,比如想批量测试多个接口,就需要来回改代码,操作就比较麻烦,所以我基于 autocannon 写了个脚本,可以逐一压测定义好的接口,同时还可以生成测试报告。

  1. 'use strict'

  2.   const autocannon = require('autocannon')

  3.   const reporter = require('autocannon-reporter')

  4.   const path = require('path')

  5.   const sleep = ms => new Promise(resolve => setTimeout(resolve, ms));

  6.   /**

  7.    * @description

  8.    * 运行autocannon

  9.    * [url=home.php?mod=space&uid=267564]@Author[/url] lizc

  10.    * @param {*} param

  11.    */

  12.   function makeAutocannon(param) {

  13.    autocannon(param).on('done', handleResults)

  14.   }

  15.   /**

  16.    * @description

  17.    * 处理接口

  18.    * @author lizc

  19.    * @param {*} result

  20.    */

  21.   function handleResults(result) {

  22.    const reportOutputPath = path.join(`./${result.title}_report.html`)

  23.    reporter.writeReport(reporter.buildReport(result), reportOutputPath, (err, res) => {

  24.    if (err) console.err('Error writting report: ', err)

  25.    else console.log('Report written to: ', reportOutputPath)

  26.    })

  27.   }

  28.   // 请求参数

  29.   const autocannonParam = {

  30.    url: 'http://127.0.0.1:6100/',

  31.    connections: 100,

  32.    duration: 10,

  33.    headers: {

  34.    type: 'application/x-www-form-urlencoded'

  35.    }

  36.   }

  37.   // 请求报文参数

  38.   const requestsParam = {

  39.    method: 'POST', // this should be a put for modifying secret details

  40.    headers: { // let submit some json?

  41.    'Content-type': 'application/json; charset=utf-8'

  42.    }

  43.   }

  44.   /**

  45.    * @description

  46.    * 启动批量压测

  47.    * @author lizc

  48.    * @param {*} methodList 接口列表

  49.    */

  50.   async function run(methodList) {

  51.    const autocannonList = methodList.map(val => {

  52.    return {

  53.    ...autocannonParam,

  54.    url: autocannonParam.url + val,

  55.    title: val,

  56.    requests: [

  57.    {

  58.    ...requestsParam,

  59.    }

  60.    ],

  61.    }

  62.    })

  63.    for (let i = 0; i < autocannonList.length; i++) {

  64.    if (i !== 0) {

  65.    await sleep((autocannonList[i - 1].duration + 2) * 1000)

  66.    makeAutocannon(autocannonList[i])

  67.    } else {

  68.    makeAutocannon(autocannonList[i])

  69.    }

  70.    }

  71.   }

  72.   // 启动

  73.   run(['order', 'crypto'])

 感谢每一个认真阅读我文章的人!!!

作为一位过来人也是希望大家少走一些弯路,如果你不想再体验一次学习时找不到资料,没人解答问题,坚持几天便放弃的感受的话,在这里我给大家分享一些自动化测试的学习资源,希望能给你前进的路上带来帮助。

软件测试面试文档

我们学习必然是为了找到高薪的工作,下面这些面试题是来自阿里、腾讯、字节等一线互联网大厂最新的面试资料,并且有字节大佬给出了权威的解答,刷完这一套面试资料相信大家都能找到满意的工作。

 

          视频文档获取方式:
这份文档和视频资料,对于想从事【软件测试】的朋友来说应该是最全面最完整的备战仓库,这个仓库也陪伴我走过了最艰难的路程,希望也能帮助到你!以上均可以分享,点下方蓝色字体或小卡片即可自行领取。软件测试全套资料分享: 耗时2个月整理的软件测试最全资料包

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.xdnf.cn/news/15310.html

如若内容造成侵权/违法违规/事实不符,请联系一条长河网进行投诉反馈,一经查实,立即删除!

相关文章

昆明华厦眼科医院在大观小学开展近视科普教育讲座

为响应全社会对青少年近视防控的号召&#xff0c;昆明华厦眼科医院组织了一场近视科普教育讲座&#xff0c;活动走进大观小学&#xff0c;旨在通过专业的眼科知识普及&#xff0c;提升小学生们对眼健康的认知&#xff0c;培养他们爱眼护眼的意识。讲座结束后还特地为教师群体进…

MPLS基本原理

Multiprotocol Label Switching 多标签交换 前言 MPLS位于TCP/IP协议栈中的链路层和网络层之间,用于向IP层提供连接服务,同时又从链路层达到服务.MPLS以标签交换代替IP转发. MPLS并不是一种业务或者应用,它实际上是一种隧道技术.这种技术不仅支持多种高层协议与业务,而且在一…

《MarsCode:编程领域的智能新势力》

《MarsCode&#xff1a;编程领域的智能新势力》 一、MarsCode 的诞生与发展&#xff08;一&#xff09;逐步崛起的历程&#xff08;二&#xff09;与各方的合作与影响 二、MarsCode 的独特魅力&#xff08;一&#xff09;强大的功能特点&#xff08;二&#xff09;多语言支持与…

PyInstaller未包含预编译引导程序

1 现象 在使用 PyInstaller 打包 Python 应用时&#xff0c;遇到了一个错误&#xff0c;错误信息如下&#xff1a; Fatal error: PyInstaller does not include a pre-compiled bootloader for your platform. For more details and instructions how to build the bootloade…

华为HCIP-openEuler考试内容大纲:备考必看!

华为HCIP-openEuler认证考试作为ICT领域的一项重要技术认证&#xff0c;已经成为越来越多IT从业者追求的目标。无论你是想提升自己的技术能力&#xff0c;还是为了未来的职业发展&#xff0c;HCIP-openEuler都是一个极具价值的认证。那么&#xff0c;如何高效备考&#xff0c;顺…

编程之路,从0开始:知识补充篇

Hello大家好&#xff0c;很高兴我们又见面了&#xff01; 给生活添点passion&#xff0c;开始今天的编程之路&#xff01; 这一篇我们来补充一下在之前篇目没讲到的知识&#xff0c;并结合一些码友的私信提问和我在编程中遇到的问题&#xff0c;做一些易错点或易混点的讲解。 …

免费PC游戏加速器--慕讯公益加速器

百度网盘链接&#xff1a; 慕讯公益加速器 提取码: y54m 官网&#xff1a; 慕讯公益加速器 优点&#xff1a; 1.不像其他加速器假免费&#xff0c;但支持的话可以向软件捐款 2.加速游戏很全&#xff08;Nikke等游戏都可以选择它&#xff09;&#xff0c;可以自由选择节点 …

git 常用命令大全

提示&#xff1a;文章写完后&#xff0c;目录可以自动生成&#xff0c;如何生成可参考右边的帮助文档 文章目录 前言一、git是什么&#xff1f;二、工作中常用git命令集合三、部分git命令注意事项四、git reset 的五种模式五、总结 前言 git命令 其实不管是服务端还是前端&am…

【JAVA毕业设计】基于Vue和SpringBoot的校园资料分享平台

博主说明&#xff1a;本文项目编号 T 059 &#xff0c;文末自助获取源码 \color{red}{T059&#xff0c;文末自助获取源码} T059&#xff0c;文末自助获取源码 目录 一、系统介绍二、演示录屏三、启动教程四、功能截图五、文案资料5.1 选题背景5.2 国内外研究现状5.3 可行性分析…

typedef 与 extern 的结合:一场误解的澄清

typedef 与 extern 的结合:一场误解的澄清 一、typedef 的基本用法二、extern 的基本用法三、typedef 与 extern 的结合:一场误解的澄清示例二:使用 extern 声明外部变量示例三:错误的用法:尝试在 typedef 中使用 extern四、总结在C语言编程的世界里,typedef和extern是两…

腾讯的AI困局

科技新知 原创作者丨林书 编辑丨蕨影 2024年已经逐渐步入了尾声&#xff0c;但国产大模型的内卷之战却还在继续着…… 最近&#xff0c;腾讯终于有了新动作&#xff0c;在开源模型上卯足了劲。11 月 5 日&#xff0c;腾讯宣布开源 MoE 大语言模型混元 Large&#xff0c;腾讯称…

想部署一个自己的抖音,但是不会写代码怎么办? 部署一个自己的抖音系统

想部署一个自己的抖音,但是不会写代码怎么办? 看完这篇文章,你也快速拥有自己的抖音 上效果 安装教程 docker pull ghcr.io/zyronon/douyin-vue:latest docker run -d -p 10002:80 ghcr.io/zyronon/douyin-vue:latest 使用 浏览器打开ip:10002 然后就可以使用你自己的抖音…

QT之QString常用函数

1、构造函数 char类型可以直接通过构造函数构造QString&#xff0c;std::string不能直接作为参数构造QString对象&#xff0c;可以使用QString中的静态函数转换为QString: std::string stdstr"world"; QString str4QString::fromStdString(stdstr); 2、格式化构造(…

Dubbo源码解析(三)

一、Dubbo整合Spring启动流程 Dubbo的使用可以不依赖Spring&#xff0c;但是生产环境中Dubbo都是整合到Spring中一起使用&#xff0c;所以本章就解析Dubbo整合Spring的启动流程 一、传统的xml解析方式 一、Dubbo配置解析流程 在Java 中&#xff0c;一切皆对象。在JDK 中使用…

用两行命令快速搭建深度学习环境(Docker/torch2.5.1+cu118/命令行美化+插件),包含完整的 Docker 安装步骤

深度学习环境的配置过于繁琐&#xff0c;所以我制作了两个基础的镜像&#xff0c;希望可以帮助大家节省时间&#xff0c;你可以选择其中一种进行安装&#xff0c;版本说明&#xff1a; base 版本基于 pytorch/pytorch:2.5.1-cuda11.8-cudnn9-devel&#xff0c;默认 python 版本…

怎么在MindMaster里插入剪贴画?

使用MindMaster绘制思维导图时&#xff0c;可以通过插入剪贴画的方式&#xff0c;让整个思维导图更具表现力。思维导图软件提供大量极具设计感的剪贴画&#xff0c;涉及商业活动、学习教育、社会生活等各个方面。本文中将详细为你解说怎样在MindMaster里插入剪贴画。 打开Mind…

shell脚本(1)脚本创建执行与变量使用

声明!!! 学习视频来自B站UP主泷羽sec&#xff0c;如涉及侵权马上删除文章 视频链接&#xff1a;泷羽sec的个人空间-泷羽sec个人主页-哔哩哔哩视频 笔记的只是方便各位师傅学习知识,以下网站只涉及学习内容,其他的都与本人无关,切莫逾越法律红线,否则后果自负 执行文件方法 首先…

智能体创新大赛|全球规模最大智能体赛事,超3成获奖者已使用智能体赚钱

11 月 12 日&#xff0c;百度搜索联合技术合作伙伴NVIDIA举办的「2024百度搜索文心智能体创新大赛」决赛颁奖典礼在百度世界2024「文心智能体&#xff0c;新智生产力」分论坛举行。 据了解&#xff0c;这是全球规模最大的智能体大赛&#xff0c;共吸引近万名参与者提交近 4000…

PVE纵览-Proxmox VE SDN入门指南:构建灵活的虚拟网络

PVE纵览-Proxmox VE SDN入门指南&#xff1a;构建灵活的虚拟网络 文章目录 PVE纵览-Proxmox VE SDN入门指南&#xff1a;构建灵活的虚拟网络摘要SDN 在 PVE 中的作用SDN 在 PVE 中的作用区域和 VNetsIPAM&#xff08;IP Address Management&#xff09; 关键字&#xff1a; PV…

【含文档】基于ssm+jsp的高校财务处理系统(含源码+数据库+lw)

1.开发环境 开发系统:Windows10/11 架构模式:MVC/前后端分离 JDK版本: Java JDK1.8 开发工具:IDEA 数据库版本: mysql5.7或8.0 数据库可视化工具: navicat 服务器: apache tomcat 主要技术: Java,Spring,SpringMvc,mybatis,mysql,vue 2.视频演示地址 3.功能 系统定义了两个…