登录
注册
node.js 学习社区
rrestjs高性能restful框架

眉间雀

2014-12-10 12:50

前阵子研究了当下最火的node.js框架——expressjs的源代码,发现其引入中间件的实现机制很巧妙,但是过多的中间件引入确实对性能影响比较大,虽然expressjs已经很快了,但是我想让他更快一些;再者expressjs的配置可谓复杂,app.set, app.get到底什么时候用什么,学习门槛比较高,我想让他更简单一些;最后expressjs的路由功能代码写的很潇洒,根据request.method分类,app.get, app.post等等,如果要增加一些uri每次都需要修改路由表,对于get和post两种方式的请求得写两遍,我想让他更方便一些。

rrestjs(ROA-Restful js)是在expressjs代码的基础上开发的(这样可以减少很多bug,同时要感谢expressjs作者visionmedia无私的奉献),不过整个框架结构已经完全改变了,属性以及方法定义也是全新的,可以说是一个全新的node.js框架。先献上一个简单的hello world 的例子吧:

 
	var  http  =   require ( 'http' ), 
    rrest  =   require ( 'rrestjs' ), 
    server  =  http . createServer ( rrest ( function   ( req ,  res )   { 
         res . send ( 'hello world' ); 
      })). listen ( 3000 );

项目及API地址:https://github.com/DoubleSpout/rrestjs

A、框架的性能一般看相对于裸奔的node.js性能下降多少,下面先列出大家最关心的性能对比数据:
注:rrestjs和expressjs均未打开session,gzip等影响性能的配置

 
		测试服务器: 
			cpu ( s ):  Intel ( R )  Xeon ( R )  E5620  2.4GHZ   ( 8  cpus  ) 
            mem :   6G 
            system :  linux  2.6 . 8   64bit 
            node :  v - 0.6 . 6 
AB 发包服务器:同上 网络环境:内网 测试软件: AB

 1 、 hellow world  输出, 1000 并发 50000 个请求 
node : 23075  req / sec
expressjs : 18452  req / sec
rrestjs : 20734  req / sec
 * node . js 在 8 核 CPU 上卓越的性能令人称赞啊 *这里 rrestjs 的入口加载机制和更少的入口处理让他比 expressjs 更快 2 、小静态 index . html 输出,   1000 并发 50000 个请求 
node : 15471  req / sec
expressjs : 9555  req / sec
rrestjs : 10411  req / sec
nginx : 13550  req / sec
 * node 在小静态文件处理上本次测试已经和老牌 web 服务器 nginx 平分秋色了 * rrestjs 在小静态文件上增加了 2 级缓存,减少一次 I / O 操作,所以更快 3 、 jade 模版输出, 1000 并发 50000 个请求 
expressjs : 10609  req / sec
rrestjs : 12584  req / sec
rrestjs ( jade cache ): 11772  req / sec
 *开启 jade 的 html 缓存并不会慢,在 5000 并发情况下,开启 html 缓存的性能要更为明显 * rrestjs 还在生成缓存加入了 key 机制,防止缓存重建时的雪崩效应 * rrestjs 减少了很多判断直接调用 jade 模版接口,所以性能略胜一筹

完整的AB和webbench测试结果请参阅:http://snoopyxdy.blog.163.com/blog/static/6011744020120135424340/

B、代码风格和上手门槛也很重要,expressjs自成一派的代码风格,各种app用顺了其实还是很方便的,但是不够直观,在定义开发模式或生产模式时需要:app.configure(‘production’,  function(){});rrestjs则类似nginx那样,只需要修改config.js文件,require不同的config.js文件即可,所有的功能在config.js上都有注释,需要打开,不需要关闭,直观而且简单。例如下面就是配置session的一段config:

 isSession : true ,  //是否开启session,开启会影响性能。 
syncSession : false ,//当多进程时是否开启session同步,开启会影响性能。 
sessionName : 'rrSid' ,  //保存session id 的cookie 的name 
sessionExpire : false ,  //false表示会话session,否则填入1000*60,表示session有效1分钟 
sessionDbStore : false ,//是否使用mongodb数据库存储session,如果设置为true,则不需要同步session

C、restful是面向资源的架构,rrestjs就是基于这个思想将req.url重新拼装,组成一个uri数组,举个例子:用户访问’/user/face/spout’,则req.path值为['user','face','spout']。只需要去require(‘user’)['face'](req, res);这样我们就可以根据用户访问的uri自动处理请求了,当然如果没有找到指定模块,则输出404页面拉。省去了繁琐的url路由,还能自由的配置各种规则,提升了性能,方便了处理。哈哈,不过我承认,取名为roa-restful确实是一个噱头,为了吸引眼球表喷我哦!示例代码:

 var  http  =   require ( 'http' ), 
    rrest  =   require ( 'rrestjs' ), 
    server  =  http . createServer ( rrest ( function   ( req ,  res ){ 
	 try {//实际测试证明,这里的try语句不会影响整体的性能,放心使用 
	    require ( './controller/' + req . path [ 0 ])[ req . path [ 1 ]]( req ,  res );//规则可以自定义,如果访问'/'则req.pah变为['index','index'] 
	 } 
	 catch ( err ){ 
            restlog . info ( 'Not found module: ' + err ); 
	    res . statusCode  =   404 ; 
	    res . render ( '/e404.jade' ); 
	 } 
    })). listen ( rrest . config . listenport );

