同一套业务逻辑,实现一个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的执行效率变高了,但这么想来也是违背了高并发的特性
抛砖引玉,一起探讨问题。如果你也感兴趣,不妨拿出点时间来写一段程序测试一下,我希望能得到不一样的结果。
代码不方便,框架用的是express,日志模块log4js,启动的时候初始化mecached和mongodb连接池,后续的就是业务逻辑操作了。解释了好多次了,即使把业务逻辑去掉,单纯测试接口返回,性能都差了不少。
@andyforever 不上代码,就没有人能够重复验证测试结果 ,谁都可以宣布自己赢了 ,就象 http://ourjs.com/detail/52fa1f91e7edb85055000008 上面的图示一样
不上图你说个卵 1, 你的express可能没启用模板编译缓存 2, 你写的代码实在是太挫
你要测试性能 应该要这样 require(‘http’).createServer(function(req, res){ //do sth… }).listen(80); 而不是需要渲染一堆页面, 没有测试的意义
你肯定会反驳… 请随意…
谁告诉你我渲染页面了? 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 当然我数据是随意写的 只是想表达如果你只是少量并发,用甚么框架不会有太大差异。 你不能因此推论更高并发也必定会有相同结果
如果比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高并发的特性。
@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才属于同一个层次 除了底层平台,两者的设计思路和写法都差不多一样