下面是我们使用Node.js时遵循的10个性能规则:
1. 避免使用同步代码
在设计上,Node.js是单线程的。为了www.usus.cc能让一个单线程处理许多并发的请求,你可以永远不要让线程等待阻塞,同步或长时间运行的操作。Node.js的一个显著特征是:它从上到下的设计和实现都是为了实现异步。这让它非常适合用于事件型程序。
不幸的是,还是有可能会发生同步/阻塞的调用。例如,许多文件系统操www.usus.cc作同时拥有同步和异步的版本,比如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。例如www.usus.cc,领英移动使用的是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>
请注意观察这个页面所有的内容,除了用户的名字,其余都是静态内容:www.usus.cc对于每个用户和页面重载内容都是一样的。因此更有效的作法是让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>
1. 避免使用同步代码
在设计上,Node.js是单线程的。为了www.usus.cc能让一个单线程处理许多并发的请求,你可以永远不要让线程等待阻塞,同步或长时间运行的操作。Node.js的一个显著特征是:它从上到下的设计和实现都是为了实现异步。这让它非常适合用于事件型程序。
不幸的是,还是有可能会发生同步/阻塞的调用。例如,许多文件系统操www.usus.cc作同时拥有同步和异步的版本,比如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。例如www.usus.cc,领英移动使用的是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>
请注意观察这个页面所有的内容,除了用户的名字,其余都是静态内容:www.usus.cc对于每个用户和页面重载内容都是一样的。因此更有效的作法是让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>