D、青出于蓝必然胜于蓝,既然在expressjs代码上开发的新框架,必然功能要超越前辈,下面就列出部分expressjs和rrestjs功能对比表(坑爹啊,编辑器没有表格55555)

                      expressjs               node . js
 工作环境                   √(直接配置)              √(加载不同配置文件) 自动Favicon                √                        √ 
IP 访问过滤                X                       √ 自动输出静态文件            √                        √ 请求路由                   路由表                  RestfulSession 支持               √( redis 支持)             √( mongodb 支持) 多进程 session 共享         X                       √ 请求 IP 地址                X                       √ 
JSON 以及 JSONP            √                        √ 
deflat ,  gzip           X                       √ 模版支持                  各种主流                jade
Jade 模版 html 缓存          X                       √ 日志功能                   √                        √(支持分级,文件切分) 多进程多任务管理           X                       √ 子进程自动重启             X                       √ 开发模式,文件修改          X                       √ 自动重启 数据库连接池封装           X                       √( mongodb ) 自动加载模块              X                       √(自动加载指定文件夹的模块)

详细expressjs和rrestjs功能对比表见:http://snoopyxdy.blog.163.com/blog/static/60117440201201344425304/

E、最后介绍一下rrestjs内置的ClusterPlus模块

node.js 自带的cluster功能很薄弱,只提供基本的几个功能,而ClusterPlus就是为了健壮cluster的,不过在0.7版本的node.js已经大大提升了这项。node.js v-0.70文档API地址:http://nodejs.org/docs/v0.7.0/api/index.html

1、多进程多任务模式,提供了多个node.js进程执行多项任务,看如下代码,表示4个node.js进程监听4个不同端口,并且当其中某一个意外挂掉,主守护进程会自动重启这个进程,还是监听此前挂掉的这个进程的端口。

 var  http  =   require ( 'http' ), 
    rrest  =   require ( 'rrestjs' ), 
    port  =   [ 3000 ,   3001 ,   3002 ,   3003 ], 
    cp  =  rrest .ClusterPlus ({ 
	CreateCallback : function ( err ,  data ){ 
		 var  server  =  http . createServer ( rrest ( function   ( req ,  res ){   //writen server listen function here 
	        	res . send ( 'process ' + data . num + ' is listen at ' + port [ data . num ]+ ' : hello world everyone!' ); 
		 })). listen ( port [ data . num ]); 
	 }, 
	num : 4 ,//also set at config.js 
     });

2、代码修改自动重启,让node.js开发像php那样,放弃频繁的 ctrl+c和↑+enter,之前cluster模块也带有reload功能,但是对于新建的文件夹无法监听,而且对于有代码错误会中断程序,ClusterPlus在此基础上重新改写了代码,对于新建文件夹和新建的文件也做到了监听,而且对于有语法错误的修改,会尝试重启然后挂起,直到修改到没有语法错误后才完全重启成功,不会意外中断。示例代码:

 var  http  =   require ( 'http' ), 
    rrest  =   require ( 'rrestjs' ), 
    cp  =  rrest .ClusterPlus ({ 
	CreateCallback : function ( err ,  data ){ 
	    var  server  =  http . createServer ( rrest ( function   ( req ,  res ){ 
		res . send ( 'process ' + data . num + ' is working : hello world everyone!!' ); 
	     })). listen ( 3000 ); 
	 }, 
        num : 1 ,//这里只能开启一个子进程才能使用修改代码自动重启功能 
      });

最后总结一下:用别人的开源框架肯定不是最适合自己项目的,毕竟要被额外绑定很多没用的功能,所以在自己的项目上达到的性能肯定也不是最好的,最好当然是对开源框架做2次开发。其次,无论你代码写的效率如何不高,只要不写死循环,硬件顶上去神马都是浮云。我记得在虚拟机2CPU 2G内存的机子上,node.js跑hello world裸奔撑死跑4000+了,在4CPU,4G内存的老服务器上可以跑到9000+,今天在8CPU上竟然跑到2W3+,硬件才是硬道理啊,优化代码真不如多买几个CPU,多几个G的内存,再装个64位系统足矣,呵呵!

原文引自:http://www.kuqin.com/web/20120212/318073.html

回复 · 0

发表回复

你可以在回复中 @ 其他人