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 的价值所在!
