Boucle D'Événements Nodejs

y a-t-il en interne Deux Boucles d'événements dans l'architecture nodejs?

  • libev / libuv
  • V8 boucle d'événement javascript

sur une requête D'E/S, le noeud fait-il la file d'attente de la requête à libeio qui, à son tour, notifie la disponibilité des données via des événements en utilisant libev et, finalement, ces événements sont traités par la boucle d'événements v8 en utilisant des callbacks?

essentiellement, comment libev et libeio sont-ils intégrés dans l'architecture de nodejs?

y a-t-il de la documentation disponible pour donner une image claire de l'architecture interne de nodejs?

122
demandé sur Tamil 2012-05-21 10:46:32

5 réponses

j'ai personnellement lu le code source du noeud.js & v8.

je suis entré dans un problème similaire comme vous quand j'ai essayé de comprendre noeud.architecture js pour écrire des modules natifs.

ce que je poste ici est ma compréhension du noeud.js et ça pourrait être un peu hors de propos aussi.

  1. Libev est la boucle d'événement qui tourne réellement en interne dans le noeud.js pour effectuer des opérations simples de boucle d'événement. C'est écrit à l'origine pour *nix systems. Libev fournit une boucle d'événement simple mais optimisée pour le processus à exécuter. Vous pouvez en savoir plus sur libev ici .

  2. LibEio est une bibliothèque pour effectuer la sortie d'entrée de façon asynchrone. Il gère les descripteurs de fichier, gestionnaires de données, prises etc. Vous pouvez lire plus à ce sujet ici ici .

  3. LibUv est une couche d'abstraction sur le dessus de libeio , libev, c-ares ( pour DNS ) et iocp (pour windows asynchrone-io). LibUv exécute, maintient et gère tous les io et événements du pool d'événements. (dans le cas de libeio threadpool). Vous devriez consulter le tutoriel de Ryan Dahl sur libUv. Cela commencera à faire plus de sens pour vous sur la façon dont libUv fonctionne lui-même et alors vous comprendrez comment nœud.js travaille sur le dessus de libuv et v8.

pour comprendre seulement la boucle d'événement javascript, vous devriez envisager de regarder ces vidéos

pour voir comment libeio est utilisé avec node.js pour créer des modules async, vous devez voir cet exemple .

essentiellement ce qui se passe à l'intérieur du noeud.js est que V8 loop exécute et gère toutes les parties javascript ainsi que les modules C++ [lorsqu'ils sont exécutés dans un thread principal ( comme par noeud de documentation officiel.js lui-même est un simple threaded) ]. Quand à l'extérieur de la le thread principal, libev et libeio le gèrent dans le pool de threads et libev fournissent l'interaction avec la boucle principale. Donc, à partir de ma compréhension, de nœud.js a une boucle d'événement permanente: c'est la boucle d'événement v8. Pour gérer les tâches asynchrones C++, il utilise un threadpool [via libeio & libev ].

par exemple:

eio_custom(Task,FLAG,AfterTask,Eio_REQUEST);

qui apparaît dans tous les modules appelle habituellement la fonction Task dans le threadpool. Quand il est complet, il appelle le AfterTask fonction dans le thread principal. Tandis que Eio_REQUEST est le gestionnaire de requêtes qui peut être une structure / objet dont le but est de fournir une communication entre le threadpool et le thread principal.

155
répondu ShrekOverflow 2018-07-11 17:33:56

ressemble à certaines des entités discutées (par exemple: libev etc.) ont perdu leur pertinence, en raison du fait que cela fait un certain temps, mais je pense que la question a encore un grand potentiel.

laissez-moi essayer d'expliquer le fonctionnement du modèle piloté par les événements à l'aide d'un exemple abstrait, dans un environnement UNIX abstrait, dans le contexte de Node, à partir d'aujourd'hui.

