我在一个小团队中开发一个单页应用程序,该应用程序严重依赖通过 WebSockets 进行的低延迟查询。后端运行在 Node.js + Redis 上。它需要支持数百到数千个并发连接,并且需要在 50 - 100 毫秒(在客户端良好的网络条件下)内处理请求。我们对服务器这部分的初始实现相当满意,它的性能符合预期。
我们还需要通过 HTTP 提供大量静态文件。这些请求对时间不敏感。由于需要大量存储,出于成本原因,我们希望选择 HDD 阵列而不是 SSD。
缓慢的磁盘 I/O 是否存在降低 Node.js 应用程序其余部分(WebSocket 部分仅使用内存数据库)性能的风险,或者它是否会严格影响 HTTP/静态文件服务部分服务器的?就我的理解而言,具有异步特性的 Node.js 非常适合这种情况,因为它允许 WebSockets 模块在 HTTP 模块等待磁盘读/写时正常处理查询?
也许大量“等待服务”的 HTTP 请求会以某种方式阻塞服务器(毕竟,它们需要存储在某个地方并且如果读/写可用则可能无法自由轮询)并且我们需要考虑使用单独的 Node.js 进程来提供静态文件,甚至完全使用单独的专用服务器?
我能想到以下几点:
- “等待服务”的 HTTP 请求将用完有限数量的可用并发 TCP 连接
- “等待服务”的 HTTP 请求也将耗尽一些 RAM
- 系统文件应该驻留在不会忙于提供静态文件的磁盘上
我们目前还不能在现实世界中测试这种情况,所以我非常感谢能听到任何有类似经历的人的意见。这可能需要我们重新思考架构,这是我们希望尽早发现的东西。
最佳答案
简短回答:是 存在巨大风险:p
https://nodejs.org/api/fs.html#fs_threadpool_usage
Threadpool Usage#
All file system APIs except fs.FSWatcher() and those that are explicitly synchronous use libuv's threadpool, which can have surprising and negative performance implications for some applications. See the UV_THREADPOOL_SIZE documentation for more information.
http://docs.libuv.org/en/v1.x/design.html#file-i-o
UV 线程池由系统线程支持,因此缩放配置文件将与应用程序的其余部分截然不同。在我看来,这并不一定是更大的风险,只是......不同的硬数据将有助于查看您的应用程序的扩展配置文件。
我认为一般最佳做法是尽可能卸载静态文件服务。在您的应用程序前面设置一个能够快速提供静态文件 (nginx) 的代理可能会有所帮助(不是因为它解决了阻止文件系统读取的核心问题,而是因为它可能提供更统一/可预测的性能或扩展,因为它只需要管理服务文件,而您的应用程序需要在用户和服务文件之间进行上下文切换。我个人会研究您关于使用单独进程或 CDN 的建议,以尝试从中完全删除静态文件服务你的申请。
关于node.js - 慢速磁盘 I/O 是否会降低 Node.js 应用程序其余部分的性能?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/54086468/