Pourquoi Node.js est-il unitaire? [fermé]


256

Dans les serveurs Web basés sur PHP (ou Java / ASP.NET / Ruby), chaque demande client est instanciée sur un nouveau thread. Mais dans Node.js, tous les clients s'exécutent sur le même thread (ils peuvent même partager les mêmes variables!) Je comprends que les opérations d'E / S sont basées sur des événements afin de ne pas bloquer la boucle de thread principale.

Ce que je ne comprends pas, c'est POURQUOI l'auteur de Node l'a choisi pour être monothread? Cela rend les choses difficiles. Par exemple, je ne peux pas exécuter une fonction gourmande en processeur car elle bloque le thread principal (et les nouvelles demandes des clients sont bloquées), j'ai donc besoin de générer un processus (ce qui signifie que je dois créer un fichier JavaScript séparé et exécuter un autre processus de nœud sur il). Cependant, en PHP, les tâches intensives du processeur ne bloquent pas les autres clients car, comme je l'ai mentionné, chaque client est sur un thread différent. Quels sont ses avantages par rapport aux serveurs Web multi-threads?

Remarque: J'ai utilisé le clustering pour contourner ce problème, mais ce n'est pas joli.


12
J'ai récemment regardé une bonne vidéo (29 minutes) expliquant une partie de la théorie derrière Node. Je pense même que le gars parle de tâches gourmandes en CPU et brièvement comment les gérer: youtube.com/watch?v=L0pjVcIsU6A
— whirlwin

24
Vous le savez peut-être, mais pour être clair, Node.js n'est pas monothread. Votre code JavaScript s'exécute sur un seul thread, mais les opérations d'E / S et d'autres choses que les plugins peuvent faire s'exécutent à partir d'un pool de threads. Node.js vous offre une grande partie des avantages du multithreading sans avoir à traiter avec du code multithread. De plus, les contributeurs de Node.js n'ont pas choisi la nature monothread de JavaScript, les auteurs de JavaScript l'ont fait. Je ne vois pas comment JS pourrait fonctionner dans un contexte multithread, mais même s'il y en avait un, V8 n'est pas écrit de cette façon, ce que Node.js utilise comme moteur JavaScript.
— Brad

5
PHP est plus monothread que JavaScript. Vous pensez probablement à des modules serveurs comme FastCGI ou mod_php. Vous comparez donc en fait Node.js avec Apache, Nginx ou IIS, pas avec PHP, Java ou Ruby.
— Álvaro González

34
Le nœud n'est pas monothread. C'est une idée fausse populaire. Même simple node -e 'setTimeout(()=>{},1000);' & ps -T h $! | wc -l; kill $!affiche cinq threads sur mon système. La boucle d'événement principale est monothread (cela n'aurait pas beaucoup de sens si ce n'était pas le cas), mais Node est fortement multithread et vous pouvez écrire des applications monoprocessus multithread si vous le souhaitez. J'aimerais écrire une réponse complète à ce sujet, mais certaines personnes ont décidé de fermer votre question, donc je ne peux pas. Je vote pour le rouvrir. S'il obtient plus de votes et est rouvert, veuillez me mentionner dans le commentaire.
— rsp

2
@rsp merci pour votre commentaire, mais je voulais dire dans le fil principal non lié aux E / S. si vous faites quelque chose lié au processeur comme une grosse boucle for qui fait quelque chose, le serveur arrête de traiter les connexions. ce qui signifie que le serveur est inutilisable à l'époque. il nous reste donc à utiliser des hacks comme des clusters juste pour faire quelque chose de si simple au lieu de threader intrinsèquement chaque connexion comme le font la plupart des serveurs. jxcore.com a essayé de résoudre ce problème, mais il utilise ensuite des plugins de nœuds spéciaux / modifiés, ce qui le rend essentiellement inutilisable pour moi.
— foreyez

Réponses:


292

Node.js a été créé explicitement comme une expérience de traitement asynchrone. La théorie était que le traitement asynchrone sur un seul thread pouvait fournir plus de performances et d'évolutivité sous des charges Web typiques que l'implémentation basée sur un thread typique.

Et tu sais quoi? À mon avis, cette théorie a été confirmée. Une application node.js qui ne fait pas de tâches gourmandes en CPU peut exécuter des milliers de connexions simultanées de plus qu'Apache ou IIS ou d'autres serveurs basés sur des threads.

La nature asynchrone à un seul fil rend les choses compliquées. Mais pensez-vous honnêtement que c'est plus compliqué que d'enfiler? Une condition de course peut ruiner tout votre mois! Ou videz votre pool de threads en raison d'un paramètre quelque part et regardez votre temps de réponse lent à une analyse! Sans parler des blocages, des inversions de priorité et de toutes les autres girations associées au multithreading.

En fin de compte, je ne pense pas que ce soit universellement meilleur ou pire; c'est différent, et parfois c'est mieux et parfois non. Utilisez le bon outil pour le travail.


26
Mais les serveurs Web font généralement BEAUCOUP de choses intensives en CPU, ce n'est pas JUSTE de récupérer la base de données. Nous devons traiter ce que nous récupérons et faire beaucoup de logique métier avant de le servir au client.
— foreyez

