Maison >interface Web >js tutoriel >Une analyse approfondie du mécanisme du disjoncteur dans Node.js

Une analyse approfondie du mécanisme du disjoncteur dans Node.js

青灯夜游
青灯夜游avant
2021-10-18 09:53:552093parcourir

Cet article vous présentera le mécanisme du disjoncteur dans Node.js J'espère qu'il vous sera utile !

Une analyse approfondie du mécanisme du disjoncteur dans Node.js

Problèmes causés par l'évolution de l'architecture

Lorsque nous utilisons l'architecture CS traditionnelle, le serveur bloque les requêtes en raison de pannes et d'autres raisons, ce qui peut entraîner une perte de réponse des requêtes du client, ce qui à son tour entraînera un lot de les utilisateurs après une période de temps ne peuvent pas obtenir le service. L'impact possible de cette situation est limité et peut être estimé.

Cependant, dans un système de microservices, votre serveur peut s'appuyer sur plusieurs autres microservices, et ces microservices peuvent à leur tour s'appuyer sur d'autres microservices. Dans ce cas, un certain service peut provoquer une congestion en aval en un instant (en quelques secondes). la consommation en cascade des ressources entraîne des conséquences catastrophiques sur l'ensemble de la liaison, nous appelons cela « l'effondrement du service ». [Apprentissage recommandé : "tutoriel Nodejs"]

Une analyse approfondie du mécanisme du disjoncteur dans Node.js

Une analyse approfondie du mécanisme du disjoncteur dans Node.js

Plusieurs façons de résoudre le problème

  • Mode fusible : Comme son nom l'indique, tout comme un circuit domestique, si la tension d'une ligne est trop élevé, le fusible sautera pour éviter un incendie. Dans un système utilisant le mode disjoncteur, s'il s'avère que l'appel de service en amont est lent ou qu'il y a un grand nombre de délais d'attente, l'appel au service sera directement terminé, les informations seront renvoyées directement et les ressources seront libérées. rapidement. L'appel ne sera repris que lorsque le service en amont s'améliorera.

  • Mode d'isolement : divisez les appels pour différentes ressources ou services en plusieurs pools de requêtes différents. L'épuisement des ressources dans un pool n'affectera pas les demandes d'autres ressources, empêchant ainsi un point de défaillance unique de consommer toutes les ressources. Il s’agit d’une conception de reprise après sinistre très traditionnelle.
  • Mode de limitation de courant : la fusion et l'isolation sont deux méthodes de post-traitement. Le mode de limitation de courant peut réduire la probabilité de problèmes avant qu'ils ne surviennent. Le mode de limitation actuel peut définir un seuil QPS maximum pour les requêtes de certains services. Les requêtes qui dépassent le seuil sont renvoyées directement et n'occupent plus de ressources à traiter. Cependant, le mode de limitation actuel ne peut pas résoudre le problème de l'effondrement des services, car cet effondrement n'est souvent pas dû au grand nombre de requêtes, mais à l'amplification de plusieurs couches en cascade.

Le mécanisme et la mise en œuvre du disjoncteur

L'existence du disjoncteur équivaut à nous donner une couche de protection lors de l'appel de services et de ressources qui ne sont pas stables ou susceptibles de tomber en panne, le disjoncteur peut les surveiller. erreur et échouer la demande après avoir atteint un certain seuil pour éviter une consommation excessive de ressources. De plus, le disjoncteur a également pour fonction d'identifier automatiquement l'état du service et de le restaurer. Lorsque le service en amont revient à la normale, le disjoncteur peut automatiquement déterminer et reprendre les demandes normales.

Jetons un coup d'œil à un processus de demande sans disjoncteur : l'utilisateur s'appuie sur ServiceA pour fournir des services, et ServiceA s'appuie sur les services fournis par ServiceB. Supposons que ServiceB échoue à ce moment-là, chaque demande sera terminée. réponse retardée de 10 secondes.

Une analyse approfondie du mécanisme du disjoncteur dans Node.js

Supposons donc que nous ayons N utilisateurs demandant le service de ServiceA. En quelques secondes, les ressources de ServiceA seront consommées en raison de la suspension des requêtes vers ServiceB, rejetant ainsi toute demande ultérieure de l'utilisateur. Pour les utilisateurs, cela signifie que ServiceA et ServiceB ont échoué en même temps, provoquant l'effondrement de l'ensemble du lien de service.

