nodejs的10个性能优化技巧


Posted in NodeJs onJuly 15, 2014

下面是我们使用Node.js时遵循的10个性能规则:

1. 避免使用同步代码

在设计上,Node.js是单线程的。为了能让一个单线程处理许多并发的请求,你可以永远不要让线程等待阻塞,同步或长时间运行的操作。Node.js的一个显著特征是:它从上到下的设计和实现都是为了实现异步。这让它非常适合用于事件型程序。

不幸的是,还是有可能会发生同步/阻塞的调用。例如,许多文件系统操作同时拥有同步和异步的版本,比如writeFile和writeFileSync。即使你用代码来控制同步方法,但还是有可能不注意地用到阻塞调用的外部函数库。当你这么做时,对性能的影响是极大的。

// Good: write files asynchronously
fs.writeFile('message.txt', 'Hello Node', function (err) {
 console.log("It's saved and the server remains responsive!");
});
 
// BAD: write files synchronously
fs.writeFileSync('message.txt', 'Hello Node');
console.log("It's saved, but you just blocked ALL requests!");

我们的初始化log在实现时无意地包含了一个同步调用来将内容写入磁盘。如果我们不做性能测试那么就会很容易忽略这个问题。当以developer box中一个node.js实例来作为标准测试,这个同步调用将导致性能从每秒上千次的请求降至只有几十个。

2.关闭套接字池

Node.js的http客户端会自动地使用套接字池:默认地,它会限制每台主机只能有5个套接字。虽然套接字的重复使用可能会让资源的增加在控制之下,但如果你需要处理许多数据来自于同一主机的并发请求时,将会导致一系列的瓶颈。在这种情况下,增大maxSockets 的值或关闭套接字池是个好主意:

// Disable socket pooling
 
var http = require('http');
var options = {.....};
options.agent = false;
var req = http.request(options)

3.不要让静态资源使用Node.js

对于css和图片等静态资源,用标准的WebServer而不是Node.js。例如,领英移动使用的是nginx。我们同时还利用内容传递网络(CDNs),它能将世界范围内的静态资拷贝到服务器上。这有两个好处:(1)能减少我们node.js服务器的负载量(2)CDNs可以让静态内容在离用户较近的服务器上传递,以此来减少等待时间。

4.在客户端渲染

让我们快速比较一下服务器渲染和客户端渲染的区别。如果我们用node.js在服务器端渲染,对于每个请求我们都会回送像下面这样的HTML页面:

<!-- An example of a simple webpage rendered entirely server side -->
 
<!DOCTYPE html>
<html>
 <head>
  <title>LinkedIn Mobile</title>
 </head>
 <body>
  <div class="header">
   <img src="http://mobile-cdn.linkedin.com/images/linkedin.png" alt="LinkedIn"/>
  </div>
  <div class="body">
   Hello John!
  </div>
 </body>
</html>

请注意观察这个页面所有的内容,除了用户的名字,其余都是静态内容:对于每个用户和页面重载内容都是一样的。因此更有效的作法是让Node.js仅以JSON形式返回页面需要的动态内容。

{"name": "John"}
页面的其余部分—所有静态的HTML标记-能放在JavaScript模板中(比如underscore.js模板):

<!-- An example of a JavaScript template that can be rendered client side -->
 
<!DOCTYPE html>
<html>
 <head>
  <title>LinkedIn Mobile</title>
 </head>
 <body>
  <div class="header">
   <img src="http://mobile-cdn.linkedin.com/images/linkedin.png" alt="LinkedIn"/>
  </div>
  <div class="body">
   Hello <%= name %>!
  </div>
 </body>
</html>

性能的提升来自于这些地方:如第三点所说,静态JavaScript模板能通过webserver(比如nginx)在服务器端提供,或者用更好的CDN来实现。此外,JavaScript模板能缓存在浏览器中或存储在本地,所有初始页面加载以后,唯一需要发送给客户端的数据就是JSON,这将是最有效果的。这个方法能极大性地减少CPU,IO,和Node.js的负载量。

5.使用gzip

nodejs的10个性能优化技巧

许多服务器和客户端支持gzip来压缩请求和应答。无论是应答客户端还是向远程服务器发送请求,请确保充分使用它。

6.并行化

nodejs的10个性能优化技巧

试着让你所有的阻塞操作-向远程服务发送请求,DB调用,文件系统访问并行化。这将能减少最慢的阻塞操作的等待时间,而不是所有阻塞操作的等待时间。为了保持回调和错误处理的干净,我们使用Step来控制流量。

7.Session自由化

领英移动使用Express框架来管理请求/应答周期。许多express的例子都包含如下的配置:

app.use(express.session({ secret: "keyboard cat" }));
默认地,session数据是存储在内存中的,这会给服务器增加巨大的开销,特别是随着用户量的增长。你可以使用一个外部session存储,比如MongoDB或Redis,不过每一个请求将会导致远程调用来取得session数据的开销。在可能的情况下,最好的选择就是在服务器端存储所有的无状态数据。通过不包含上述express配置让session自由化,你会看到更好的性能。

8.使用二进制模块

如果可能,用二进制模块取代JavaScript模块。例如,当我们从用JavaScript写的SHA模块转换到Node.js的编译版本,我们会看到性能的一个大跃进:

// Use built in or binary modules
var crypto = require('crypto');
var hash = crypto.createHmac("sha1",key).update(signatureBase).digest("base64");