22
Il suffit donc de faire apparaître des travailleurs, eh bien! C'est toute l'affaire avec Node.js. Les choses lourdes peuvent s'exécuter dans un autre processus, et vous traitez cela entraîne un rappel léger.
— MaiaVictor

7
Le problème avec cela est qu'il y a un processus au niveau du système d'exploitation en cours d'exécution par travailleur. Vous les verrez en utilisant la commande "ps". Cela signifie donc potentiellement des milliers de processus en cours d'exécution sur la machine à la fois - c'est fou!
— foreyez

9
@foreyez, Vous n'avez pas besoin d'un processus par utilisateur. Vous avez le choix dans la façon dont vous répartissez la charge. De plus, tout le monde ne fait pas une tonne de choses gourmandes en CPU. Node est un outil pour un travail ... peut-être pas votre travail, mais de nombreux types d'emplois.
— Brad

15
En fait, j'aimerais que @foreyez sauvegarde cette déclaration selon laquelle "les serveurs Web utilisent généralement BEAUCOUP (sic) de choses gourmandes en CPU". D'après mon expérience, ce n'est pas le cas. Ou peut-être que ma définition de «intensif cpu» diffère de la sienne. La conversion des données de produit en interface utilisateur ne nécessite pas beaucoup de CPU, ni le calcul de commandes ou similaires. La plupart du Web est assez transactionnel. Les choses gourmandes en CPU sont des choses comme la conversion de vidéos, la conversion de formats d'image, etc. Cela est dû en grande partie aux E / S de fichiers qui, en fait, le nœud fonctionne plutôt bien. Et facilite le déchargement vers un autre processus dédié à la conversion.
— Paul

63

Le problème avec le modèle «un thread par demande» pour un serveur est qu'ils ne s'adaptent pas bien pour plusieurs scénarios par rapport au modèle de thread de boucle d'événements.

En règle générale, dans les scénarios intensifs d'E / S, les demandes passent la plupart du temps à attendre la fin des E / S. Pendant ce temps, dans le modèle "un thread par requête", les ressources liées au thread (comme la mémoire) sont inutilisées et la mémoire est le facteur limitant. Dans le modèle de boucle d'événement, le thread de boucle sélectionne l'événement suivant (E / S terminé) à gérer. Le thread est donc toujours occupé (si vous le programmez correctement bien sûr).

Le modèle de boucle d'événement, comme toutes les nouvelles choses, semble brillant et la solution à tous les problèmes, mais le modèle à utiliser dépendra du scénario que vous devez aborder. Si vous avez un scénario d'E / S intensif (comme un proxy), le modèle de base d'événements régnera, tandis qu'un scénario gourmand en CPU avec un faible nombre de processus simultanés fonctionnera mieux avec le modèle basé sur les threads.

Dans le monde réel, la plupart des scénarios seront un peu au milieu. Vous devrez équilibrer le besoin réel d'évolutivité avec la complexité du développement pour trouver l'architecture correcte (par exemple, disposer d'un frontend de base d'événements qui délègue au backend pour les tâches gourmandes en CPU. Le front end utilisera peu de ressources en attente de la tâche) Comme pour tout système distribué, il faut un certain effort pour le faire fonctionner.

Si vous recherchez la balle d'argent qui s'adaptera à n'importe quel scénario sans aucun effort, vous vous retrouverez avec une balle dans votre pied.


8
Node.js est limité au traitement événementiel uniquement en raison du manque de prise en charge du multithreading v8. Eh bien, le langage javascript lui-même n'a pas les fonctionnalités nécessaires, donc toute implémentation finira par être délicate. C'est le principal coupable de Node.js, à mon avis. Dans d'autres langues, vous pouvez choisir ce que vous voulez. Ou un hybride des deux modèles, comme java NIO.
— FrameGrace

2
@Kazaag, les serveurs Web modernes font maintenir un threadpool. Ils ne génèrent pas simplement un nouveau fil par chargement de page. Ce sont les anciens serveurs Web.
— Pacerier

1
@Pacerier Je n'ai jamais dit qu'un nouveau thread est généré, mais chaque thread est alloué à une demande jusqu'à ce que la demande soit terminée.
— Kazaag

2
@Kazaag Ce n'est certainement pas une règle générale que "chaque thread est alloué à une demande jusqu'à ce que la demande soit terminée". C'est-à-dire en .Net (y compris le traitement des requêtes HTTP), on peut et doit utiliser la programmation asynchrone (basée sur les tâches) et cela libérera les threads en attendant que les E / S et autres opérations asynchrones se terminent. Cela s'applique également à la programmation de haut niveau, c'est-à-dire aux contrôleurs MVC / API. Donc, en pratique, il pourrait y avoir 20 requêtes HTTP en attente mais un seul thread actif.
— user3285954

29

Pour faire court, le nœud s'inspire de la V8, qui est un filetage interne unique. Il existe des moyens de contourner les contraintes des tâches gourmandes en ressources processeur.

À un moment donné (0,7), les auteurs ont essayé d'introduire des isolats comme moyen d'implémenter plusieurs threads de calcul, mais ont finalement été supprimés: https://groups.google.com/forum/#!msg/nodejs/zLzuo292hX0/F7gqfUiKi2sJ


Avez-vous plus d'informations sur cet "isolat"?
— Pacerier
En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.