摘要:我们分别使用这样的原则来测试向每个架构注入个静态路由,测试最末尾的那个。而我们如何做到达到的性能,主要我们在内存中维护了一份静态路由列表,能让程序以最快的速度找到我们需要的。
对比
如果使用nodejs来搭建Service服务,那么我们首选express或者koa,而fastify告诉我们一个数据:
Framework | Version | Router? | Requests/sec |
---|---|---|---|
hapi | 18.1.0 | ✓ | 29,998 |
Express | 4.16.4 | ✓ | 38,510 |
Restify | 8.0.0 | ✓ | 39,331 |
Koa | 2.7.0 | ✗ | 50,933 |
Fastify | 2.0.0 | ✓ | 76,835 |
- | |||
http.Server | 10.15.2 | ✗ | 71,768 |
从数据中可以看出,Koa的性能远大于express。当然,它的测试基于简单的单路由测试。不过由此我们可以看到fastify的性能远大于Koa。相信使用过fastify的小伙伴都会对它的性能速度感到惊讶。其实原理很简单,就是请求的URL快速匹配Callback。如何做到,理论上也很简单,就是找寻它的最短路径来匹配。所以一般能够快速匹配的,都是通过空间换时间的方式来达到效果。
这里,我还想告诉大家一点,fastify并不是最快的。
主角今天的主角就是koa-rapid-router。为什么我们会以KOA打头呢?因为这篇文章目的其实是与koa-router的比较,而不是fastify。而此路由架构,也是为了在使用KOA的时候能够接近fastify的性能(经过测试,没有超过fastify,KOA本身的性能也有问题)。
接下来,我们会抛出一系列的测试数据来告诉大家Koa-router的性能是何其糟糕。我们分别使用这样的原则来测试
向每个架构注入10000个静态路由,测试最末尾的那个。
使用相同的测试命令 autocannon -c 100 -d 40 -p 10
对比静态路由和动态路由性能上的差距
测试代码全部在这里
静态路由对比我们写入如下的代码
for (let i = 0; i < 10000; i++) { router.get("/uuid/" + (i + 1), async (ctx) => ctx.body = "ok"); vrouter.get("/uuid/" + (i + 1), (res) => res.end("ok")); route_2.get("/interface/api/uuid/" + (i + 1), async (ctx) => ctx.body = "ok"); fastify.get("/interface/api/uuid/" + (i + 1), (request, reply) => reply.send("ok")); }
接着进行测试 npm run test,得到数据:
Preview:
Results
command | architecture | Latency | Req/Sec | Bytes/Sec |
---|---|---|---|---|
test:koa | koa + koa-router | 245.07 ms | 394.25 | 56 kB |
test:fast | fastify | 1.96 ms | 49324 | 7 MB |
test:rapid | koa + koa-rapid-router | 2.17 ms | 44828.8 | 6.37 MB |
test:http | http + koa-rapid-router | 1.64 ms | 58911.2 | 5.95 MB |
从数据上得出结论,koa-router在有10000个路由的时候,它的性能超级低下,只能达到平均的394.25,意思就是每秒只能处理394.25个请求,多来就不行。而koa + koa-rapid-router则处理到了44828.8个。同样是使用KOA模型,差距很明显。我做了分析,主要是koa-router内部循环比较多导致的。在10000个请求循环过程中,效率非常低下。而我们如何做到达到44828.8的性能,主要我们在内存中维护了一份静态路由列表,能让程序以最快的速度找到我们需要的callback。
对比fastify,可以看出,KOA本身性能的问题很大。
大家一定会问,对比静态路由Koa-router肯定没有优势,那么我们来对比动态路由。
动态路由对比我们写入如下代码
router.get("/zzz/{a:number}", async (ctx) => ctx.body = "ok"); vrouter.get("/zzz/{a:number}", (res) => res.end("ok")); route_2.get("/interface/api/zzz/:a(d+)", async (ctx) => ctx.body = "ok"); fastify.get("/interface/api/zzz/:a", (request, reply) => reply.send("ok"));
我们将这段代码加入到10000个静态路由代码的后面,修正测试的路径,我们得到如下数据:
Results
command | architecture | Latency | Req/Sec | Bytes/Sec |
---|---|---|---|---|
test:koa | koa + koa-router | 220.29 ms | 441.75 | 62.7 kB |
test:fast | fastify | 1.9 ms | 50988.65 | 7.24 MB |
test:rapid | koa + koa-rapid-router | 2.32 ms | 41961.6 | 5.96 MB |
test:http | http + koa-rapid-router | 1.82 ms | 53160.8 | 5.37 MB |
动态路由的对比从一定程度上可以看出koa-router的糟糕之处,不论是静态路由还是动态路由,它都基本稳定在400左右的qps。而koa + koa-rapid-router稍有下降,fastify一如既往的稳定。但是从http + koa-rapid-router模型上看,rapid完全超越fastify。koa + koa-rapid-router与koa + koa-router对比,性能大概是100倍的样子。如果我们可以这样认定,如果我们需要高并发,但是还是使用koa的生态的话,koa + koa-rapid-router是最佳选择。如果我们完全追求性能,不考虑生态的话,那么fastify首选。
有人会问,那么为什么http + koa-rapid-router不使用,它可是比fastify更快的路由?那是因为,http + koa-rapid-router需要多带带建立生态,暂时无法做到大规模使用,也许到最后,我们可以用上新的基于koa-rapid-router的企业级服务架构。这也是我正在思考的。
结尾我们所造的轮子的性能是不可能超越http模块的性能,我们只能无限接近它。这就像光速的道理一样,只能接近,无法等于。高性能架构主要还是在于理念模型,跟数学息息相关。
项目开源在 https://github.com/cevio/koa-rapid-router 有兴趣的小伙伴关注下,谢谢。
文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。
转载请注明本文地址:https://www.ucloud.cn/yun/102589.html
摘要:所以,最佳选择是。事实上,这种处理完全不必要。这样的设计,使得读取局部变量比读取全局变量快得多。请看下面两段代码,第一段代码是读取全局变量第二段代码是读取局部变量第二段代码读取变量的时候,不用前往上一层作用域,所以要比第一段代码快五六倍。 转自:http://www.ruanyifeng.com/blog/2011/08/jquery_best_practices.html ...
摘要:所以,最佳选择是。事实上,这种处理完全不必要。这样的设计,使得读取局部变量比读取全局变量快得多。请看下面两段代码,第一段代码是读取全局变量第二段代码是读取局部变量第二段代码读取变量的时候,不用前往上一层作用域,所以要比第一段代码快五六倍。 转自:阮一峰 日期: 2011年8月 4日http://www.ruanyifeng.com/blo... 上周,我整理了《jQuery设计思想》。...
摘要:转自阮一峰年月日上周,我整理了设计思想之理解篇。这样的设计,使得读取局部变量比读取全局变量快得多。请看下面两段代码,第一段代码是读取全局变量第二段代码是读取局部变量第二段代码读取变量的时候,不用前往上一层作用域,所以要比第一段代码快五六倍。 转自:阮一峰 2011年8月4日 http://www.ruanyifeng.com/blo... 上周,我整理了https://segmentf...
摘要:框架会默认加载下命名为或的配置文件。采用异步写日志的方式而不让此次写日志发生磁盘,阻塞线程从而造成不必要的性能损耗。 通过阅读本篇文章将了解到 1.日志输出到文件并根据LEVEL级别将日志分类保存到不同文件 2.通过异步输出日志减少磁盘IO提高性能 3.异步输出日志的原理 配置文件logback-spring.xml SpringBoot工程自带logback和slf4j的依赖,所...
摘要:框架会默认加载下命名为或的配置文件。采用异步写日志的方式而不让此次写日志发生磁盘,阻塞线程从而造成不必要的性能损耗。 通过阅读本篇文章将了解到 1.日志输出到文件并根据LEVEL级别将日志分类保存到不同文件 2.通过异步输出日志减少磁盘IO提高性能 3.异步输出日志的原理 配置文件logback-spring.xml SpringBoot工程自带logback和slf4j的依赖,所...
阅读 2443·2021-11-19 09:59
阅读 1970·2019-08-30 15:55
阅读 929·2019-08-29 13:30
阅读 1330·2019-08-26 10:18
阅读 3081·2019-08-23 18:36
阅读 2382·2019-08-23 18:25
阅读 1155·2019-08-23 18:07
阅读 430·2019-08-23 17:15