Javascript Nodejs事件循环

Javascript Nodejs事件循环,javascript,node.js,event-loop,libev,Javascript,Node.js,Event Loop,Libev,nodejs架构中是否有两个内部事件循环 libev/libuv v8 javascript事件循环 在I/O请求上,节点是否将请求排队到libeio,然后libeio通过使用libev的事件通知数据的可用性,最后这些事件由使用回调的v8事件循环处理 基本上,libev和libeio是如何集成到nodejs架构中的 是否有任何文档可以清晰地描述NodeJ的内部架构?我一直在阅读node.js和v8的源代码 当我试图理解node.js体系结构以编写本机模块时,我遇到了与您类似的问题 我在这里发

nodejs架构中是否有两个内部事件循环

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

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


是否有任何文档可以清晰地描述NodeJ的内部架构?

我一直在阅读node.js和v8的源代码

当我试图理解node.js体系结构以编写本机模块时,我遇到了与您类似的问题

我在这里发布的是我对node.js的理解,这可能有点偏离正轨

  • 是实际在node.js内部运行以执行简单事件循环操作的事件循环。它最初是为*nix系统编写的。Libev为流程提供了一个简单但优化的事件循环。你可以阅读更多关于利贝夫的信息

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

  • 是libeio、libev、c-ares(用于DNS)和iocp(用于windows异步io)之上的抽象层。LibUv执行、维护和管理事件池中的所有io和事件。(对于libeio线程池)。你应该在libUv上查看。这将使您对libUv本身的工作方式有更多的了解,然后您将了解node.js如何在libUv和v8之上工作

  • 为了理解JavaScript事件循环,你应该考虑看这些视频

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

    基本上,No.js中发生的是V8循环运行并处理所有JavaScript部分以及C++模块(当它们在主线程中运行时(如官方文档No.JS本身是单线程))。当在主线程之外时,libev和libeio在线程池中处理它,libev提供与主循环的交互。根据我的理解,node.js有一个永久的事件循环:那就是v8事件循环。为了处理C++异步任务,它使用线程池[通过LyBeo和LyBev]。 例如:

    eio_custom(Task,FLAG,AfterTask,Eio_REQUEST);
    

    它出现在所有模块中,通常调用线程池中的函数
    Task
    。完成后,它调用主线程中的
    后任务
    函数。然而,
    Eio\u REQUEST
    是请求处理程序,它可以是一个结构/对象,其目的是提供线程池和主线程之间的通信。

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

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

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

    当执行寿命较长或具有阻塞I/O的代码时,它不直接调用函数,而是将函数与回调一起添加到事件队列中,回调将在函数完成后执行。当Node.js事件队列上的所有事件都已执行时,Node.js应用程序将终止

    当应用程序函数阻塞I/O时,事件循环开始引发问题

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

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

    该项目始于2009年,是一个与浏览器分离的JavaScript环境。使用Google和Marc Lehmann的node.js,它将I/O模型(evented)与一种非常适合编程风格的语言相结合;由于浏览器对它的塑造方式。随着node.js越来越流行,让它在Windows上工作很重要,但libev只在Unix上运行。类似于kqueue或(e)poll的内核事件通知机制的Windows等价物是IOCP。libuv是围绕libev或IOCP的抽象,取决于平台,为用户提供了基于libev的API。在node-v0.9.0版本的libuv中

    还有一张图片描述了Node.js中的事件循环@


    更新日期2017年9月5日

    根据这份文件

    下图显示了事件循环操作顺序的简化概述

       ┌───────────────────────┐
    ┌─>│        timers         │
    │  └──────────┬────────────┘
    │  ┌──────────┴────────────┐
    │  │     I/O callbacks     │
    │  └──────────┬────────────┘
    │  ┌──────────┴────────────┐
    │  │     idle, prepare     │
    │  └──────────┬────────────┘      ┌───────────────┐
    │  ┌──────────┴────────────┐      │   incoming:   │
    │  │         poll          │<─────┤  connections, │
    │  └──────────┬────────────┘      │   data, etc.  │
    │  ┌──────────┴────────────┐      └───────────────┘
    │  │        check          │
    │  └──────────┬────────────┘
    │  ┌──────────┴────────────┐
    └──┤    close callbacks    │
       └───────────────────────┘
    
    ┌───────────────────────┐
    ┌─>│        计时器│
    │  └──────────┬────────────┘
    │  ┌──────────┴────────────┐
    │  │     I/O回调│
    │  └──────────┬────────────┘
    │  ┌──────────┴────────────┐
    │  │     空闲,准备│
    │  └──────────┬────────────┘      ┌───────────────┐
    │  ┌──────────┴────────────┐      │   进来的:│
    
    │ │ 投票│ libuv只提供了一个事件循环,V8只是一个JS运行时引擎。

    看起来像讨论的一些实体(e
    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>);