Node.js NodeJ如何处理高并发请求?

Node.js NodeJ如何处理高并发请求?,node.js,multithreading,concurrency,Node.js,Multithreading,Concurrency,我试图理解与基于线程的方法(如Servlet服务器)相比,nodejs如何实现更高的并发性 我已经知道在nodejs中,“除了代码之外,所有东西都并行运行”,而且libuv中有一个后端线程池来处理文件IO或数据库调用,这通常是瓶颈 所以我的问题是:如果nodejs使用线程池来处理数据库调用,那么在Tomcat也可以使用epoll/kqueue支持的NIO来实现高并发性的情况下,它如何能够服务于比诸如Tomcat这样的Servlet服务器更高的并发请求 例如,如果有一个100k并发请求进入,并且每

我试图理解与基于线程的方法(如Servlet服务器)相比,nodejs如何实现更高的并发性

我已经知道在nodejs中,“除了代码之外,所有东西都并行运行”,而且libuv中有一个后端线程池来处理文件IO或数据库调用,这通常是瓶颈

所以我的问题是:如果nodejs使用线程池来处理数据库调用,那么在Tomcat也可以使用epoll/kqueue支持的NIO来实现高并发性的情况下,它如何能够服务于比诸如Tomcat这样的Servlet服务器更高的并发请求

例如,如果有一个100k并发请求进入,并且每个请求都需要数据库操作,如果这些100k请求需要并发服务,那么使用NodeJ,我们仍然会创建100k线程,这可能会像Tomcat一样导致内存耗尽。是的,100k线程只是一种想象,因为(我知道)nodejs有一个固定的线程池,不同的操作在事件循环中排队,但使用Tomcat它以相同的方式处理事情——我们还可以在Tomcat中配置线程池大小,它还可以排队请求

或者,我说“nodejs使用libuv中的后端线程池来处理文件IO或数据库调用”是错误的吗?nodejs是否使用epoll/kqueue在没有单独线程的情况下处理数据库io

我在看书,但还是没有得到答案

如果nodejs使用线程池处理数据库调用

这是一个错误的假设。NodeJ通常使用网络与运行在不同进程或不同主机上的本地数据库进行通信。node.js中的网络不使用任何类型的线程-它使用事件驱动的I/O。数据库对线程的作用取决于数据库,独立于node.js,因为无论您使用哪种服务器环境,它都是相同的

node.js确实使用线程池进行本地磁盘访问,但大型应用程序通常使用数据库作为其磁盘访问的关键,这些应用程序在单独的进程中运行,并有自己的I/O优化来处理大量请求。一个给定的数据库如何实现它取决于该实现,但它不会对每个请求使用nodejs线程

我试图理解与基于线程的方法(如Servlet服务器)相比,nodejs如何实现更高的并发性

一般的概念是,node.js中正确编写的服务器应用程序对所有I/O使用异步I/O(可能除了仅在服务器启动期间运行的启动代码)。这意味着,当大多数请求等待某种类型的I/O时,它可以使用单个Javascript线程同时处理大量请求。如果同时处理大量请求,与使用操作系统线程相比,系统使用node.js的方式来完成这项工作效率更高。在node.js中,所有请求都是协同切换的,而在操作系统线程中,每个线程都有与之相关的操作系统开销,每个抢占式线程切换都有与之相关的操作系统和CPU开销

在node js中,活动请求之间没有先发制人的切换。一次只运行一个,它运行到完成或碰到一个非同步操作为止,在异步I/O操作完成之前,它没有其他事情要做。此时,JS引擎返回事件队列并选择一个事件(可能是其他请求之一)。与操作系统级线程相比,这种类型的协作切换速度更快、效率更高。有时,node.js开发人员必须使用异步I/O编写代码,以利用异步I/O,这会带来编程成本,因为它有一个学习曲线,以便能够熟练地编写具有正确错误处理的良好、干净的代码,并且也有一个调试代码的学习曲线

例如,如果有一个100k并发请求进入,并且每个请求都需要数据库操作,如果这些100k请求需要并发服务,那么使用NodeJ,我们仍然会创建100k线程,这可能会像Tomcat一样导致内存耗尽

不,您将不会创建100k线程。node.js数据库接口层,在node.js和另一个进程或另一台主机上的实际数据库代码之间进行接口,可以完全在node.js中编写(使用TCP网络与数据库对话)并且根本不引入新线程,或者它可能有一些本机代码,并使用少量线程来执行自己的本机代码操作,但很可能只有少量线程,甚至每个请求都没有一个线程

或者,我说“nodejs使用libuv中的后端线程池来处理文件IO或数据库调用”是错误的吗?nodejs是否使用epoll/kqueue在没有单独线程的情况下处理数据库io


对于文件I/O,是的,它使用libuv中的线程池。对于数据库调用,否-虽然细节完全取决于数据库实现,但通常每个数据库调用都没有线程。数据库通常处于另一个进程中,数据库的nodejs接口库要么直接使用nodejs TCP与数据库对话(不使用线程),要么它有自己的本机代码加载项与数据库对话,数据库可能使用少量线程进行工作,但通常不是每个请求一个线程。

感谢您的全面解释。当我谈到数据库调用时,我主要指的是来自客户端的调用,在这种情况下,我们的js代码充当DB客户端。是的,数据库调用最终是网络套接字io,所以我可以说来自客户端的数据库调用被底层io机制(如libuv包装的epoll/kqueue)覆盖了吗?否则,我无法想象在DB调用是异步的情况下不使用线程的情况。@davenkin-您的数据库注释让我感到困惑。通常,运行数据库的实际代码将位于node.js(和sometim)之外的单独进程中