为了完整性,我从 github 存储库复制了您的测试结果:
Python
Java Spring Webflux
Node Native Mongo
所以,有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 上,