Node.js真的有高并发优势吗?看看Node.js和Tomcat的并发测试结果
发布于 7个月前 作者 andyforever 2326 次浏览

同一套业务逻辑,实现一个webservice中间接口,中间涉及memcached和mogodb的一些操作。 分别在Node.js和JAVA平台实现,java代码部署在Tomcat 7.0上,用Apache jmeter进行压力测试。 得到的测试结果很是出乎意料,Node.js的高并发优势为什么没有体现出来呢???

**操作系统:**CentOS 6.4(虚拟机) **内存:**1.5G **CPU:**单核

并发数 100 **ramp-up period(in seconds)**1 执行次数 10

以下是测试结果: Lable #Sample Average Median 90%Line Min Max Error% Throughput KB/sec Node.js HTTP请求 1000 333 369 485 1 956 0.0 183.3180568285976 40.995932630614114 Tomcat HTTP请求 1000 48 9 188 2 563 0.0 183.4862385321101 58.414564220183486

可以看到Node.js的平均执行时间为333毫秒,Tomcat的执行时间为48毫秒,Tomcat比Node.js快了近7倍!

补充1:即使是测试接口直接返回,不涉及后续的操作,Tomcat也比Node.js快了很多,求各位大神给个解释。

补充2:修改jmeter 的 ramp-up period的测试条件,比如这个值增大(如10秒),node.js的执行效率变高了,但这么想来也是违背了高并发的特性

抛砖引玉,一起探讨问题。如果你也感兴趣,不妨拿出点时间来写一段程序测试一下,我希望能得到不一样的结果。

32 回复

执行次数 10 是啥意思

100个线程循环执行10次

你确定你写的测试对?

业务逻辑没有问题,返回结果正确。

上代码吧 还有测试工具

代码不方便,框架用的是express,日志模块log4js,启动的时候初始化mecached和mongodb连接池,后续的就是业务逻辑操作了。解释了好多次了,即使把业务逻辑去掉,单纯测试接口返回,性能都差了不少。

@andyforever 不上代码,就没有人能够重复验证测试结果 ,谁都可以宣布自己赢了 ,就象 http://ourjs.com/detail/52fa1f91e7edb85055000008 上面的图示一样

@yakczh 业务逻辑确实是一样的,代码实现上肯定有些差别。我再用ab测试一下结果看看。

你这比较对象首先就有问题, 你应该用nginx 跟 Tomcat 比. Node.js 应该跟 java 对比

Node.js可以看成是web服务器

100个并发没有意义,压测至少上千至上万才有会有意义, 就像select在低连线数时,效率可能会比epoll更高。

后面的业务逻辑在生产环境,现在想用node替换一个中间件,看来效果并不是很好。100个并发效率这么低的话,再大的并发也不适用于真实场景了。

你指的成千上万是1秒时间内么?

不上图你说个卵 1, 你的express可能没启用模板编译缓存 2, 你写的代码实在是太挫