Et que se passe-t-il lorsqu'on installe un disjoncteur sur ServiceA ?

  • Une fois que le nombre de pannes atteint un certain seuil, le disjoncteur constatera que la demande adressée au ServiceB n'est pas valide. À ce stade, ServiceA n'a pas besoin de continuer à demander au ServiceB, mais renvoie directement la panne ou utilise un autre repli. données de sauvegarde. A ce moment, le disjoncteur est à l'état circuit ouvert.

  • Après un certain temps, le disjoncteur commencera à demander périodiquement si le ServiceB a été rétabli. À ce moment, le disjoncteur est à l'état à moitié ouvert.

  • Si le ServiceB a été restauré, le disjoncteur sera placé à l'état off À ce moment, ServiceA appellera ServiceB normalement et renverra le résultat.

Une analyse approfondie du mécanisme du disjoncteur dans Node.js

Le schéma d'état du disjoncteur est le suivant :

Une analyse approfondie du mécanisme du disjoncteur dans Node.js

On peut voir que plusieurs points essentiels du disjoncteur sont les suivants :

  • Timeout : Combien de temps dure la demande avant qu'il ne provoque une panne

  • Seuil de panne : c'est-à-dire le nombre de pannes qui doivent être atteintes avant que le disjoncteur ne déclenche un circuit ouvert

  • Délai d'attente de nouvelle tentative : lorsque le disjoncteur est dans l'état de circuit ouvert, combien de temps faut-il pour recommencer la demande, c'est-à-dire entrer dans l'état semi-ouvert

Avec cette connaissance, nous pouvons essayer de créer un disjoncteur :

class CircuitBreaker {
  constructor(timeout, failureThreshold, retryTimePeriod) {
    // We start in a closed state hoping that everything is fine
    this.state = 'CLOSED';
    // Number of failures we receive from the depended service before we change the state to 'OPEN'
    this.failureThreshold = failureThreshold;
    // Timeout for the API request.
    this.timeout = timeout;
    // Time period after which a fresh request be made to the dependent
    // service to check if service is up.
    this.retryTimePeriod = retryTimePeriod;
    this.lastFailureTime = null;
    this.failureCount = 0;
  }
}

Construire un disjoncteur Machine d'état :

async call(urlToCall) {
    // Determine the current state of the circuit.
    this.setState();
    switch (this.state) {
      case 'OPEN':
      // return  cached response if no the circuit is in OPEN state
        return { data: 'this is stale response' };
      // Make the API request if the circuit is not OPEN
      case 'HALF-OPEN':
      case 'CLOSED':
        try {
          const response = await axios({
            url: urlToCall,
            timeout: this.timeout,
            method: 'get',
          });
          // Yay!! the API responded fine. Lets reset everything.
          this.reset();
          return response;
        } catch (err) {
          // Uh-oh!! the call still failed. Lets update that in our records.
          this.recordFailure();
          throw new Error(err);
        }
      default:
        console.log('This state should never be reached');
        return 'unexpected state in the state machine';
    }
  }

Fonctions supplémentaires restantes :

// reset all the parameters to the initial state when circuit is initialized
  reset() {
    this.failureCount = 0;
    this.lastFailureTime = null;
    this.state = 'CLOSED';
  }

  // Set the current state of our circuit breaker.
  setState() {
    if (this.failureCount > this.failureThreshold) {
      if ((Date.now() - this.lastFailureTime) > this.retryTimePeriod) {
        this.state = 'HALF-OPEN';
      } else {
        this.state = 'OPEN';
      }
    } else {
      this.state = 'CLOSED';
    }
  }

  recordFailure() {
    this.failureCount += 1;
    this.lastFailureTime = Date.now();
  }

Lors de l'utilisation d'un disjoncteur, il vous suffit d'envelopper la requête dans la méthode Call de l'instance du disjoncteur et de l'appeler :

...
const circuitBreaker = new CircuitBreaker(3000, 5, 2000);

const response = await circuitBreaker.call('http://0.0.0.0:8000/flakycall');

Bibliothèque de disjoncteurs Node.js mature

Red Hat a depuis longtemps créé une implémentation de disjoncteur Node.js mature appelée Opossum, le lien est ici : Opossum. Pour les systèmes distribués, l'utilisation de cette bibliothèque peut considérablement améliorer la tolérance aux pannes de votre service et résoudre fondamentalement le problème de panne de service.

Adresse originale : https://juejin.cn/post/7019217344601948173

Auteur : ES2049 / Looking for Singularity

Pour plus de connaissances liées à la programmation, veuillez visiter : Vidéo de programmation ! !

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!

Déclaration:
Cet article est reproduit dans:. en cas de violation, veuillez contacter admin@php.cn Supprimer