Node+Express+MongoDB Native Client 性能问题

2024-01-28

我正在使用 MongoDB 测试 Node.js (ExpressJS/Fastify)、Python (Flask) 和 Java(带有 webflux 的 Spring Boot)的性能。我将所有这些示例应用程序相继托管在同一台服务器上,因此所有服务都具有相同的环境。我使用了两种不同的工具 Load-test 和 Apache Benchmark cli 来测量性能。

Node 示例的所有代码都在此存储库中:基准测试-nodejs-mongodb https://github.com/ashwanigarg/benchmark-nodejs-mongodb

我使用这两种工具对请求数量和并发请求的各种组合执行了多次测试

阿帕奇基准测试总计 1K 请求和 100 个并发

ab -k -n 1000 -c 100 http://{{服务器}}:7102/api/case1/1000

负载测试总共 100 个请求和 10 个并发

负载测试 http://{{server}}:7102/api/case1/1000 -n 100 -c 10

结果也附在 Github 存储库中,与其他技术相比,NodeJS 感到震惊,要么请求在测试之间中断,要么完成测试花费了太多时间。

服务器配置:不专注但

CPU:酷睿 i7 第 8 代 12 核 内存:32GB 存储:2TB硬盘 网络带宽:30Mbps

蒙戈服务器不同网络上的不同节点通过互联网连接

请帮助我详细了解这个问题。我确实了解事件循环在 Node.js 中的工作原理,但这个问题无法识别。

转载

Setup:

  • Mongodb Atlas M30
  • 同一区域的 AWS c4xlarge

Results:

无故障

Document Path:          /api/case1/1000
Document Length:        37 bytes

Concurrency Level:      100
Time taken for tests:   33.915 seconds
Complete requests:      1000
Failed requests:        0
Keep-Alive requests:    1000
Total transferred:      265000 bytes
HTML transferred:       37000 bytes
Requests per second:    29.49 [#/sec] (mean)
Time per request:       3391.491 [ms] (mean)
Time per request:       33.915 [ms] (mean, across all concurrent requests)
Transfer rate:          7.63 [Kbytes/sec] received

Connection Times (ms)
              min  mean[+/-sd] median   max
Connect:        0    1   3.1      0      12
Processing:   194 3299 1263.1   3019    8976
Waiting:      190 3299 1263.1   3019    8976
Total:        195 3300 1264.0   3019    8976

较大负载下的长度失效:

Document Path:          /api/case1/5000
Document Length:        37 bytes

Concurrency Level:      100
Time taken for tests:   176.851 seconds
Complete requests:      1000
Failed requests:        22
   (Connect: 0, Receive: 0, Length: 22, Exceptions: 0)
Keep-Alive requests:    978
Total transferred:      259170 bytes
HTML transferred:       36186 bytes
Requests per second:    5.65 [#/sec] (mean)
Time per request:       17685.149 [ms] (mean)
Time per request:       176.851 [ms] (mean, across all concurrent requests)
Transfer rate:          1.43 [Kbytes/sec] received

Connection Times (ms)
              min  mean[+/-sd] median   max
Connect:        0    0   0.9      0       4
Processing:   654 17081 5544.0  16660   37911
Waiting:      650 17323 5290.9  16925   37911
Total:        654 17081 5544.1  16660   37911

为了完整性,我从 github 存储库复制了您的测试结果:

Python enter image description here

Java Spring Webflux image

Node Native Mongo image

所以,有3个问题。

上传带宽

ab -k -n 1000 -c 100 http://{{server}}:7102/api/case1/1000通过网络上传大约 700 MB 的 bson 数据。

30Mb/s = 小于 4MB/s,仅需要至少 100 秒即可以最高速度传输数据。如果您在家进行测试,消费级 ISP 并不总是为您提供最大速度,尤其是上传速度。

对于服务器来说,这通常不是一个问题,特别是当应用程序托管在数据库附近时。我在问题本身的同一区域中放置了托管在 aws 上的应用程序和 mongo 服务器的一些统计信息。

失败的请求

我所能注意到的只是“长度”失败 - 实际收到的字节数不匹配。

它只发生在最后一批(100 个请求),因为 Nodejs 集群模块中的一些竞争条件 - 主服务器在工作线程之前关闭与工作线程的连接http.response.end()将数据写入套接字。在 TCP 级别上,它看起来像这样:

经过 46 秒的挣扎,没有收到 HTTP 200 OK,只有 FIN、ACK。

通过使用 nginx 反向代理 + 手动启动的 Nodejs Worker 数量而不是内置集群模块,或者让 k8s 进行资源管理,这个问题很容易解决。

简而言之 - 不要使用 Nodejs 集群模块来执行网络密集型任务。

Timeout

这是ab超时。当网络是限制因素并且您将有效负载增加 x5 时 - 将默认超时(30 秒)增加至少 x4:

ab -s 120 -k -n 1000 -c 100 http://{{server}}:7102/api/case1/5000

我确信您在其他测试中也这样做了,因为您报告了 java 的 99 秒/请求和 python 的 81 秒/请求。

结论

Nodejs 并没有什么令人震惊的坏处。集群中存在一些错误,但这是一个非常小众的用例,而且解决它很简单。

火焰图:

大部分 CPU 时间用于序列化/反序列化 bson 并将数据发送到流,其中约 10% 花费在 CPU 最密集的 bson serialiseInto 上,

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

Node+Express+MongoDB Native Client 性能问题 的相关文章

随机推荐