精华 高性能http/https的nodejs路由模块iroute
发布于 2年前 作者 DoubleSpout 2379 次浏览

一直想写一个高性能的路由模块,原来rrestjs框架那种try{}catch(){}方式感觉太丑陋了,最近有幸写了一个简单、轻量、高效的iroute路由模块。

irtoue具体功能可以根据http的请求方法归类路由,根据请求地址和url参数路由到不同的action中去,目前支持,get,post,put、delete、options、head这6种,其他http的method都归于other。

不同于普通的正则匹配,iroute模块采用c++的字符串验证,速度更快,跨平台支持,windows, linux和mac都经过了测试。

适用人群:不想用expressjs框架,只想用一个简单的路由给自己的应用或者站点,或者对性能要求比较高的用户。

安装方法: npm install iroute 或者直接去github上下载源码然后执行 node-gyp rebuild github地址:https://github.com/DoubleSpout/iroute

1、iroute模块的性能和传统正则匹配对比: A、注册100个路由,进行匹配1000次

regexp: 11ms
cb1 run times :1000
iroute: 3ms
cb2 run times :1000

B、注册1000个路由,进行匹配10000次

regexp: 1107ms
cb1 run times :10000
iroute: 251ms
cb2 run times :10000

iroute模块在普通2cpu的linux机器上性能差不多是原生的js正则的4倍。

2、iroute模块的api iroute模块api很简单,只有2个,1个用作注册路由规则,另外一个负责路由匹配。 A、iroute.add(routearray [,not_match_function]); 一个简单的代码示例,很容易就看明白了:

var iroute = require("iroute");"
iroute.add([
["get:/test1/",function(req,res){res.end('test1')}],
["get:/test2/test2/test2/test2/",function(req,res){res.end('test2')}],
["get:/test3/test3/test3/test3?key1&key2&key3",function(req,res){res.end('test3')}],
["post:/test4",function(req,res){res.end('test4')}],
["post:/test5/test5/test5/test5",function(req,res){res.end('test5')}],
["post:/test6/test6/test6/test6?key1&key2&key3",function(req,res){res.end('test6')}],
["put:/test7",function(req,res){res.end('test7')}],
["put:/test8/test8/test8/test8",function(req,res){res.end('test8')}],
["put:/test9/test9/test9/test9?key1",function(req,res){res.end('test9')}],
["delete:/test10",function(req,res){res.end('test10')}],
["delete:/test11/test11/test11/test11",function(req,res){res.end('test11')}],
["delete:/test12/test12/test12/test12?key1&key2&key3&key4&key5&key6&key7&key8&key9&key10",function(req,res){res.end('test12')}],
["head:/test6/test6/test6/test6?key1&key2&key3",function(req,res){res.end('')}],
["options:/test6/test6/test6/test6?key1&key2&key3",function(req,res){res.end('test14')}],
["other:/test6/test6/test6/test6?key1&key2&key3",function(req,res){res.end('test15')}],
],function(req,res){
  res.statusCode = 404;
    res.end('404')
})

not_match_function接受2个参数,req和res,当所有路由匹配不成功会调用这个函数

B、iroute.route(req,res); 这个方法用来进行路由匹配,放在入口处即可,比如下面这个代码就是一个简单的应用

var http = require('http');
http.createServer(function (req, res) {    
    var buf_list = [];
    var len=0;
    req.on("data",function(chunk){
        buf_list.push(chunk);
        len += chunk.length;
    })
    req.on("end", function(){
        req.body = Buffer.concat(buf_list, len).toString();
        if(req.url != '/favicon.ico') {
        
         iroute.route(req,res);
        } 
    })
  }).listen(8124);

欢迎广大node爱好者试用~ 最后附上expressjs使用简单代码:

    var express = require('express');
    var app = express();
    var iroute = require("iroute");
  
    var route_array = [
      ["get:/hello/world",function(req,res){res.end('hello world')}],
    ]
  
    app.use(iroute.connect(route_array));
  
    app.listen(3000);

这样在浏览器输入/hello/world就可以看到 hello world,输入其他路劲则是404

博客原文

另外为什么把代码加粗什么的功能键去掉了?不会排版了。。。

16 回复

不知道是否可以跟 connection 结合使用

目前没封装~

对于静态资源呢?

这个只是对请求路由的封装,没有做静态资源的控制

@snoopy 不过貌似只要用

  app.use(function(req, res, next){
    iroute.route(req,res);
  });

就可以集成近expressjs了,下午我自己试试

@snoopy iroute.add里面如果不加一些静态资源路由的话是不是就阻断了对静态资源的访问了呢

哈,昨天就在github上看到你这个模块了,是研究libuv的成果?

哈哈,我也奇怪,我还在调试发布的时候怎么又人watch了,一看头像就是你了,哈哈~ 没用libuv,多线程有时不一定有单线程高效,而且还要处理各种锁。

@showen 把静态资源的路由的app.use放在iroute匹配前面,或者把静态资源单独提取到其他域名下

@snoopy 嗯,看了下源码,不错不错。兄台很高产啊!

大大.能+Q问题儿童么

@snoopy 使用中发现了一个问题,还望解答。

iroute.add([ ["get:/",agent.index], ["post:/signup",agent.signup], ["get:/signup",agent.signup], ["get:/status",agent.status] ], agent.notFound); 如果将 ["get:/",agent.index] 加在第一位,则所有get请求均会走这个路由,包括未定义的, 例如 URL/abc 不会走 not_match_function 函数。

如果放在最后,这在这之前定义的路由会生效,但未定义的还是会走 ["get:/",agent.index]

不知道这种直接访问URL的路由规则应该如何设置?

hoho~是我写的一个bug,忘记考虑直接请求’/’这种情况了,已经fixed了,谢谢你的测试啊,你可以npm install iroute新版本0.2.4,试试~

@snoopy 对应真快啊。。刚试了下新版本,已经没这个问题了。。谢谢

回到顶部