Node.js nodejs通过将I/O委托给内核来隐式生成线程。这与每个请求生成一个线程的服务器有何不同

Node.js nodejs通过将I/O委托给内核来隐式生成线程。这与每个请求生成一个线程的服务器有何不同,node.js,multithreading,io,kernel,Node.js,Multithreading,Io,Kernel,跟进我之前两个问题的想法: 我最近一直在调查nodejs。它被标榜为“单线程”,这在一定程度上是正确的,因为所有的JS都在一个线程上运行,但从我在后台读到的内容来看,node通过将I/O任务委托给内核来实现这一点,这样它就不必等待响应 我很难理解的是,这与每个请求显式创建线程的范例有什么不同 有人能解释一下深度上的差异吗?如果node为每个I/O请求创建一个线程,这将是正确的。但是,当然,它不会这样做。它有一个I/O引擎,能够理解在每个平台上执行I/O的最佳方式 nodejs对您隐藏的不

跟进我之前两个问题的想法:

我最近一直在调查nodejs。它被标榜为“单线程”,这在一定程度上是正确的,因为所有的JS都在一个线程上运行,但从我在后台读到的内容来看,node通过将I/O任务委托给内核来实现这一点,这样它就不必等待响应

我很难理解的是,这与每个请求显式创建线程的范例有什么不同


有人能解释一下深度上的差异吗?

如果node为每个I/O请求创建一个线程,这将是正确的。但是,当然,它不会这样做。它有一个I/O引擎,能够理解在每个平台上执行I/O的最佳方式

nodejs对您隐藏的不是某个简单的实现,其中调度实体等待每个请求完成,而是一个复杂的实现,它了解在实现它的每个平台上执行I/O的最佳方式

更新:

如果这两种方法都需要内核进行I/O,那么它们不是都会为每个请求创建一个内核线程吗

不需要。有很多方法可以将内核用于I/O,而不需要每个请求都有一个内核线程。不同平台的情况不同。Windows有IOCP。Linux有epoll。等等

如果nodejs以某种方式使用固定数量的线程并对I/O操作进行排队,那么这不是比每个请求一个线程慢吗

不,由于各种原因,它通常要快得多,这取决于每个平台的具体情况。以下是一些优点:

  • 当大量I/O同时完成时,您可以避免“雷鸣般的群”。相反,您可以只唤醒可以同时有效运行的线程数
  • 您可以避免需要大量的上下文切换来执行所有不同的线程。相反,每个线程可以在完成后处理完成
  • 对于每个I/O操作,您不必将每个线程放在等待队列中。相反,您可以对线程组使用单个等待队列
  • 只是想让你知道它有多重要,考虑一下使用I/O线程和在Linux上使用EPOLL的区别。如果每个I/O使用一个线程,这意味着每个I/O操作都需要一个线程将自身置于等待队列中,该线程将被阻止,该线程将被解锁,该线程将发生上下文切换,该线程将自身从等待队列中移除


    相比之下,使用epoll,单个线程可以为任意数量的I/O完成提供服务,而无需对每个I/O的等待队列进行重新调度、添加或删除。类似地,线程可以发出大量I/O请求,而无需重新调度。这种差异是巨大的。

    如果节点为每个I/O请求创建一个线程,这将是真实的。但是,当然,它不会这样做。它有一个I/O引擎,能够理解在每个平台上执行I/O的最佳方式

    nodejs对您隐藏的不是某个简单的实现,其中调度实体等待每个请求完成,而是一个复杂的实现,它了解在实现它的每个平台上执行I/O的最佳方式

    更新:

    如果这两种方法都需要内核进行I/O,那么它们不是都会为每个请求创建一个内核线程吗

    不需要。有很多方法可以将内核用于I/O,而不需要每个请求都有一个内核线程。不同平台的情况不同。Windows有IOCP。Linux有epoll。等等

    如果nodejs以某种方式使用固定数量的线程并对I/O操作进行排队,那么这不是比每个请求一个线程慢吗

    不,由于各种原因,它通常要快得多,这取决于每个平台的具体情况。以下是一些优点:

  • 当大量I/O同时完成时,您可以避免“雷鸣般的群”。相反,您可以只唤醒可以同时有效运行的线程数
  • 您可以避免需要大量的上下文切换来执行所有不同的线程。相反,每个线程可以在完成后处理完成
  • 对于每个I/O操作,您不必将每个线程放在等待队列中。相反,您可以对线程组使用单个等待队列
  • 只是想让你知道它有多重要,考虑一下使用I/O线程和在Linux上使用EPOLL的区别。如果每个I/O使用一个线程,这意味着每个I/O操作都需要一个线程将自身置于等待队列中,该线程将被阻止,该线程将被解锁,该线程将发生上下文切换,该线程将自身从等待队列中移除


    相比之下,使用epoll,单个线程可以为任意数量的I/O完成提供服务,而无需对每个I/O的等待队列进行重新调度、添加或删除。类似地,线程可以发出大量I/O请求,而无需重新调度。这种差异是巨大的。

    @AR7老实说,就您的问题而言,我认为最有用的答案是“节点可以在每个平台上做任何工作,每个I/O线程在大多数平台上都不是最好的”。也就是说,好处是有一个抽象层,避免了程序员必须知道如何最好地在他希望代码运行的每个平台上进行I/O。类似的层是libevent和boost ASIO。非常感谢。我想我现在需要读更多关于epoll和其他你提到的东西。我不知道它们的存在。有了这些工具,你就不需要了。这是他们的优势@AR7老实说,就您的问题而言,我认为最有用的答案是“节点可以在每个平台上做任何工作,每个I/O线程在大多数平台上都不是最好的”。也就是说,好处在于