首页 > 解决方案 > 为什么 tomcat 比提供静态资源的 nodejs 快

问题描述

有人告诉我,在提供静态资源(例如 js/css/img)时,tomcat 很慢。(我只熟悉nodejs)

我不明白为什么 tomcat 比 nodejs/nginx 慢。他们应该都使用内存缓存,还是至少在提供静态资源时使用非阻塞 io?


我做了一个AB测试,结果出乎意料(tomcat比nodejs快)。我使用的是带有 Intel Core i5-5200 @ 2.20GHz 和 8GB RAM(戴尔笔记本电脑)的 Windows 7 Pro。我的 nodejs 版本是 v8.9.0,java 版本是 1.8.045 和 tomcat 5.5.17。

节点代码:

const path = require('path');
const Koa = require('koa');
const Router = require('koa-router');
const staticServer = require('koa-static');

const app = new Koa();
const router = new Router();

app.use(staticServer( path.join(__dirname, 'static')) );
app.listen(8001);

nodejs的结果是:

E:\soft-new\apache\Apache24\bin>ab -c 20 -n 1000 http://localhost:8001/benu_crm/a.html
This is ApacheBench, Version 2.3 <$Revision: 1748469 $>
Copyright 1996 Adam Twiss, Zeus Technology Ltd, http://www.zeustech.net/
Licensed to The Apache Software Foundation, http://www.apache.org/

Benchmarking localhost (be patient)
Completed 100 requests
Completed 200 requests
Completed 300 requests
Completed 400 requests
Completed 500 requests
Completed 600 requests
Completed 700 requests
Completed 800 requests
Completed 900 requests
Completed 1000 requests
Finished 1000 requests


Server Software:
Server Hostname:        localhost
Server Port:            8001

Document Path:          /benu_crm/a.html
Document Length:        3 bytes

