Cet article vous présente une brève discussion sur la haute concurrence et les clusters distribués dans node.js. Il a une certaine valeur de référence. Les amis dans le besoin peuvent s'y référer.
Avant d'expliquer pourquoi le nœud peut atteindre une simultanéité élevée, vous pourriez aussi bien jeter un œil à plusieurs autres fonctionnalités du nœud :
Clarifions d'abord un concept, à savoir : le nœud est 单线程
, ce qui est le même que les caractéristiques de JavaScript dans le navigateur, et dans le nœud, le fil principal JavaScript est différent des autres les threads (tels que les threads d'E/S) ne peuvent pas partager l'état.
L'avantage du thread unique est :
Il n'est pas nécessaire de prêter attention au problème de synchronisation d'état entre les threads comme le multi-threading
Il n'y a pas de surcharge causée par le changement de thread
Aucun blocage n'existe
Bien sûr, le threading unique présente également de nombreux inconvénients :
Impossible d'utiliser pleinement le processeur multicœur
Un grand nombre de calculs occupant le processeur entraîneront un blocage des applications (c'est-à-dire ne conviennent pas au processeur- intensif)
Des erreurs entraîneront la fermeture de l'ensemble de l'application
Cependant, il semble aujourd'hui que ces inconvénients ne soient plus un problème ou aient été résolu de manière appropriée :
(1) Créer un processus ou une instance de subdivision
Concernant le premier problème, la solution la plus simple consiste à utiliser le module central ou le cluster child_process : child_process et l'application combinée net. Nous pouvons utiliser pleinement chaque cœur en créant plusieurs processus sur un serveur multicœur (généralement en utilisant une opération fork), mais nous devons résoudre les problèmes de communication inter-processus.
Une autre solution consiste à diviser la machine physique en plusieurs machines virtuelles monocœur et à utiliser des outils tels que pm2 pour gérer plusieurs machines virtuelles afin de former une architecture de cluster afin d'exécuter efficacement les services requis. Je ne discuterai pas ici de la communication (synchronisation des statuts) entre les machines, et je l'expliquerai en détail dans l'architecture distribuée Node ci-dessous.
(2) Rotation des tranches de temps
Concernant le deuxième point, après en avoir discuté avec mes amis, je pense que l'on peut utiliser la rotation des tranches de temps pour simuler le multi-threading sur un seul thread et réduire de manière appropriée blocage des applications. Feeling (même si cette méthode ne fera pas vraiment gagner du temps comme le multi-threading)
(3) Équilibrage de charge, surveillance/isolation des pixels morts
Quant au troisième point, mes amis et Nous avons également discuté du fait que le principal problème est que le nœud est différent de JAVA et que la logique qu'il implémente est principalement asynchrone.
Cela fait que le nœud ne peut pas utiliser try/catch pour détecter et contourner les erreurs aussi facilement que JAVA, car il est impossible de déterminer quand la tâche asynchrone renverra l'exception. Dans un environnement monothread, le fait de ne pas contourner les erreurs signifie que l'application se fermera et que l'intervalle entre le redémarrage et la récupération entraînera des interruptions de service que nous ne souhaitons pas voir.
Bien sûr, maintenant que les ressources du serveur sont abondantes, nous pouvons utiliser des outils tels que pm2 ou nginx pour déterminer dynamiquement l'état du service. Isolez le serveur de pixels défectueux lorsqu'une erreur de service se produit, transférez la demande au serveur normal et redémarrez le serveur de pixels défectueux pour continuer à fournir des services. Cela fait également partie de l'architecture distribuée de Node.
Vous vous demandez peut-être, puisque le nœud est monothread et que tous les événements sont traités sur un seul thread, cela ne devrait-il pas être très inefficace et contraire à une concurrence élevée ?
Au contraire, les performances du nœud sont très élevées. L'une des raisons est que le nœud possède la fonctionnalité 异步I/O
Chaque fois qu'une demande d'E/S se produit, le nœud fournit un thread d'E/S à la demande. Ensuite, le nœud ne se souciera pas du processus d'opération d'E/S, mais continuera à exécuter l'événement sur le thread principal. Il ne doit être traité que lorsque la requête renvoie le rappel. C'est-à-dire que le nœud permet de gagner beaucoup de temps en attendant les requêtes.
C'est également l'une des raisons importantes pour lesquelles le nœud prend en charge une concurrence élevée.
En fait, non seulement les opérations d'E/S, la plupart des opérations du nœud sont asynchrones. effectué d'une manière. C'est comme un organisateur : il n'a pas besoin de tout faire personnellement, il doit seulement dire aux membres comment fonctionner correctement, accepter les commentaires et gérer les étapes clés, afin que toute l'équipe puisse fonctionner efficacement.
Vous voudrez peut-être demander à nouveau : comment le nœud sait-il que la demande a renvoyé un rappel et quand doit-il gérer ces rappels ?
La réponse est une autre fonctionnalité du nœud : 事务驱动
, c'est-à-dire que le thread principal exécute le programme en déclenchant la boucle d'événements
C'est une autre façon pour le nœud de prendre en charge une concurrence élevée . Raisons importantes
Schéma de la boucle d'événement dans l'environnement de nœud :
┌───────────────────────┐ ┌─>│ timers │<p><strong>phase d'interrogation : </strong></p><p>Lors de l'entrée dans la phase d'interrogation, et Lorsqu'aucun minuteur n'est appelé, la situation suivante se produit : </p><p> (1) Si la file d'attente d'interrogation n'est pas vide : </p>
La boucle d'événement sera exécutée de manière synchrone dans le rappel de la file d'attente d'interrogation (nouvel événement d'E/S) jusqu'à ce que la file d'attente soit vide ou que le rappel exécuté arrive en ligne.
(2) Si la file d'attente d'interrogation est vide :
Si le script appelle setImmediate(), la boucle d'événements mettra fin à la phase d'interrogation et entrez Exécuter le rappel de setImmediate() dans la phase de vérification.
Si le script n'est pas appelé par setImmediate(), la boucle d'événements attendra que les rappels (nouveaux événements d'E/S) soient ajoutés à la file d'attente, puis les exécutera immédiatement.
Lorsque vous entrez dans la phase de sondage et que vous appelez les minuteurs, les événements suivants se produiront :
Une fois la file d'attente du sondage vide, la boucle d'événements vérifiera si les minuteurs, si un ou plusieurs temporisateurs sont arrivés, la boucle d'événements reviendra à la phase du temporisateur et exécutera les rappels de ces temporisateurs (c'est-à-dire, entrera le tick suivant).
Priorité :
File d'attente de ticks suivante > File d'attente MicroTask
setTimeout, setInterval > >Puisque le timer doit retirer le timer de l'arbre rouge-noir pour déterminer si l'heure est arrivée, la complexité temporelle est O(lg(n)), donc si vous souhaitez exécuter un événement de manière asynchrone immédiatement, il est préférable de ne pas utiliser setTimeout(func, 0) . Utilisez plutôt process.nextTick() pour le faire.
Architecture de nœuds distribuésNginx (équilibrage de charge, planification) -> ; Cluster de nœuds-> Redis (statut de synchronisation)
J'ai organisé une image selon ma compréhension :
Bien sûr, cela devrait être une architecture idéale. Car bien que la lecture/écriture de Redis soit assez rapide, c'est parce qu'il stocke les données dans le pool de mémoire et effectue les opérations associées sur la mémoire.
C'est assez élevé pour la charge mémoire du serveur, donc généralement nous ajoutons toujours Mysql à l'architecture, comme indiqué ci-dessous :
Expliquez d'abord cette image :
Lorsque les données utilisateur arrivent, les données sont d'abord écrites dans Mysql. Lorsque Node a besoin des données, il ira dans Redis pour les lire. S'il n'est pas trouvé, il ira dans Mysql. pour interroger les données souhaitées et les écrire, entrez Redis, et vous pourrez directement interroger dans Redis la prochaine fois que vous l'utiliserez.
Les avantages de l'ajout de Mysql par rapport à la seule lecture/écriture dans Redis sont :
(1) Évitez d'écrire des données inutiles sur Redis à court terme, d'occuper de la mémoire et de réduire la charge sur Redis
(2) Lorsque des requêtes spécifiques et une analyse des données sont nécessaires à un stade ultérieur (comme l'analyse de l'augmentation du nombre d'utilisateurs dans les activités opérationnelles), les requêtes relationnelles SQL peuvent être d'une grande aide
Bien sûr , lorsque nous traitons un trafic important sur une courte période Lors de l'écriture, nous pouvons également écrire directement des données sur Redis pour atteindre l'objectif de stocker rapidement les données et d'augmenter la capacité du serveur à gérer le trafic. Lorsque le trafic diminue, nous pouvons alors écrire. les données vers Mysql séparément.
Après avoir brièvement présenté l'architecture générale, examinons de plus près les détails de chaque partie :
Couche d'accès au trafic
Bien sûr, cette plate-forme ne se limite pas au transfert. , vous pouvez la comprendre comme un grand système de cloud privé qui fournit les services suivants :
(1) Écrire un code de nœud fiable et fournir des services back-end pour les besoins
(2) Écrivez des instructions de requête hautes performances, interagissez avec Redis et Mysql et améliorez l'efficacité des requêtes
(3) Synchronisez l'état de chaque service Node dans le cluster via Redis
(4) Pass Plate-forme de gestion du matériel, gère/surveille l'état des machines physiques, gère les adresses IP, etc. (En fait, il semble inapproprié de mettre cette partie du travail sur cette couche, mais je ne sais pas sur quelle couche doit être placé sur...)
(Bien sûr, je ne liste que brièvement les éléments de cette partie, il faut quand même du temps pour accumuler et comprendre en profondeur)
Le travail principal de cette couche est :
(1) Créer Mysql et concevoir des pages et des tables associées ; établir les index et les clés étrangères nécessaires pour améliorer la commodité des requêtes
(2) Déployer Redis et fournir les interfaces correspondantes à la couche Node
Recommandations associées :
Comment vue utilise axios pour demander des données backend
Analyse de la liaison d'entrée du formulaire et les bases des composants dans Vue
Ce qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!