perspective du programme:

  • Moteur de Script démarre l'exécution du script.
  • chaque fois qu'une opération liée au CPU est rencontrée, elle est exécutée en ligne (machine réelle), dans son intégralité.
  • chaque fois qu'une opération liée à une entrée/sortie est rencontrée, la demande, et son gestionnaire d'exécution sont enregistrés avec une "machine d'événement" (machine virtuelle)
  • répétez les opérations de la même manière jusqu'à la fin du script. Opération liée au CPU-exécution en ligne, I / O liée ceux, demande à la machine, comme ci-dessus.
  • lorsque l'entrée/sortie est terminée, les auditeurs sont rappelés.

la machine événementielle ci-dessus est appelée libuv AKA event loop framework. Nœud utilise cette bibliothèque à mettre en œuvre sa programmation événementielle modèle.

Nod's perspective:

  • ont un thread pour héberger l'exécution.
  • ramasser l'utilisateur script.
  • compiler en natif [leverage v8 ]
  • chargez le binaire, et sautez dans le point d'entrée.
  • le code compilé exécute les activités liées au CPU en ligne, en utilisant des primitives de programmation.
  • de nombreux codes d'E / S et de minuterie ont des wraps natifs. Par exemple, réseau I / O.
  • ainsi les appels d'E/S sont acheminés du script vers les ponts C++, avec la poignée d'E/S et l'achèvement handler est passé en argument.
  • le code natif exerce la boucle libuv. Il acquiert la boucle, interroge un événement de bas niveau qui représente l'E/S, et un wrapper de callback natif dans la structure de boucle de la libuv.
  • le code natif retourne au script - aucune entrée / sortie n'a lieu en ce moment!
  • Les Items
  • ci-dessus sont répétés plusieurs fois, jusqu'à ce que tous les codes non-I/O soient exécutés, et que tous les codes d'e/s soient enregistrés comme libuv.
  • enfin, quand il ne reste plus rien à exécuter dans le système, le noeud passe le contrôle à la
  • libuv entre en action, il récupère tous les événements enregistrés, interroge le système d'exploitation pour obtenir leur opérabilité.
  • ceux qui sont sont prêts pour l'entrée/sortie en mode non-blocage, sont ramassés, l'entrée/sortie effectuée, et leurs callbacks émis. L'un après l'autre.
  • Ceux qui ne sont pas encore prêts (par exemple une lecture de socket, pour laquelle l'autre point final n'a pas encore écrit quoi que ce soit) continuera d'être explorée avec L'OS jusqu'à ce qu'ils soient disponibles.
  • La boucle interne gère une augmentation de la minuterie. Lorsque l'application demande un callback différé(tel que setTimeout), cette valeur de minuterie interne est utilisée pour calculer le bon moment pour lancer le callback.

alors que la plupart des fonctionnalités sont couvertes de cette manière, certaines (versions async) des opérations de fichiers sont effectuées à l'aide de threads supplémentaires, bien intégrés dans la libuv. Tandis que les opérations d'E/S réseau peuvent attendre dans l'attente d'un événement externe tel que l'autre terminal répondant avec des données, etc. les opérations de fichier ont besoin de travail à partir du noeud lui-même. Par exemple, si vous ouvrez un fichier et attendez que le fd soit prêt avec les données, cela n'arrivera pas, car personne ne lit réellement! En même temps, si vous lisez à partir du fichier inline dans le fil principal, il peut potentiellement bloquer d'autres activités dans le programme, et peut rendre les problèmes visibles, car les opérations de fichiers sont très lentes par rapport aux activités liées au cpu. Ainsi, les threads de travail internes (configurables par la variable d'environnement UV_THREADPOOL_SIZE) sont employés pour fonctionner sur des fichiers, tandis que l'abstraction basée sur un événement fonctionne intacte, du point de vue du programme.

Espérons que cette aide.

17
répondu Gireesh Punathil 2016-04-26 08:34:01

Une Introduction à libuv

