Nodejs事件循环

nodejs体系结构内部是否存在两个事件循环?

  • libev / libuv
  • v8 javascript事件循环

在I / O请求上,节点是否将请求排队到libeio,而libeio又通过使用libev的事件通知数据的可用性,最后这些事件由v8事件循环使用回调来处理?

基本上,libev和libeio如何集成到nodejs架构中?

是否有任何文档可以清楚地了解nodejs内部体系结构?

斯丁2020/04/07 11:34:34

pbkdf2函数具有JavaScript实现,但实际上将所有工作委托给C ++端。

env->SetMethod(target, "pbkdf2", PBKDF2);
  env->SetMethod(target, "generateKeyPairRSA", GenerateKeyPairRSA);
  env->SetMethod(target, "generateKeyPairDSA", GenerateKeyPairDSA);
  env->SetMethod(target, "generateKeyPairEC", GenerateKeyPairEC);
  NODE_DEFINE_CONSTANT(target, OPENSSL_EC_NAMED_CURVE);
  NODE_DEFINE_CONSTANT(target, OPENSSL_EC_EXPLICIT_CURVE);
  NODE_DEFINE_CONSTANT(target, kKeyEncodingPKCS1);
  NODE_DEFINE_CONSTANT(target, kKeyEncodingPKCS8);
  NODE_DEFINE_CONSTANT(target, kKeyEncodingSPKI);
  NODE_DEFINE_CONSTANT(target, kKeyEncodingSEC1);
  NODE_DEFINE_CONSTANT(target, kKeyFormatDER);
  NODE_DEFINE_CONSTANT(target, kKeyFormatPEM);
  NODE_DEFINE_CONSTANT(target, kKeyTypeSecret);
  NODE_DEFINE_CONSTANT(target, kKeyTypePublic);
  NODE_DEFINE_CONSTANT(target, kKeyTypePrivate);
  env->SetMethod(target, "randomBytes", RandomBytes);
  env->SetMethodNoSideEffect(target, "timingSafeEqual", TimingSafeEqual);
  env->SetMethodNoSideEffect(target, "getSSLCiphers", GetSSLCiphers);
  env->SetMethodNoSideEffect(target, "getCiphers", GetCiphers);
  env->SetMethodNoSideEffect(target, "getHashes", GetHashes);
  env->SetMethodNoSideEffect(target, "getCurves", GetCurves);
  env->SetMethod(target, "publicEncrypt",
                 PublicKeyCipher::Cipher<PublicKeyCipher::kPublic,
                                         EVP_PKEY_encrypt_init,
                                         EVP_PKEY_encrypt>);
  env->SetMethod(target, "privateDecrypt",
                 PublicKeyCipher::Cipher<PublicKeyCipher::kPrivate,
                                         EVP_PKEY_decrypt_init,
                                         EVP_PKEY_decrypt>);
  env->SetMethod(target, "privateEncrypt",
                 PublicKeyCipher::Cipher<PublicKeyCipher::kPrivate,
                                         EVP_PKEY_sign_init,
                                         EVP_PKEY_sign>);
  env->SetMethod(target, "publicDecrypt",
                 PublicKeyCipher::Cipher<PublicKeyCipher::kPublic,
                                         EVP_PKEY_verify_recover_init,
                                         EVP_PKEY_verify_recover>);

资源:https : //github.com/nodejs/node/blob/master/src/node_crypto.cc

Libuv模块还有另一个责任,与标准库中的某些非常特殊的功能有关。

对于某些标准库函数调用,Node C ++端和Libuv决定完全在事件循环之外进行昂贵的计算。

Instead they make use of something called a thread pool, the thread pool is a series of four threads that can be used for running computationally expensive tasks such as the pbkdf2 function.

By default Libuv creates 4 threads in this thread pool.

In addition to the threads used in the event loop there are four other threads that can be used to offload expensive calculations that need to occur inside our application.

Many of the functions included in the Node standard library automatically make use of this thread pool. The pbkdf2 function being one of them.

The presence of this thread pool is very significant.

