我想了解與基於線程的方法(如Servlet服務器)相比,nodejs如何實現更高的併發性。NodeJS如何處理高併發請求?
我已經知道在nodejs中「除了你的代碼以外所有東西都是並行運行的」,並且在libuv中還有一個後端線程池來處理通常是瓶頸的文件IO或數據庫調用。
所以,這裏是我的問題:如果nodejs使用線程池來處理數據庫調用,那麼它如何能夠服務更高的併發請求,比Tomcat等Servlet服務器更好,因爲Tomcat也可以使用由epoll/kqueue支持的NIO來實現高併發性?例如,如果有100k個併發請求進入並且每個請求都需要數據庫操作,如果這些100k請求需要同時服務,那麼使用nodejs,我們最終還是會創建100k個線程,這可能會導致內存耗盡,正如Tomcat所做的那樣。是的,100k線程只是一個想象,因爲(我知道)nodejs有一個固定的線程池,不同的操作在事件循環中排隊,但是使用Tomcat它以相同的方式處理事情 - 我們也可以配置線程池在Tomcat中的大小,它也排隊請求。
或者,我錯了,說「nodejs使用libuv中的後端線程池來處理文件IO或數據庫調用」? nodejs是否使用epoll/kqueue來處理數據庫io而沒有單獨的線程?
我在讀this similar question,但仍然沒有得到答案。
感謝您的全面解釋。當我談到數據庫調用時,主要是指來自客戶端的調用,在這種情況下,我們的js代碼充當數據庫客戶端。是的,數據庫調用最終是網絡套接字io,所以我可以說,在數據庫調用來自客戶端的數據庫調用覆蓋的底層io機制,如epoll/kqueue包裝libuv?否則我無法想象在數據庫調用異步時沒有使用線程的場景。 – davenkin
@davenkin - 您的數據庫評論令我困惑。通常,運行數據庫的實際代碼將與node.js(有時在另一個主機上)處於不同的進程中。當node.js中的Javascript向客戶端調用數據庫時,它將準備與其他進程或其他主機的某些通信。該通信通常不會使用node.js線程,因爲它通常是非阻塞TCP並且node.js不會爲每個TCP連接使用額外的線程。 – jfriend00
@davenkin - 給你一個想法。如果我編寫node.js應用程序來向100個不同的主機發起http API調用,以便所有100個請求同時處於運行狀態並等待響應,但不會在node.js中使用任何其他線程。現在,如果node.js中的數據庫驅動程序具有自己的本機代碼,那麼它可以在其自己的本機代碼中執行任何它想要的操作。有些人可能會使用一些本地線程來跟蹤請求 - 我不知道。但是,根本不需要node.js模型。 – jfriend00