Concurrency Level:      20
Time taken for tests:   0.679 seconds
Complete requests:      1000
Failed requests:        0
Total transferred:      209000 bytes
HTML transferred:       3000 bytes
Requests per second:    1472.67 [#/sec] (mean)
Time per request:       13.581 [ms] (mean)
Time per request:       0.679 [ms] (mean, across all concurrent requests)
Transfer rate:          300.57 [Kbytes/sec] received

Connection Times (ms)
              min  mean[+/-sd] median   max
Connect:        0    0   0.2      0       1
Processing:     6   13   3.0     13      26
Waiting:        6   11   2.7     10      23
Total:          6   13   3.0     13      26

Percentage of the requests served within a certain time (ms)
  50%     13
  66%     14
  75%     15
  80%     15
  90%     18
  95%     20
  98%     21
  99%     23
 100%     26 (longest request)

而tomcat的结果是:(对于tomcat,我只是做了一个没有任何java代码的a.html)

E:\soft-new\apache\Apache24\bin>ab -c 20 -n 1000 http://localhost:8050/benu_crm/a.html
This is ApacheBench, Version 2.3 <$Revision: 1748469 $>
Copyright 1996 Adam Twiss, Zeus Technology Ltd, http://www.zeustech.net/
Licensed to The Apache Software Foundation, http://www.apache.org/

Benchmarking localhost (be patient)
Completed 100 requests
Completed 200 requests
Completed 300 requests
Completed 400 requests
Completed 500 requests
Completed 600 requests
Completed 700 requests
Completed 800 requests
Completed 900 requests
Completed 1000 requests
Finished 1000 requests


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

Document Path:          /benu_crm/a.html
Document Length:        3 bytes

Concurrency Level:      20
Time taken for tests:   0.171 seconds
Complete requests:      1000
Failed requests:        0
Total transferred:      222000 bytes
HTML transferred:       3000 bytes
Requests per second:    5847.61 [#/sec] (mean)
Time per request:       3.420 [ms] (mean)
Time per request:       0.171 [ms] (mean, across all concurrent requests)
Transfer rate:          1267.74 [Kbytes/sec] received

Connection Times (ms)
              min  mean[+/-sd] median   max
Connect:        0    0   0.2      0       2
Processing:     0    3   1.3      3       8
Waiting:        0    3   1.4      3       8
Total:          0    3   1.3      3       8

Percentage of the requests served within a certain time (ms)
  50%      3
  66%      4
  75%      4
  80%      4
  90%      5
  95%      6
  98%      6
  99%      7
 100%      8 (longest request)

@EugèneAdell 谢谢。我将大小a.html增加到 309,344 字节。然后tomcat 5.5.17和nodejs koa2几乎相等。稍后我会尝试 NIO tomcat 并将结果也放上去。但它仍然让我感到惊讶,比 BIO 的 tomcat 与 koa2 几乎相等。

节点结果:

E:\soft-new\apache\Apache24\bin>ab -c 20 -n 1000 http://localhost:8001/benu_crm/a.html
This is ApacheBench, Version 2.3 <$Revision: 1748469 $>
Copyright 1996 Adam Twiss, Zeus Technology Ltd, http://www.zeustech.net/
Licensed to The Apache Software Foundation, http://www.apache.org/

Benchmarking localhost (be patient)
Completed 100 requests
Completed 200 requests
Completed 300 requests
Completed 400 requests
Completed 500 requests
Completed 600 requests
Completed 700 requests
Completed 800 requests
Completed 900 requests
Completed 1000 requests
Finished 1000 requests


Server Software:
Server Hostname:        localhost
Server Port:            8001

Document Path:          /benu_crm/a.html
Document Length:        309344 bytes

Concurrency Level:      20
Time taken for tests:   1.071 seconds
Complete requests:      1000
Failed requests:        0
Total transferred:      309555000 bytes
HTML transferred:       309344000 bytes
Requests per second:    933.65 [#/sec] (mean)
Time per request:       21.421 [ms] (mean)
Time per request:       1.071 [ms] (mean, across all concurrent requests)
Transfer rate:          282243.05 [Kbytes/sec] received

Connection Times (ms)
              min  mean[+/-sd] median   max
Connect:        0    0   0.3      0       3
Processing:     8   21  12.0     20     386
Waiting:        2   10   2.2      9      23
Total:          8   21  12.0     20     386

Percentage of the requests served within a certain time (ms)
  50%     20
  66%     22
  75%     23
  80%     23
  90%     25
  95%     26
  98%     29
  99%     31
 100%    386 (longest request)

Tomcat结果:

E:\soft-new\apache\Apache24\bin>ab -c 20 -n 1000 http://localhost:8050/benu_crm/a.html
This is ApacheBench, Version 2.3 <$Revision: 1748469 $>
Copyright 1996 Adam Twiss, Zeus Technology Ltd, http://www.zeustech.net/
Licensed to The Apache Software Foundation, http://www.apache.org/

Benchmarking localhost (be patient)
Completed 100 requests
Completed 200 requests
Completed 300 requests
Completed 400 requests
Completed 500 requests
Completed 600 requests
Completed 700 requests
Completed 800 requests
Completed 900 requests
Completed 1000 requests
Finished 1000 requests


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

Document Path:          /benu_crm/a.html
Document Length:        309344 bytes

Concurrency Level:      20
Time taken for tests:   0.916 seconds
Complete requests:      1000
Failed requests:        0
Total transferred:      309573000 bytes
HTML transferred:       309344000 bytes
Requests per second:    1091.64 [#/sec] (mean)
Time per request:       18.321 [ms] (mean)
Time per request:       0.916 [ms] (mean, across all concurrent requests)
Transfer rate:          330021.72 [Kbytes/sec] received

Connection Times (ms)
              min  mean[+/-sd] median   max
Connect:        0    0   0.4      0       1
Processing:     4   18   3.6     17      45
Waiting:        0    2   2.8      1      22
Total:          4   18   3.6     18      45

Percentage of the requests served within a certain time (ms)
  50%     18
  66%     18
  75%     19
  80%     19
  90%     21
  95%     23
  98%     27
  99%     37
 100%     45 (longest request)

标签: javanode.jsperformanceexpresstomcat

解决方案


归功于tomcat-users邮件列表和 devshed 这个基准测试,良好的 Tomcat 性能更可能归功于 Java 运行时:

纯 Java Tomcat 如何比 Apache httpd 更快地提供静态资源?我们能想到的主要原因:因为 Tomcat 是用 Java 编写的,并且因为 Java 字节码可以在运行时进行原生编译和高度优化,所以编写良好的 Java 代码在实现了许多运行时优化的成熟 Java VM 上运行时可以非常快,例如 Sun Hotspot JVM。在它运行并服务于许多请求之后,JVM 知道如何针对特定硬件上的特定用途对其进行优化。另一方面,Apache httpd 是用 C 语言编写的,完全在运行时之前编译。

但是,由于您的测试是关于多次访问一个小文件,也可能是 Tomcat 的设计比 Node.js 的设计更有效,特别是对于“接受连接并开始服务”部分。网络捕获可能有助于了解 Node.js 中的这种延迟来自何处


推荐阅读