Nest 项目目前可以链接云服务的 Mysql 服务
那么如果直接在云服务上部署 Nest 项目链接本地 Mysql 服务理应比 Serverless 性能好才对,遂我们采用 ab 压测一下,看看哪个部署更有性价比
目前有云服务器两台,一台上部署 Nest 项目和 Mysql 服务 (A 服务器), 一台安装 ab 用来测试 (B 服务器), 同时使用 serverless 部署的云函数通过内网链接该云服务器的 Mysql 服务
# 当前环境配置
- A 服务器: 1 核 2GB 1Mbps 带宽 Linux Centos7.6
- B 服务器: 4 核 4GB 8Mbps 带宽 Linux Centos7.6
- Serverless 云函数配置: 500 并发 / 分钟
# 在 B 服务器安装 ab 压测工具
$ yum install httpd-tools -y |
# A 服务器部署项目
# nginx 配置域名访问 Nest 项目
nginx 配置反向代理访问 9002 端口 (该服务器 9000 端口被 php 占用)
server { | |
listen 80; | |
server_name manager.aplus.pub; | |
location / { | |
proxy_pass http://127.0.0.1:9002; | |
proxy_set_header Host $host:80; | |
proxy_set_header X-Real-IP $remote_addr; | |
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; | |
proxy_set_header Upgrade $http_upgrade; | |
proxy_set_header Connection "upgrade"; | |
proxy_connect_timeout 7d; | |
proxy_send_timeout 7d; | |
proxy_read_timeout 7d; | |
} | |
} |
# 使用 PM2 部署 Nest 项目
使用 pm2 部署 nest 项目为了监控占用机器性能等参数
$ pm2 start ./dist/main.js | |
$ pm2 monit |
# 压测实验开始
# 实验前本地测试
项目部署好了,先在本地测试一下访问速度
就以 GET /api/options
作为今天的测试接口
先使用浏览器访问 http://manager.aplus.pub/api/options
多次测试下来接口访问时间在 40-45 毫秒内,算是非常快了
接下来访问采用 Serverless 部署的项目 https://service-mlmh4ts7-1252902543.sh.apigw.tencentcs.com/api/options
多次测试下来接口访问时间在 70-100 毫秒之间,比直接在云服务器上部署的要慢了 1 倍!
这里怀疑是因为直接在云服务部署的服务直接访问到本地的 mysql 服务器,而云函数则要通过网络访问,虽然是内网,但是延迟加网络传输造成的时间差也是很多的.
再次测试 GET /api/hello
接口
使用浏览器访问 http://manager.aplus.pub/api/hello
响应时间依旧在 40-45 毫秒
使用浏览器访问 https://service-mlmh4ts7-1252902543.sh.apigw.tencentcs.com/api/hello
响应时间最后稳定在 60-80 毫秒,差距不是太大了,响应时间大概是直接访问云服务器的 2 倍左右,性能尚可
# ab 压测
为了进一步验证使用 Serverless 的性能,使用 ab 压测工具来测试一下
首先对 A 云服务器进行压测 GET /api/options
首先来个 200 并发,2000 个请求
[root@VM-12-5-centos /]# ab -n 2000 -c 200 http://manager.aplus.pub/api/options | |
This is ApacheBench, Version 2.3 <$Revision: 1430300 $> | |
Copyright 1996 Adam Twiss, Zeus Technology Ltd, http://www.zeustech.net/ | |
Licensed to The Apache Software Foundation, http://www.apache.org/ | |
Benchmarking manager.aplus.pub (be patient) | |
Completed 200 requests | |
Completed 400 requests | |
Completed 600 requests | |
Completed 800 requests | |
Completed 1000 requests | |
Completed 1200 requests | |
Completed 1400 requests | |
Completed 1600 requests | |
Completed 1800 requests | |
Completed 2000 requests | |
Finished 2000 requests | |
Server Software: nginx/1.19.6 | |
Server Hostname: manager.aplus.pub | |
Server Port: 80 | |
Document Path: /api/options | |
Document Length: 102 bytes | |
Concurrency Level: 200 | |
Time taken for tests: 14.776 seconds | |
Complete requests: 2000 | |
Failed requests: 0 | |
Write errors: 0 | |
Total transferred: 664000 bytes | |
HTML transferred: 204000 bytes | |
Requests per second: 135.36 [#/sec] (mean) | |
Time per request: 1477.567 [ms] (mean) | |
Time per request: 7.388 [ms] (mean, across all concurrent requests) | |
Transfer rate: 43.89 [Kbytes/sec] received | |
Connection Times (ms) | |
min mean[+/-sd] median max | |
Connect: 3 19 121.8 4 1007 | |
Processing: 6 826 1426.8 403 13370 | |
Waiting: 6 815 1431.8 395 13370 | |
Total: 9 845 1428.8 420 13373 | |
Percentage of the requests served within a certain time (ms) | |
50% 420 | |
66% 628 | |
75% 664 | |
80% 928 | |
90% 1915 | |
95% 3337 | |
98% 6372 | |
99% 6715 | |
100% 13373 (longest request) |
在压测时,A 服务器单核 cpu 占用率一直在 70% 左右,可以认为该服务器的一个高占用了
结果 QPS 达到 135/s,80% 的用户响应时间在 1S 以下,性能尚可,毕竟只有 1 核 2G,1MB 带宽的配置,相信带宽更多的话 QPS 还会更高
接下来对 Serverless 部署的云函数进行压测,也是 200 并发,2000 个请求
[root@VM-12-5-centos /]# ab -n 2000 -c 200 https://service-mlmh4ts7-1252902543.sh.apigw.tencentcs.com/api/options | |
This is ApacheBench, Version 2.3 <$Revision: 1430300 $> | |
Copyright 1996 Adam Twiss, Zeus Technology Ltd, http://www.zeustech.net/ | |
Licensed to The Apache Software Foundation, http://www.apache.org/ | |
Benchmarking service-mlmh4ts7-1252902543.sh.apigw.tencentcs.com (be patient) | |
Completed 200 requests | |
Completed 400 requests | |
Completed 600 requests | |
Completed 800 requests | |
Completed 1000 requests | |
Completed 1200 requests | |
Completed 1400 requests | |
Completed 1600 requests | |
Completed 1800 requests | |
Completed 2000 requests | |
Finished 2000 requests | |
Server Software: | |
Server Hostname: service-mlmh4ts7-1252902543.sh.apigw.tencentcs.com | |
Server Port: 443 | |
SSL/TLS Protocol: TLSv1.2,ECDHE-RSA-AES128-GCM-SHA256,2048,128 | |
Document Path: /api/options | |
Document Length: 102 bytes | |
Concurrency Level: 200 | |
Time taken for tests: 15.280 seconds | |
Complete requests: 2000 | |
Failed requests: 607 | |
(Connect: 0, Receive: 0, Length: 607, Exceptions: 0) | |
Write errors: 0 | |
Non-2xx responses: 607 | |
Total transferred: 2020156 bytes | |
HTML transferred: 173043 bytes | |
Requests per second: 130.89 [#/sec] (mean) | |
Time per request: 1527.950 [ms] (mean) | |
Time per request: 7.640 [ms] (mean, across all concurrent requests) | |
Transfer rate: 129.11 [Kbytes/sec] received | |
Connection Times (ms) | |
min mean[+/-sd] median max | |
Connect: 12 46 42.9 29 261 | |
Processing: 4 896 2909.6 29 15081 | |
Waiting: 4 892 2910.1 28 15081 | |
Total: 18 943 2927.3 64 15184 | |
Percentage of the requests served within a certain time (ms) | |
50% 64 | |
66% 89 | |
75% 106 | |
80% 110 | |
90% 912 | |
95% 6300 | |
98% 15151 | |
99% 15154 | |
100% 15184 (longest request) |
这里发现个问题
Failed requests:607
, 错误链接数竟然达到 607 个,感觉很不正常,遂查看 Serverless 云函数日志,发现有一部分请求出现了错误
Error: Too many connections | |
at Packet.asError (/var/user/node_modules/mysql2/lib/packets/packet.js:728:17) | |
at ClientHandshake.execute (/var/user/node_modules/mysql2/lib/commands/command.js:29:26) | |
at PoolConnection.handlePacket (/var/user/node_modules/mysql2/lib/connection.js:456:32) | |
at PacketParser.onPacket (/var/user/node_modules/mysql2/lib/connection.js:85:12) | |
at PacketParser.executeStart (/var/user/node_modules/mysql2/lib/packet_parser.js:75:16) | |
at Socket.<anonymous> (/var/user/node_modules/mysql2/lib/connection.js:92:25) | |
at Socket.emit (node:events:390:28) | |
at addChunk (node:internal/streams/readable:315:12) | |
at readableAddChunk (node:internal/streams/readable:289:9) | |
at Socket.Readable.push (node:internal/streams/readable:228:10) |
这是 Mysql 连接数达到上限了,查看 Mysql 的最大连接数只有 151, 改为 5000 继续进行压测实验
mysql> show variables like 'max_connections'; | |
+-----------------+-------+ | |
| Variable_name | Value | | |
+-----------------+-------+ | |
| max_connections | 151 | | |
+-----------------+-------+ | |
1 row in set (0.03 sec) | |
mysql> set global max_connections=5000; | |
Query OK, 0 rows affected (0.00 sec) | |
mysql> exit |
修改完 Mysql 的最大连接数限制之后继续进行压测发现还有 500 多 Failed requests
, 怀疑是访问 Serverless 云函数时请求过多过快超过了它本身的并发限制,查看日志发现很多 StatusCode 429
的情况,果然是超出了限制
因为我的 Serverless 云函数是最便宜的套餐,只有 500 并发 / 分钟,我们之前的测试已经达到了 130 / 秒,肯定大大超过了限制
打开云函数控制台,发现有个设置 请求多并发
请求并发优势
在 IO 密集型场景中,如 Websocket 长连接业务,可减少计费执行时长,节省费用。
多个请求并发在同一个实例中可复用数据库连接池,减缓下游服务压力。
请求并发密集时,多个请求只需要一个实例进行处理,无需拉起多个实例,从而降低实例冷启动几率,降低响应延迟。
设置为静态并发 50 之后,再来压测试一试
[root@VM-12-5-centos /]# ab -n 2000 -c 200 https://service-mlmh4ts7-1252902543.sh.apigw.tencentcs.com/api/options | |
This is ApacheBench, Version 2.3 <$Revision: 1430300 $> | |
Copyright 1996 Adam Twiss, Zeus Technology Ltd, http://www.zeustech.net/ | |
Licensed to The Apache Software Foundation, http://www.apache.org/ | |
Benchmarking service-mlmh4ts7-1252902543.sh.apigw.tencentcs.com (be patient) | |
Completed 200 requests | |
Completed 400 requests | |
Completed 600 requests | |
Completed 800 requests | |
Completed 1000 requests | |
Completed 1200 requests | |
Completed 1400 requests | |
Completed 1600 requests | |
Completed 1800 requests | |
Completed 2000 requests | |
Finished 2000 requests | |
Server Software: | |
Server Hostname: service-mlmh4ts7-1252902543.sh.apigw.tencentcs.com | |
Server Port: 443 | |
SSL/TLS Protocol: TLSv1.2,ECDHE-RSA-AES128-GCM-SHA256,2048,128 | |
Document Path: /api/options | |
Document Length: 102 bytes | |
Concurrency Level: 200 | |
Time taken for tests: 9.619 seconds | |
Complete requests: 2000 | |
Failed requests: 0 | |
Write errors: 0 | |
Total transferred: 2076000 bytes | |
HTML transferred: 204000 bytes | |
Requests per second: 207.93 [#/sec] (mean) | |
Time per request: 961.884 [ms] (mean) | |
Time per request: 4.809 [ms] (mean, across all concurrent requests) | |
Transfer rate: 210.77 [Kbytes/sec] received | |
Connection Times (ms) | |
min mean[+/-sd] median max | |
Connect: 15 26 27.9 17 116 | |
Processing: 18 568 1569.1 117 9427 | |
Waiting: 18 567 1569.1 117 9427 | |
Total: 34 594 1592.0 135 9538 | |
Percentage of the requests served within a certain time (ms) | |
50% 135 | |
66% 162 | |
75% 189 | |
80% 205 | |
90% 325 | |
95% 6101 | |
98% 6368 | |
99% 6437 | |
100% 9538 (longest request) |
这次没有 Failed requests
了
而且 90% 的请求在 400 毫秒内就完成了,QPS 达到了 207 / 秒,比在 A 服务器部署的服务快了 1 倍左右
# 性价比评测
同样是 200 个并发 2000 个请求,A 服务器普遍响应比较慢,CPU 占用率达到 70% 左右,如果再多一点并发则服务器可能宕机
云函数通过参数调试与测试之后也完成了 200 并发 2000 请求的测试,成绩比 A 服务器更好,而且不用考虑 CPU 占用率问题,只需考虑并发配额
这里云函数并发配额是最少的情况,每月仅需要 9.9
元,而 1 核 2G1MB 的云服务器一个月费用则为 121
元
如果项目较为复杂并且占用 CPU 更多的情况,无疑采用 Serverless 部署更为经济
如果每天的用户很多,那么把数据库放在云服务器上,省去购买 RDS 的费用,则每月只需要 100 多元则可以达到以前 4 核乃至 8 核服务器才能承载的并发压力,我认为这就是采用 Serverless 的价值所在!