你要测试性能 应该要这样 require(‘http’).createServer(function(req, res){ //do sth… }).listen(80); 而不是需要渲染一堆页面, 没有测试的意义

你肯定会反驳… 请随意…

看来没有几个人懂测试。。。

@andyforever 如果单纯的测试并发 个人感觉就不应该有业务逻辑 毕竟如果有很多复杂逻辑的话 Node就不擅长了~

谁告诉你我渲染页面了? app.post("/",function(req, res){ //时间戳校验 res.json({"status":"error","code":"C_0008","msg":"您的时间戳超时"}); }) 好吧,我就写个时间戳校验太挫了,占用了node大部分的处理时间。

我的意思是你可能100个并发node要300ms, tomcat只要50ms 但1000个并发 node可能500ms tomcat却要300ms 10000个并发 node可能1000ms tomcat却要3000ms 当然我数据是随意写的 只是想表达如果你只是少量并发,用甚么框架不会有太大差异。 你不能因此推论更高并发也必定会有相同结果

@asoedarren 感兴趣可以分别写一段java和js代码试一下,我也是来求证的。 不过好像大部分都人云亦云了,真正测过的没有几个。

如果比node和Tomcat的性能请用

var http = require('http');
http.createServer(function (req, res) {
  ...
}).listen(80);

如果比node和java的性能 请上代码 或 简单说一下各自用的框架和怎么实现的

node.js框架用的是express,日志模块log4js,启动的时候初始化mecached和mongodb连接池,后续的就是业务逻辑操作. java是SpringMVC+mybatis。 测试过程有memcached和mongodb操作,也有独立的接口操作,不涉及数据库操作。 代码不方便发。

帮顶。我也挺感兴趣的,因为毕竟无业务的纯压node是没有意义的,用在业务场景上才有效。当然,业务背景也不能过于复杂,否则就没有可比性了。 感觉这更像2套方案的比较,跟node还是tomcat没有太直接的关系。 建议去掉memcached和mybatis,且后端都用mysql。这样缓存能减少更多,也就排除掉更多的因素了。

我来发个方便发代码的 机器是笔记器i5 2g内存 win7 nodejs express2.5 代码

app.get('/bench',function(req,res){

var sql="";
var i=0;
do {
  sql='select * from user ';
    sql+=' left join userinfo';
    sql+='  using(uid) ';
    sql+=' where age> 20 and salary > 3000';
    }while (i++ < 30);

res.write(sql);
res.end();


});

ab -n 10000 -c 200 http://localhost:3000/bench

Server Software: Server Hostname: localhost Server Port: 3000

Document Path: /bench Document Length: 83 bytes

Concurrency Level: 200 Time taken for tests: 32.205495 seconds Complete requests: 10000 Failed requests: 0 Write errors: 0 Total transferred: 1810000 bytes HTML transferred: 830000 bytes Requests per second: 310.51 [#/sec] (mean) Time per request: 644.110 [ms] (mean) Time per request: 3.221 [ms] (mean, across all concurrent requests) Transfer rate: 54.87 [Kbytes/sec] received

Connection Times (ms) min mean[+/-sd] median max Connect: 0 1 1.6 2 40 Processing: 27 630 177.1 537 1148 Waiting: 5 326 210.2 305 1042 Total: 27 632 177.6 537 1150 tomcat8

public class RequestBench extends HttpServlet {
    @Override
    public void doGet(HttpServletRequest request,
                      HttpServletResponse response)
        throws IOException, ServletException
    {
        response.setContentType("text/html");
 
         PrintWriter out = response.getWriter();
          int i=0;
  StringBuilder sb;
  do {
  sb = new StringBuilder();
  sb.append("select * from user ");
  sb.append(" left join userinfo");
  sb.append("  using(uid) ");
  sb.append(" where age> 20 and salary > 3000");
 
  } while (i++ < 30);
   
        out.println(sb);
    }

    @Override
    public void doPost(HttpServletRequest request,
                      HttpServletResponse response)
        throws IOException, ServletException
    {
        doGet(request, response);
    }

}

ab -n 10000 -c 200 http://localhost:8080/examples/bench/

Server Software: Apache-Coyote/1.1 Server Hostname: localhost Server Port: 8080

Document Path: /examples/bench/ Document Length: 85 bytes

Concurrency Level: 200 Time taken for tests: 38.352093 seconds Complete requests: 10000 Failed requests: 0 Write errors: 0 Total transferred: 2510000 bytes HTML transferred: 850000 bytes Requests per second: 260.74 [#/sec] (mean) Time per request: 767.042 [ms] (mean) Time per request: 3.835 [ms] (mean, across all concurrent requests) Transfer rate: 63.91 [Kbytes/sec] received

Connection Times (ms) min mean[+/-sd] median max Connect: 0 2 1.8 2 70 Processing: 28 750 218.5 693 1313 Waiting: 7 393 251.2 367 1272 Total: 30 752 219.2 695 1315 有服务器的可以把代码放到服务器上重复验证一下测试结果

其实我有这样的测试方案,因为在res.json返回前会有一些校验,最先是校验时间戳,我只要时间戳控制一下就不会走会面的业务流程了,包括memcached、mongodb、mybatis等。 但是就单纯的测试校验返回node的性能也不是很高。

不太了解ab测试,不知道这200个并发10000个请求是否跟jmeter一样在准备线程的时候有个ramp-up period参数,即线程的创建时间,如果这个时间值越大,node的性能就能高一些,就像补充2里提到的,这违背了node.js高并发的特性。

@jeremy16601 pm2 start app.js 和node app.js都分别测试过,结果一样。

@andyforever 那我能吧java看成web服務器嗎

@andyforever http://java.dzone.com/articles/performance-comparison-between 这里有用jmeter做测试的结果 两者都读取couchdb然后输出json
nodejs 509 java/servlet 422 509/422 =1.2061611374407584 310/260 = 1.1923076923076923 跟我的测试结果相差不多, 偏高主要可能是因为用http模块来跟servlet来pk有点占便宜,应该是 express跟servlet来pk才属于同一个层次 除了底层平台,两者的设计思路和写法都差不多一样

回到顶部