Node.js应该用于密集处理吗?

dav*_*wil 9 javascript webserver scalability mongodb node.js

假设我正在构建一个3层网站,后端有Mongo DB,浏览器中有一些非常轻量级的javascript(假设只是对表单进行验证,可能还有几个奇特的控件可以触发一些AJAX请求).

我需要为"中间"层选择一种技术(我们可以将其划分为子层,但这个细节不是重点,只是整体技术选择),我想要处理来自DB,并将其呈现为一些HTML,我将其推送到浏览器.一个相当典型的瘦客户端Web架构.

我的安全选择是在Java中实现这个中间层,使用像Jongo这样的库来与Mongo DB交谈,也许杰克逊可以编组/解组JSON,以便在他们发出AJAX请求时与我的花哨控件交谈.还有一些Java模板框架用于在服务器上呈现我的HTML.

但是,我真的很感兴趣的是将所有这些抛出窗口并将Node.js用于此中间层,原因如下:

  • 我喜欢javascript(好的部分),让我们说这个应用程序的业务逻辑比Java更具表现力.

  • 到处都是javascript.在堆栈中的任何地方工作时,无需在语言之间切换,实际上也不需要在OO和功能范例之间切换.层之间没有转换管道,JSON在本地支持.

  • 我可以在客户端和服务器上重用验证逻辑.

  • 如果将来我决定在浏览器中进行HTML呈现客户端,我可以重用现有模板,例如Backbone,只需极少的重构/重新测试工作.

如果你现在和Node一样,以上所有内容都会显而易见.所以我应该选择Node吧?

但是......这就是我失败的地方:因为我们都知道Node基于单线程异步I/O Web服务器模型.这对于我在数据请求服务方面的可扩展性和性能非常有用,但我的业务逻辑呢?我的模板渲染怎么样?这个东西不会对单线程上的所有请求造成巨大的瓶颈吗?

我想到了两个明显的解决方案,但它们都不正确:

  1. 将"阻塞"业务逻辑保留在那里,只使用一组Node实例和一个负载均衡器,以真正的并行方式为请求提供服务.好的,那么为什么Node首先不是多线程的呢?或者这总是想法,保持简单愚蠢并避免基本情况下多线程复杂性的可能性,如果需要多核处理能力,程序员可以在此基础上进行额外的设置工作吗?

  2. 保留单个节点实例,并通过调用在其他多线程应用服务器上运行的业务逻辑的某些java实现来保持其不阻塞.好吧,这个选项完全取消了我列出的使用Node的所有专业人员(实际上它增加了仅使用Java的复杂性),除了可能获得的对数据库的CRUD请求的性能和可伸缩性.

这最终导致了我的问题 - 我是否遗漏了Node难题的一些重要部分,我是否完全错了我的事实,或者Node是否不适合在服务器上处理业务逻辑?换句话说,Node是否有用于坐在数据库上并以比I/O阻塞的其他实现更高性能和可扩展的方式为许多CRUD请求提供服务?您必须在以下某个层甚至客户端执行所有业务逻辑,以维持任何合理的性能和可伸缩性级别?

考虑到Node上的所有嗡嗡声,我宁愿希望它带来更多的表格.我更乐意相信!

sla*_*pon 7

在任何给定的系统上,你有N cpus可用(1-64,或者恰好是N).在任何CPU密集型应用程序中,您将遇到N cpu的吞吐量.通过添加超过N个线程/进程/任何东西,没有神奇的方法可以解决这个问题.您的代码必须更高效,或者您需要更多的CPU.更多线程无济于事.

关于多CPU性能的一个鲜为人知的事实是,如果您需要同时运行N + 1个 CPU密集型操作,则每个CPU的吞吐量会下降很多.CPU耗尽的过程往往会在放弃之前长时间挂在CPU上,导致其他任务非常糟糕.在大多数情况下,它阻止了I/O和随之而来的任务切换,这使得现代操作系统多任务工作和它一样有效.如果我们的日常常见任务中有更多是受CPU限制的,我们会发现我们的机器中需要的CPU比现在多得多.

Node.js为服务器方带来效率的好处是对每个线程的彻底使用.理想情况下,您最终会减少任务切换.这不是一个巨大的胜利,但是N个线程异步处理N*C连接将比在相同数量的CPU上运行的N*C阻塞线程具有性能优势.但是CPU的底线仍然是相同的:如果你有超过N个值的实际CPU工作要做,你会感到有些痛苦.

我最后一次查看Node.js API时,有一种方法可以启动一个服务器,每个CPU有一个监听器和一个工作线程.如果你能做到这一点,我会倾向于使用Node.js提供一些警告:

  • Javascript-无处不在的方法为您带来了一些简单性.对于复杂的事情,我会担心异步编程风格使事情变得更难而不是更容易.
  • 与其他语言/平台选择相比,Node.js中的模板处理和其他CPU密集型任务的速度并不慢.
  • 数据库驱动程序是可靠的.

我可以看到一个缺点:

  • 如果线程崩溃,则会丢失该线程所服务的所有连接.

最后,请记住,程序员时间通常比服务器或带宽更昂贵.