9.用标准的 V8 JavaScript 取代客户端库

许多JavaScript库都是为了在web浏览器上使用而创建的,因为在JavaScript环境不同时:比如,一些浏览器支持forEach,map和reduce这样的函数,但有些浏览器不支持。因此客户端库通常用许多低效的代码来克服浏览器的差异。另一方面,在Node.js中,你能确切地知道哪些JavaScript方法是有效的:V8 JavaScript引擎支撑Node.js实现ECMA-262第五版中指定的ECMAScript。直接用标准的V8 JavaScript函数替代客户端库,你会发现性能得到显著的提高。

10.让你的代码保持小且轻

使用移动设备会让访问速度慢且延迟高,这告诉我们要让我们的代码保持小且轻。对于服务器代码也保持同样的理念。偶尔回头看看你的决定且问自己像这样的问题:“我们真的需要这个模块吗?”,“我们为什么用这个框架,它的开销值得我们使用吗?”,“我们能用简便的方法实现它吗?”。小轻且的代码通常更高效、快速。

试试看

我们很努力地让自己的移动应用变得快速。在IPhone应用,Android应用和HTML5移动版本这些平台上尝试一下,让我们知道自己做得怎么样。

NodeJs 相关文章推荐
Nodejs异步回调的优雅处理方法
Sep 25 NodeJs
nodejs中简单实现Javascript Promise机制的实例
Dec 06 NodeJs
Nodejs中session的简单使用及通过session实现身份验证的方法
Feb 04 NodeJs
你一定会收藏的Nodejs代码片段
Feb 04 NodeJs
Nodejs学习item【入门手上】
May 05 NodeJs
详解nodejs 文本操作模块-fs模块(一)
Dec 22 NodeJs
详解nodejs 文本操作模块-fs模块(四)
Dec 22 NodeJs
配置nodejs环境的方法
May 13 NodeJs
nodejs结合Socket.IO实现的即时通讯功能详解
Jan 12 NodeJs
nodejs require js文件入口,在package.json中指定默认入口main方法
Oct 10 NodeJs
NodeJs 模仿SIP话机注册的方法
Jun 21 NodeJs
NodeJS配置CORS实现过程详解
Dec 02 NodeJs
提高NodeJS中SSL服务的性能
Jul 15 #NodeJs
在NodeJS中启用ECMAScript 6小结(windos以及Linux)
Jul 15 #NodeJs
nodejs 实现模拟form表单上传文件
Jul 14 #NodeJs
14款NodeJS Web框架推荐
Jul 11 #NodeJs
基于promise.js实现nodejs的promises库
Jul 06 #NodeJs
我的NodeJs学习小结(一)
Jul 06 #NodeJs
nodejs中使用monk访问mongodb
Jul 06 #NodeJs
You might like
PHP中的加密功能
2006/10/09 PHP
php 魔术方法详解
2014/11/11 PHP
yii用户注册表单验证实例
2015/12/26 PHP
PHP 7.0新增加的特性介绍
2017/06/08 PHP
php生成二维码不保存服务器还有下载功能的实现代码
2018/08/09 PHP
jquery 图片截取工具jquery.imagecropper.js
2010/04/09 Javascript
js中单引号与双引号冲突问题解决方法
2013/10/04 Javascript
JavaScript实现班级随机点名小应用需求的具体分析
2014/05/12 Javascript
一张Web前端的思维导图分享
2015/07/03 Javascript
jquery分隔Url的param方法(推荐)
2016/05/25 Javascript
JavaScript实现图片轮播组件代码示例
2016/11/22 Javascript
NodeJS基础API搭建服务器详细过程记录
2017/04/01 NodeJs
Bootstrap实现的标签页内容切换显示效果示例
2017/05/25 Javascript
angular.extend方法的具体使用
2017/09/14 Javascript
angular中ui calendar的一些使用心得(推荐)
2017/11/03 Javascript
使用veloticy-ui生成文字动画效果
2018/02/08 Javascript
Angular4.x通过路由守卫进行路由重定向实现根据条件跳转到相应的页面(推荐)
2018/05/10 Javascript
使用express来代理服务的方法
2019/06/21 Javascript
vue 集成jTopo 处理方法
2019/08/07 Javascript
three.js 将图片马赛克化的示例代码
2020/07/31 Javascript
python实现unicode转中文及转换默认编码的方法
2017/04/29 Python
Python写一个基于MD5的文件监听程序
2019/03/11 Python
Python手绘可视化工具cutecharts使用实例
2019/12/05 Python
django处理select下拉表单实例(从model到前端到post到form)
2020/03/13 Python
keras打印loss对权重的导数方式
2020/06/10 Python
PyQT5速成教程之Qt Designer介绍与入门
2020/11/02 Python
科沃斯机器人官网商城:Ecovacs
2016/08/29 全球购物
阿里巴巴英国:Alibaba英国
2019/12/11 全球购物
物流管理专业职业生涯规划书
2014/01/06 职场文书
股权转让协议书
2014/04/12 职场文书
计算机应用专业自荐信
2014/07/05 职场文书
检讨书范文2000字
2015/01/28 职场文书
反四风问题学习心得体会
2016/01/22 职场文书
给原生html中添加水印遮罩层的实现示例
2021/04/02 Javascript
OpenCV-Python实现怀旧滤镜与连环画滤镜
2021/06/09 Python
sql字段解析器的实现示例
2021/06/23 SQL Server