我试图了解与基于线程的方法(如Servlet服务器)相比,nodejs如何实现更高的并发性。
我已经知道,在nodejs中,“除了代码之外,所有东西都是并行运行的”,而且在libuv中还有一个后端线程池来处理文件IO或数据库调用,这通常是瓶颈。
下面是我的问题:如果nodejs使用线程池来处理数据库调用,那么它如何处理比Tomcat这样的Servlet服务器更高的并发请求,因为Tomcat也可以使用由epoll/kqueue支持的NIO来实现高并发性?
例如,如果有一个100 k并发请求传入,并且每个请求都需要数据库操作,如果这100 k请求要同时处理,那么使用nodejs,我们仍然会创建100 k线程,这可能会像Tomcat那样导致内存耗尽。是的,100 k线程只是一种想象,因为(我知道) nodejs有一个固定的线程池,不同的操作在事件循环中排队,但是使用Tomcat它处理事情的方式是相同的--我们还可以在Tomcat中配置线程池大小,它还可以对请求进行队列。
或者,我说"nodejs使用libuv中的后端线程池来处理文件IO或数据库调用“是错误的吗?nodejs是否使用epoll/kqueue来处理没有单独线程的数据库io?
我在读this similar question,但仍然没有得到答案。
发布于 2017-07-16 08:18:02
如果nodejs使用线程池来处理数据库调用
这是个错误的假设。nodejs通常使用网络与运行在不同进程或不同主机上的本地数据库进行对话。node.js中的网络不使用任何类型的线程--它使用事件驱动的I/O。数据库对线程所做的事情取决于数据库,并且独立于node.js,因为无论您使用哪种服务器环境,它都是相同的。
node.js确实使用线程池进行本地磁盘访问,但是大型应用程序通常使用数据库作为磁盘访问的关键,这些数据库运行在单独的进程中,并具有自己的I/O优化以处理大量请求。给定的数据库是如何实现的,但是它不会在每个请求中使用nodejs线程。
我试图了解与基于线程的方法(如Servlet服务器)相比,nodejs如何实现更高的并发性。
一般的概念是,在node.js中正确编写的服务器应用程序对所有I/O都使用异步I/O (可能只在服务器启动期间运行的启动代码除外)。这意味着它可以在运行中同时拥有许多请求,只有一个Javascript线程,而大多数请求都在等待某种类型的I/O。如果同时有大量的请求在运行中,系统可以更有效地执行单个线程的node.js方式,其中所有请求都是协作切换的,而使用OS线程时,每个线程都有与其相关的OS开销,而每个抢占式线程开关都有与其相关的OS和CPU开销。
在节点-js中,在活动请求之间没有先发制人的切换.一次只运行一次,直到它完成或命中一个异步操作,在异步I/O操作完成之前没有什么可做的。此时,JS引擎返回到事件队列并选择一个事件(可能用于其他请求之一)。与OS级线程相比,这种类型的协作切换更快,效率更高.有时编程成本是因为node.js开发人员必须使用异步I/O来编写代码,这样才能利用它的学习曲线,以便能够熟练地编写优秀、干净的代码,并进行适当的错误处理,并具有调试它的学习曲线。
例如,如果有一个100 k并发请求传入,并且每个请求都需要数据库操作,如果这100 k请求要同时处理,那么使用nodejs,我们仍然会创建100 k线程,这可能会像Tomcat那样导致内存耗尽。
不,您将不会创建100 k线程。在另一个进程中或在另一个主机上,在node.js和实际数据库代码之间进行接口的node.js数据库接口层可以完全用node.js编写(使用TCP网络与数据库对话),并且完全不引入新的线程,或者它可能有一些本机代码并使用少量线程来执行它自己的本机代码操作,但是它可能是少量线程,甚至每个请求都没有接近一个线程。
或者,我说"nodejs使用libuv中的后端线程池来处理文件IO或数据库调用“是错误的吗?nodejs是否使用epoll/kqueue来处理没有单独线程的数据库io?
对于文件I/O,是的,它使用了libuv中的线程池。对于数据库调用,虽然细节完全取决于数据库实现,但通常每个数据库调用不存在线程。数据库通常处于另一个进程中,DB的nodejs接口库要么直接使用nodejs TCP与数据库对话(数据库不使用线程),要么它有自己的本机代码附加项,与数据库对话,数据库可能使用少量线程来工作,但通常不是每个请求使用一个线程。
https://stackoverflow.com/questions/45126321
复制相似问题