le noeud .js projet a commencé en 2009 comme un environnement JavaScript découplé du navigateur. En utilisant le V8 de Google et le libev de Marc Lehmann , noeud.js a combiné un modèle de I / O – evented – avec un langage qui était bien adapté au style de programmation; en raison de la façon dont il avait été façonné par les navigateurs. En tant que nœud.js a grandi en popularité, il était important de le faire fonctionner sur Windows, mais libev ne fonctionnait que sous Unix. L'équivalent Windows des mécanismes de notification des événements du noyau comme kqueue ou (e)poll est IOCP. libuv était une abstraction autour de libev ou IOCP en fonction de la plateforme, fournissant aux utilisateurs une API basée sur libev. Dans le noeud-v0.9.La version 0 de libuv libev a été retirée .

aussi une image qui décrit la boucle D'événement dans le noeud.js par @ BusyRich


mise à jour 05/09/2017

pour ce noeud doc .js boucle d'événement ,

Le diagramme suivant montre un aperçu simplifié de la boucle d'événement de l'ordre des opérations.

┌───────────────────────┐ ┌─>│ timers │ │ └──────────┬────────────┘ │ ┌──────────┴────────────┐ │ │ I/O callbacks │ │ └──────────┬────────────┘ │ ┌──────────┴────────────┐ │ │ idle, prepare │ │ └──────────┬────────────┘ ┌───────────────┐ │ ┌──────────┴────────────┐ │ incoming: │ │ │ poll │<─────┤ connections, │ │ └──────────┬────────────┘ │ data, etc. │ │ ┌──────────┴────────────┐ └───────────────┘ │ │ check │ │ └──────────┬────────────┘ │ ┌──────────┴────────────┐ └──┤ close callbacks │ └───────────────────────┘

note: chaque case sera appelée "phase" de la boucle d'événements.

Aperçu Des Phases

  • timers : cette phase exécute les callbacks programmés par setTimeout() et setInterval() .
  • I / O callbacks : exécute presque tous les callbacks à l'exception de
  • close callbacks , ceux programmés par timers, et setImmediate() . inactif, préparer: utilisé uniquement en interne.
  • poll : récupérez les nouveaux événements d'e/s; le noeud bloquera ici le cas échéant.
  • vérifier : setImmediate() rappels sont invoqués ici.
  • fermer " callbacks : par exemple socket.on('close', ...) .

entre chaque passage de la boucle d'événement, noeud.js vérifie si elle attend une entrée/sortie asynchrone ou chronomètre et se ferme proprement s'il n'y en a pas.

14
répondu zangw 2017-05-09 05:55:12

il y a une boucle d'événement dans L'Architecture NodeJs.

Node.js Boucle d'Événement de Modèle

Nœud d'exécution des applications dans un seul thread event-driven modèle. Cependant, Node implémente un pool de threads en arrière-plan pour que le travail puisse être effectué.

Node.js ajoute du travail à une file d'attente d'événements et a ensuite un seul thread qui exécute une boucle d'événements. La boucle event saisit l'élément supérieur de la file d'attente event, l'exécute, puis attrape le prochain objet.

lors de l'exécution de code qui est de plus longue durée ou a des entrées/sorties de blocage, au lieu d'appeler la fonction directement, il ajoute la fonction à la file d'événements avec un rappel qui sera exécuté après la fonction complète. Quand tous les événements sur le noeud.js event queue ont été exécutés, le noeud.l'application js se termine.

la boucle d'événement commence à rencontrer des problèmes lorsque nos fonctions d'application bloquent l'entrée / sortie.

Node.js utilise des callbacks d'événements pour éviter d'avoir à attendre le blocage des entrées/sorties.par conséquent, toutes les requêtes qui effectuent le blocage des entrées/sorties sont effectuées sur un thread différent en arrière-plan.

Lorsqu'un événement qui bloque l'entrée/sortie est récupéré à partir de la file D'attente d'événements, noeud.js récupère un thread du pool de threads, et exécute la fonction là au lieu du thread de la boucle d'événement principale. Cela empêche l'E/S de bloquer le reste des événements dans la file d'attente des événements.

10
répondu Peter Hauge 2015-10-27 15:48:48

il n'y a qu'une boucle d'événement fournie par libuv, V8 n'est qu'un moteur JS.

8
répondu Warren Zhou 2016-01-06 05:41:30