nodejs的10个性能优化技巧 |
本文标签:nodejs,性能优化 下面是我们使用Node.js时遵循的10个性能规则: 1. 避免使用同步代码 在设计上,Node.js是单线程的 。为了能让一个单线程处理许多并发的请求,你可以永远不要让线程等待阻塞,同步或长时间运行的操作 。Node.js的一个显著特征是:它从上到下的设计和实现都是为了实现异步 。这让它非常适合用于事件型程序 。 不幸的是,还是有可能会发生同步/阻塞的调用 。例如,许多文件系统操作同时拥有同步和异步的版本,比如writeFile和writeFileSync 。即使你用代码来控制同步方法,但还是有可能不注意地用到阻塞调用的外部函数库 。当你这么做时,对性能的影响是极大的 。 // Good: write files asynchronously fs.writeFile(message.txt, Hello Node, function (err) { console.log("Its saved and the server remains responsive!"); }); // BAD: write files synchronously fs.writeFileSync(message.txt, Hello Node); console.log("Its 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"} <!-- 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 许多服务器和客户端支持gzip来压缩请求和应答 。无论是应答客户端还是向远程服务器发送请求,请确保充分使用它 。 6.并行化 试着让你所有的阻塞操作-向远程服务发送请求,DB调用,文件系统访问并行化 。这将能减少最慢的阻塞操作的等待时间,而不是所有阻塞操作的等待时间 。为了保持回调和错误处理的干净,我们使用Step来控制流量 。 7.Session自由化 领英移动使用Express框架来管理请求/应答周期 。许多express的例子都包含如下的配置: app.use(express.session({ secret: "keyboard cat" })); 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移动版本这些平台上尝试一下,让我们知道自己做得怎么样 。 |