共计 7763 个字符,预计需要花费 20 分钟才能阅读完成。
测试动机
NodeJS 因为它的非阻塞 I / O 和优秀的高并发性能受到越来越多的关注,而且 NodeJS 的服务器相对于 Nginx 其搭建非常简单,仅需很少的步骤和设置就可以搭建一个高性能的文件服务器。之前我有一台 Tomcat 服务器兼做文件下载的功能,后来我在上面部署了一个 NodeJS 来提供静态文件的下载,然后经过压力测试发现 NodeJS 在静态文件的服务能力上强于 Tomcat 很多,主要体现在支持的并发连接数多,处理单个请求快。下面介绍一下我部署 NodeJS 静态资源文件服务器的过程和压测结果。
这里以 Ubuntu 系统为例介绍 NodeJS 服务器的搭建过程
首先需要安装 node 服务和 npm 工具,Ubuntu 安装命令如下:
$sudo apt install nodejs-legacy
$sudo apt install npm
如果网速还可以,那么安装这两个东西的时间也就在一分钟以内。
然后我们需要为我们的 nodejs 应用创建一个目录,比如文件夹的名字叫 myapp
$ mkdir myapp
$ cd myapp
然后通过 npm init
命令为你的应用创建一个 package.json
文件,作用是初始化 Express 这个 nodeJS 框架的
$ npm init
敲回车以后需要输入一些东西,全部用默认的就可以,一路回车敲下去
输入“yes”后,会在 myapp 目录下生成一个.json 文件,如上图,然后我们安装 express 框架 并将其保存到依赖列表中
$ npm install express --save
然后我们需要创建一个 index.js 作为 nodeJS 服务器的入口文件
在 index.js 中,输入如下内容
var express = require('express');
var app = express();
app.get('/', function (req, res) {res.send('Hello World!');
});
app.use(express.static('public'));
var server = app.listen(3000, function () {var host = server.address().address;
var port = server.address().port;
console.log('Example app listening at http://%s:%s', host, port);
});
其中
app.use(express.static('public'));
表示将静态资源文件所在的目录作为参数传递给 express.static
中间件以提供静态资源文件的访问。例如,假设在 /public
目录放置了图片、CSS 和 JavaScript 文件,就可以通过这个配置将 public 底下的文件映射到 url 上面
然后我在 images 目录放了一个图片文件,名字叫 pic1.jpg
然后我启动 nodeJS 服务器,用下面的命令
$ node index.js
执行这段指令的时候会在控制台打出刚才我在 index.js 中配置的 console 函数,控制台输出 Example app listening at http://:::3000,表示 NodeJS 服务器已经成功启动并监听 3000 端口.
注意: 如果此时点击 ctrl+ c 会终止掉 nodeJS 的服务进程, 包括 SSH 工具
然后通过浏览器访问 http://localhost:3000 可以看到浏览器输出一句Hello World!, 说明 NodeJS 服务器运转正常
然后访问我们部署好的静态文件 pic1.png 只需要访问 http://localhost:3000/images/pic1.jpg 就可以看到浏览器下载到的图片了,这里要注意 public 文件夹映射到了 3000 端口的根目录,也就是说不必在 url 中输入 /public。
下面我们来对比一下 tomcat 静态文件下载和 nodeJS 静态文件下载的并发性能,测试工具是 apache 的 ab,测试目标是一个 20m 左右的 apk 文件,首先看一下 tomcat 的表现
测试环境:
- 网络环境:本地回环
- 测试客户端:本机
- 被测试服务器:本机
- 服务器系统:Ubuntu 14.04
- 服务器配置:Intel(R) Core i7(TM) CPU 3.40GHz 2 CPUS
- 内存:8GB
- NodeJS 版本: v0.4.12
我在服务器上同时部署了 80 端口的 tomcat 和 3000 端口的 nodeJS,tomcat 的文件目录为 webapp/ 项目目录 /release/,tomcat 所有设置除了端口以外均采用默认设置,使用两个 20MB 左右的 apk 压缩包做测试目标,测试命令分别为:
ab -n1000 -c100 192.168.1.81/release/test.apk
ab -n1000 -c100 192.168.1.81:3000/test.apk
让我们来观察一下控制台输出:
alex@alex-ThinkPad-T430:~$ ab -n1000 -c100 192.168.1.81/release/test.apk
This is ApacheBench, Version 2.3 <$Revision: 1706008 $>
Copyright 1996 Adam Twiss, Zeus Technology Ltd, http://www.zeustech.net/
Licensed to The Apache Software Foundation, http://www.apache.org/
Benchmarking 192.168.1.81 (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: 192.168.1.81
Server Port: 80
Document Path: /release/test.apk
Document Length: 20300487 bytes
Concurrency Level: 100
Time taken for tests: 6.486 seconds
Complete requests: 1000
Failed requests: 0
Total transferred: 20300772000 bytes
HTML transferred: 20300487000 bytes
Requests per second: 154.17 [#/sec] (mean)
Time per request: 648.617 [ms] (mean)
Time per request: 6.486 [ms] (mean, across all concurrent requests)
Transfer rate: 3056498.14 [Kbytes/sec] received
Connection Times (ms)
min mean[+/-sd] median max
Connect: 0 1 0.8 0 6
Processing: 43 638 333.7 519 2088
Waiting: 0 5 15.8 1 93
Total: 43 639 333.9 520 2091
WARNING: The median and mean for the initial connection time are not within a normal deviation
These results are probably not that reliable.
Percentage of the requests served within a certain time (ms)
50% 520
66% 672
75% 843
80% 883
90% 1085
95% 1334
98% 1528
99% 1781
100% 2091 (longest request)
我们可以看到 1000 个请求的总用时是6.486 秒,下面再看看 nodeJS 的表现,nodeJS 文件目录为项目目录 /public/
同上面测试 tomcat 一样,测试同一个 20m 的 apk 文件,index.js 的代码如下:
var express = require('express');
var app = express();
app.get('/', function (req, res) {res.send('Hello World!');
});
app.use(express.static('public'));
var server = app.listen(3000, function () {var host = server.address().address;
var port = server.address().port;
console.log('Example app listening at http://%s:%s', host, port);
});
alex@alex-ThinkPad-T430:~$ ab -n1000 -c100 192.168.1.81:3000/test.apk
This is ApacheBench, Version 2.3 <$Revision: 1706008 $>
Copyright 1996 Adam Twiss, Zeus Technology Ltd, http://www.zeustech.net/
Licensed to The Apache Software Foundation, http://www.apache.org/
Benchmarking 192.168.1.81 (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: 192.168.1.81
Server Port: 3000
Document Path: /test.apk
Document Length: 20300487 bytes
Concurrency Level: 100
Time taken for tests: 18.002 seconds
Complete requests: 1000
Failed requests: 0
Total transferred: 20300799000 bytes
HTML transferred: 20300487000 bytes
Requests per second: 55.55 [#/sec] (mean)
Time per request: 1800.207 [ms] (mean)
Time per request: 18.002 [ms] (mean, across all concurrent requests)
Transfer rate: 1101261.94 [Kbytes/sec] received
Connection Times (ms)
min mean[+/-sd] median max
Connect: 0 0 0.7 0 3
Processing: 1685 1798 43.1 1799 1876
Waiting: 32 53 11.1 52 87
Total: 1685 1798 43.0 1801 1876
Percentage of the requests served within a certain time (ms)
50% 1801
66% 1829
75% 1837
80% 1840
90% 1849
95% 1856
98% 1862
99% 1871
100% 1876 (longest request)
NodeJS 总耗时为18.002 秒,比 tomcat 的速度慢 3 倍左右。
从这里可以看出,对于一个不需要执行任何动态代码的静态文件下载,tomcat 服务器在默认配置下要比 nodeJS 在默认配置下高 3 倍性能。
但是要注意这是使用服务器自己测试服务器自己,所有的流量均走本地回环网卡,也就是说排除了网速对于服务器处理性能的影响,我也是过在局域网内使用另一台 linux 服务器进行测试,不过由于测试文件是个 20m 的 apk,几乎 99.999% 的时间都用于网络传输(使用 ab 能让局域网网速跑满,实测的时候一直保持在 11.3MB/s)所以 Tomcat 和 NodeJS 的性能差别并不明显。
那么既然 nodeJS 在文件的并发访问请求方面相对于 tomcat 并无优势,那么我们为什么还要使用 nodeJS 来做静态资源服务器呢?
有一个优势是 nodeJS 提供了方便的 url 重定向功能,比如我们有好几个文件夹下的静态文件都想通过 192.168.1.81:3000/static/xxx.jpg 这样来获取,也就是不加上具体资源文件夹的名字如 /css,/js 这样,那么通过 nodeJS 只需几行代码就可以搞定:
app.use('/static', express.static('css'));
app.use('/static', express.static('js'));
app.use('/static', express.static('imgs'));
这样就轻松的把所有类型的静态文件都影射到了 192.168.1.81:3000/static/ 这个 url 下
另外,NodeJS 在做静态资源文件服务器的时候,还可以监听资源文件夹的文件增删改事件,然后以这些事件做为触发器做一些其他的操作,这个功能使用 Tomcat 很难完成,例如有人用新增 jpg 图片文件的事件触发制作了 webp 压缩图片文件,对于 nodeJS 只需几行代码就搞定了,我把上面测试的代码稍加改动如下就可以实现监听某个文件夹动作的功能,使用 fs 模块和 chokidar 模块分别做测试:
var express = require('express');
var chokidar = require('chokidar');// 文件监听,需要使用 npm 安装新模块
var fs = require('fs');//fs 文件监听
var app = express();
app.get('/', function (req, res) {res.send('Hello World!');
});
app.use(express.static('/opt/apache-tomcat-8.0.36/webapps/AndroidOnlinePackage/release'));
app.use(express.static('public'));
var server = app.listen(3000, function () {var host = server.address().address;
var port = server.address().port;
console.log('Example app listening at http://%s:%s', host, port);
// 监控文件夹
var watcher = chokidar.watch("public", {persistent: true // 保持监听状态});
// 监听增加,修改,删除文件的事件
watcher.on('all', (event, path) => {switch (event) {
case 'add':
console.log('添加文件'+path)
case 'change':
console.log('改变文件'+path)
break;
case 'unlink':
console.log('删除文件'+path);
break;
default:
break;
}
});
fs.watch('public', function (event, filename) {//fs 的文件监听虽然系统集成该模块,但是使用的时候感觉并不是很准
console.log('event is:' + event);
if (filename) {console.log('filename provided:' + filename);
} else {console.log('filename not provided');
}
});
});
其中,如果使用 chokidar 模块进行监听需要使用 npm 安装该模块
npm install chokidar
注意在该 js 文件启动的时候,chokidar 会将所有之前存在的文件都认为是‘添加文件’,出发 js 命令,所以要格外小心。
另外 chokidar.watch 函数还可以轻松的添加过滤器等设置,用法比 fs 要简单实用。
下面关于 Node.js 的内容你可能也喜欢:
在 Ubuntu 14.04/15.04 上安装配置 Node.js v4.0.0 http://www.linuxidc.com/Linux/2015-10/123951.htm
如何在 CentOS 7 安装 Node.js http://www.linuxidc.com/Linux/2015-02/113554.htm
Ubuntu 14.04 下搭建 Node.js 开发环境 http://www.linuxidc.com/Linux/2014-12/110983.htm
Ubunru 12.04 下 Node.js 开发环境的安装配置 http://www.linuxidc.com/Linux/2014-05/101418.htm
Node.Js 入门[PDF+ 相关代码] http://www.linuxidc.com/Linux/2013-06/85462.htm
Node.js 开发指南 高清 PDF 中文版 + 源码 http://www.linuxidc.com/Linux/2014-09/106494.htm
Node.js 入门开发指南中文版 http://www.linuxidc.com/Linux/2012-11/73363.htm
Ubuntu 编译安装 Node.js http://www.linuxidc.com/Linux/2013-10/91321.htm
Node.js 的详细介绍:请点这里
Node.js 的下载地址:请点这里
本文永久更新链接地址:http://www.linuxidc.com/Linux/2016-10/136494.htm