开发者社区> 穆客> 正文
阿里云
为了无法计算的价值
打开APP
阿里云APP内打开

Node.js 性能平台支持死循环和正则攻击定位

简介: Node.js 性能平台开始支持死循环和正则攻击定位
+关注继续查看

Node.js 应用里面,常见性能问题从表现上来看有这么几类(Node.js 性能平台都提供了对应解决方案):

  • CPU 飚高:做 CPU Prfiling 定位热点函数
  • 内存泄露:堆快照/heaptimeline/heapprofile进行定位
  • CPU/内存使用都不高,但是 QPS 上不去或者 RT 很长:trace进行定位

CPU 飚高的情况又可分为两类:

  • 仍然可以继续处理业务,只是 RT 变长,这可以通过 CPU Profiling 定位
  • 完全无法继续处理业务,表现为 CPU 100% 占用,堆信息监控为直线

无法处理新业务的情况,JS 代码一般处于下面几种状态:

  • while/for 循环一直运行
  • 计算一直无法完成:例如执行一个斐波那契数列运算,当输入大于 50 的时候
  • 执行长时间正则表达式,

Node.js 性能平台在运行时v3.11.3v4.2.1及以前的版本里面对于,由于无法启动 CPU Profiling,也没有特别好的定位方法。只能根据监控提供问题开始时刻,去 nginx 的 access 日志里面查找相关线索。

随着 v3.11.4v4.2.1版本的发布,这两大难题将不会继续困扰我们。

即使代码处于上述中死循环长时间计算或者长时间正则表达式匹配状态,仍然可以启动 CPU Profiling,定位到问题所在。

下面的例子都来自不同行业的用户案例,为了简化验证过程,集成到了一个简单的 http 服务中。
默认用户已经开通 Node.js 性能服务,否则请参考 用户指南

'use strict';

const http = require('http');

function regexp() {
  let str = '<br/>                                             ' +
    '           早餐后自由活动,于指定时间集合自行办理退房手续。';
  str += '<br/>                                      <br/>' +
    '                                        <br/>           ' +
    '                         <br/>';
  str += '                                    <br/>' +
    '                                                        ' +
    '                                                        ' +
    '        <br/>';
  str += '                                                <br/>                                                                                                                <br/>';
  str += '                                                     ' +
    '                                                        ' +
    '       根据船班时间,自行前往暹粒机场,返回中国。<br/>';
  str += '如需送机服务,需增加280/每单。<br/>';

  let r = String(str).replace(/(^(\s*?<br[\s\/]*?>\*?)+|(\s*?<br[\s\/]*?>\s*?)+?$)/igm, '');
}

function deadloop () {
  while(1);
}

function f1() {
  deadloop();
}
function f2(){
  f1();
}
function f3(){
  f2();
}
function f4(){
  f3();
}

http.createServer( (req, res) => {
  console.log(req.url);

  switch(req.url) {
    case '/regexp': {
      regexp();
      res.end('regexp case');
    } break;
    case '/deadloop': {
      f4();
      res.end('deadloop case');
    } break;
    case '/exit': {
      process.exit(0);
    } break;
    default: {
      res.writeHead(200, "OK",{'Content-Type': 'text/html'});
      res.write('<html><head><title>Node.js</title></head><body style="font-family:arial;">');
      res.write('<h2> Regular Expression and Dead Loop Detection Example</h2>');

      res.write('<p>Click on button below to trigger long time running regexp test.');
      res.write('<form enctype="application/x-www-form-urlencoded" action="/regexp" method="post">');
      res.write('<button>Trigger Long Running Regular Expression</button></form>');

      res.write('<p>Click on button below to enter JavaScript dead loop test');
      res.write('<form enctype="application/x-www-form-urlencoded" action="/deadloop" method="post">');
      res.write('<button>Trigger Dead Loop JS function</button></form>');

      res.write('<p>The test can be terminated only before the above cases triggered.');
      res.write('<form enctype="application/x-www-form-urlencoded" action="/exit" method="post">');
      res.write('<button>Exit Test</button></form>');
      res.write('</form></body></html');
      res.end();
    } break;
  }
}).listen(8080);

console.log('\nhttp listen at 8080 pid: ', process.pid);

以下两幅图均是代码已经处于 CPU 100% 状态后启动 Profiling 后定位结果。

  • 正则表达式准确定位到当前执行的函数

undefined

  • 死循环目前定位到 while(1) 所在函数的调用者。如果在 CPU 100% 前启动 Profiling 则可以定位到具体函数,然而线上故障的不可预测性使得我们无法在问题出现前3分钟启动,后续 Node.js 性能平台会继续优化此处。

undefined

注意:
v3.11.4 和 v4.2.1 运行时采用了 SIGUSR2 触发诊断。如果用户没有设置 ENABLE_NODE_LOG=YES,请不要点击故障诊断按钮,否则会造成进程 crash。 其它版本没有这个问题。

版权声明:本文内容由阿里云实名注册用户自发贡献,版权归原作者所有,阿里云开发者社区不拥有其著作权,亦不承担相应法律责任。具体规则请查看《阿里云开发者社区用户服务协议》和《阿里云开发者社区知识产权保护指引》。如果您发现本社区中有涉嫌抄袭的内容,填写侵权投诉表单进行举报,一经查实,本社区将立刻删除涉嫌侵权内容。

相关文章
技能学习:学习使用Node.js + Vue.js,开发前端全栈网站-3.element-ui和vue-router路由的安装和使用
只要学会了路由,就可以搭建我们的项目了,只要审美没问题,就可以搭建出一个漂亮的静态网站,现在大家可以根据自己的需求把后台的页面和路由做出来了。 要制作一个动态网站,后续还要有很多需要学习借鉴的东西。
124 0
技能学习:学习使用Node.js + Vue.js,开发前端全栈网站-4.使用axios,并创建接口上传数据到mongodb数据库
根据我的业务范围,设想网站内容分为三类,设计、开发、小程序,设计中有二级分类平面设计、UI设计,平面设计又有三级分类包括VI设计、名片设计、LOGO设计…之后网站发布的不管是文章还是合作订单,全部归属到这些类别中,这样就需要用到数据的关联。
213 0
技能学习:学习使用Node.js + Vue.js,开发前端全栈网站-5.mongoodb数据库的“删、改、查”操作
上篇我们说了上传数据,也就是数据库的增加数据,本节我们探索一下“删、改、查”数据。
139 0
技能学习:学习使用Node.js + Vue.js,开发前端全栈网站-8.server端使用通用CRUD接口
CRUD是指在做计算处理时的增加(Create)、检索(Retrieve)、更新(Update)和删除(Delete)几个单词的首字母简写。CRUD主要被用在描述软件系统中数据库或者持久层的基本操作功能。
124 0
技能学习:学习使用Node.js + Vue.js,开发前端全栈网站-9.图片上传
之前我们做出了分类功能模块,同时在分类中实现了无限级分类关联;又制作文章功能模块,利用文章做出了多个分类的关联。本篇文章我们再建立一个技能模块,用来讲解图片的上传功能实现。
40 0
+关注
文章
问答
文章排行榜
最热
最新
相关电子书
更多
基于 Node.js 内核的企业级性能解决方案
立即下载
探究 Node.js 的服务端之路
立即下载
沪江基于Node.js大规模应用实践
立即下载