So Node is not truly single threaded, because there are other threads that Node uses for doing some computationally expensive tasks.

If the event pool was responsible for doing the computationally expensive task, then our Node application could do nothing else.

Our CPU runs all the instructions inside a thread one by one.

By using the thread pool we can do other things inside an event loop while calculations are occurring.

逆天猿2020/04/07 11:34:34

作为一个JavaScript初学者,我也有同样的疑问,NodeJS是否包含2个事件循环?经过长期的研究和与V8贡献者的讨论,我得到了以下概念。

  • 事件循环是JavaScript编程模型的基本抽象概念。因此,V8引擎为事件循环提供了默认的实现,嵌入器(浏览器,节点)可以替换或扩展你们可以在这里找到事件循环的V8默认实现
  • 在NodeJS中,仅存在一个事件循环,该循环由节点运行时提供。V8默认事件循环实现已被NodeJS事件循环实现取代
卡卡西Near2020/04/07 11:34:34

我一直在亲自阅读node.js&v8的源代码。

当我试图了解node.js架构以编写本机模块时,遇到了类似的问题。

我在这里发布的内容是我对node.js的理解,这也可能会偏离轨道。

  1. Libev是事件循环,它实际上在node.js内部运行,以执行简单的事件循环操作。它最初是为* nix系统编写的。Libev为运行该流程提供了一个简单但经过优化的事件循环。您可以在此处阅读有关libev的更多信息

  2. LibEio是一个用于异步执行输入输出的库。它处理文件描述符,数据处理程序,套接字等。您可以在此处了解更多信息

  3. LibUv是libeio,libev,c-ares(对于DNS)和iocp(对于Windows异步-io)顶部的抽象层。LibUv执行,维护和管理事件池中的所有io和事件。(如果是libeio线程池)。您应该查看Ryan Dahl关于libUv 的教程这将使您对libUv本身的工作方式更加了解,然后您将了解node.js在libuv和v8之上的工作方式。

要仅了解javascript事件循环,您应该考虑观看这些视频

要了解libeio如何与node.js一起使用以创建异步模块,您应该看到此示例

基本上,在node.js内部发生的事情是v8循环运行并处理所有javascript部分以及C ++模块(当它们在主线程中运行时(根据官方文档,node.js本身是单线程的))。当在主线程之外时,libev和libeio在线程池中对其进行处理,并且libev提供与主循环的交互。因此,据我了解,node.js具有1个永久事件循环:这就是v8事件循环。为了处理C ++异步任务,它使用一个线程池[通过libeio&libev]。

例如:

eio_custom(Task,FLAG,AfterTask,Eio_REQUEST);

在所有模块中出现的通常是Task在线程池中调用该函数完成后,它将AfterTask在主线程中调用该函数。Eio_REQUEST请求处理程序可以是结构/对象,其目的是在线程池和主线程之间提供通信。

阿飞2020/04/07 11:34:34

libuv仅提供一个事件循环,V8只是一个JS运行时引擎。

番长樱梅2020/04/07 11:34:34

NodeJs体系结构中有一个事件循环。

Node.js事件循环模型

节点应用程序以单线程事件驱动模型运行。但是,Node在后台实现线程池,以便可以执行工作。

Node.js将工作添加到事件队列,然后让一个线程运行事件循环将其拾取。事件循环获取事件队列中的头一个项目,执行它,然后获取下一个项目。

当执行寿命更长或阻塞I / O的代码时,与其直接调用该函数,不如直接将函数添加到事件队列中,并在函数完成后将执行回调。执行完Node.js事件队列上的所有事件后,Node.js应用程序终止。

当我们的应用程序功能在I / O上阻塞时,事件循环开始引发问题。

Node.js使用事件回调来避免等待阻塞I / O。因此,任何执行阻塞I / O的请求都在后台的不同线程上执行。

当从事件队列中检索到阻止I / O的事件时,Node.js从线程池中检索线程,然后在该线程池中而不是在主事件循环线程上执行该函数。这样可以防止阻塞的I / O阻止事件队列中的其余事件。