为什么Tomcat比Node.js更快地提供静态资源

4

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

我不明白为什么Tomcat比Node.js / Nginx慢。它们是否都应该使用内存缓存,或者至少在提供静态资源时使用非阻塞io呢?


我进行了一次AB测试,结果出乎意料(Tomcat比Node.js更快)。我使用的是Windows 7 Pro,Intel Core i5-5200 @ 2.20GHz和8GB RAM(Dell笔记本电脑)。我的Node.js版本是v8.9.0,Java版本是1.8.045,Tomcat版本是5.5.17。

下面是Node.js的代码:

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);

Node.js 的结果是:

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 几乎相等仍然让我感到惊讶。

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:        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)

2
你有进行基准测试来证明这个吗? - Eugène Adell
1
现代的Tomcat版本使用Java NIO,性能应该与本地代码非常相似。但是,正如@EugèneAdell所说,您应该在自己的环境中进行验证。 - stdunbar
你的问题太过模糊和宽泛。请在帖子中更新具体问题,以便解决。如果您只是想更深入地了解Tomcat在提供静态资源时的性能,那么您的问题就与主题无关。 - skomisa
从测试结果来看,他正在运行Tomcat 5.5,该版本不支持NIO(NIO连接器是在6.0版本中引入的)。 - Eugène Adell
1
@jiajianrong 您正在提供一个非常小的3字节文件。您的测试并没有准确比较提供静态资源所需的时间,而更可能是建立TCP连接和开始提供任何内容所需的时间。 - Eugène Adell
显示剩余5条评论
1个回答

2
感谢tomcat-users邮件列表和devshed提供这个基准测试,良好的Tomcat性能更可能归因于Java运行时: 引用块中说到:“纯Java的Tomcat如何能够比Apache httpd更快地提供静态资源?我们能想到的主要原因是:因为Tomcat是用Java编写的,并且因为Java字节码可以在运行时本地编译和高度优化,编写良好的Java代码可以在实现许多运行时优化(如Sun Hotspot JVM)的成熟Java VM上运行得非常快。在它运行并服务了许多请求之后,JVM知道如何针对特定的硬件优化它。另一方面,Apache httpd是用C语言编写的,它完全在运行时之前被编译。”
然而,由于您的测试涉及多次访问小文件,可能是Tomcat的设计比Node.js更有效,特别是对于“接受连接并开始提供服务”的部分。进行网络捕获可能有助于查看Node.js中延迟来自何处。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接