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 入门教程文档
Node.js是一个基于Chrome JavaScript运行时建立的平台, 用于方便地搭建响应速度快、易于扩展的网络应用。Node.js使用事件驱动,非阻塞I/O 模型而得以轻量和高效,非常适合在分布式设备上运行数据密集型的实时应用。 V8引擎本身使用了一些最新的编译技术。这使得用Javascript这类脚本语言编写出来的代码运行速度获得了极大提升,又节省了开发成本。对性能的苛求是Node的一个关键因素。 Javascript是一个事件驱动语言,Node利用了这个优点,编写出可扩展性高的服务器。Node采用了一个称为“事件循环(event loop)”的架构,使得编写可扩展性高的服务器变得既容易又安全。提高服务器性能的技巧有多种多样。Node选择了一种既能提高性能,又能减低开发复杂度的架构。这是一个非常重要的特性。并发编程通常很复杂且布满地雷。Node绕过了这些,但仍提供很好的性能。
目录
相关文章
|
27天前
|
JavaScript 安全 前端开发
js开发:请解释什么是XSS攻击和CSRF攻击,并说明如何防范这些攻击。
XSS和CSRF是两种常见的Web安全威胁。XSS攻击通过注入恶意脚本盗取用户信息或控制账户,防范措施包括输入验证、内容编码、HTTPOnly Cookie和CSP。CSRF攻击则诱使用户执行未经授权操作,防范手段有CSRF Tokens、双重验证、Referer检查和SameSite Cookie属性。开发者应采取这些防御措施并定期进行安全审计以增强应用安全性。
19 0
|
6月前
|
监控 数据可视化 安全
如何使用webgl(three.js)实现煤矿隧道、井下人员定位、掘进面、纵采面可视化解决方案——第十九课(一)
three.js、webgl、3D煤矿隧道、三维井下人员定位、掘进面三维可视化、纵采面可视化、采集面可视化展示、设备检测、数字孪生、物联网3D、3d建筑、3d库房,bim管理系统
165 1
|
4月前
|
监控 前端开发 JavaScript
在线教育系统|线上教学系统|基于Springboot+Vue+Nodejs实现在线教学平台系统
在线教育系统|线上教学系统|基于Springboot+Vue+Nodejs实现在线教学平台系统
|
9月前
|
JSON 前端开发 JavaScript
javascript:layui实现定位、查询数据以及select筛选的组合功能
javascript:layui实现定位、查询数据以及select筛选的组合功能
230 0
|
4月前
|
负载均衡 JavaScript 算法
Node.js 多进程的概念、原理、优势以及如何使用多进程来提高应用程序的性能和可伸缩性
Node.js 多进程的概念、原理、优势以及如何使用多进程来提高应用程序的性能和可伸缩性
41 1
|
1月前
|
JSON JavaScript 前端开发
JS逆向快速定位关键点之9大通用hook脚本
JS逆向快速定位关键点之9大通用hook脚本
|
6月前
|
移动开发 JavaScript 前端开发
【前端用法】html5实现地理位置定位(JS获取当前地理位置的方法)
【前端用法】html5实现地理位置定位(JS获取当前地理位置的方法)
123 0
|
3月前
|
人工智能 小程序 前端开发
毕业设计|基于NODE+VUE的校园跑腿平台系统
毕业设计|基于NODE+VUE的校园跑腿平台系统
|
3月前
|
监控 前端开发 JavaScript
在线教育系统|线上教学系统|基于Springboot+Vue+Nodejs实现在线教学平台系统
在线教育系统|线上教学系统|基于Springboot+Vue+Nodejs实现在线教学平台系统
|
4月前
|
监控 前端开发 Java
共享车位|基于SpringBoot+vue+node共享车位平台的设计与实现
共享车位|基于SpringBoot+vue+node共享车位平台的设计与实现