Motif : Disjoncteur

Contexte

Vous avez appliqué l’architecture de Microservice.Les services collaborent parfois lors du traitement des demandes.Lorsqu’un service en appelle un autre de manière synchrone, il est toujours possible que l’autre service ne soit pas disponible ou présente une latence si élevée qu’il est essentiellement inutilisable.Des ressources précieuses telles que des threads peuvent être consommées dans l’appelant en attendant que l’autre service réponde.Cela pourrait entraîner un épuisement des ressources, ce qui empêcherait le service appelant de traiter d’autres demandes.La défaillance d’un service peut potentiellement se répercuter sur d’autres services dans l’ensemble de l’application.

Problème

Comment empêcher une panne de réseau ou de service de se répercuter sur d’autres services?

Solution

Un client de service doit appeler un service distant via un proxy qui fonctionne de la même manière qu’un disjoncteur électrique.Lorsque le nombre de pannes consécutives franchit un seuil, le disjoncteur se déclenche et, pendant la durée d’un délai d’attente, toutes les tentatives d’appel du service distant échouent immédiatement.Après l’expiration du délai d’attente, le disjoncteur permet à un nombre limité de demandes de test de passer.Si ces demandes réussissent, le disjoncteur reprend son fonctionnement normal.Sinon, en cas d’échec, le délai d’expiration recommence.

Exemple

RegistrationServiceProxy de l’application Exemple de Microservices est un exemple de composant, écrit en Scala, qui utilise un disjoncteur pour gérer les pannes lors de l’appel d’un service distant.

@Componentclass RegistrationServiceProxy @Autowired()(restTemplate: RestTemplate) extends RegistrationService { @Value("${user_registration_url}") var userRegistrationUrl: String = _ @HystrixCommand(commandProperties=Array(new HystrixProperty(name="execution.isolation.thread.timeoutInMilliseconds", value="800"))) override def registerUser(emailAddress: String, password: String): Either = { try { val response = restTemplate.postForEntity(userRegistrationUrl, RegistrationBackendRequest(emailAddress, password), classOf) response.getStatusCode match { case HttpStatus.OK => Right(response.getBody.id) } } catch { case e: HttpClientErrorException if e.getStatusCode == HttpStatus.CONFLICT => Left(DuplicateRegistrationError) } }}

Le @HystrixCommand s’arrange pour que les appels à registerUser() soient exécutés à l’aide d’un disjoncteur.

La fonctionnalité du disjoncteur est activée à l’aide de l’annotation @EnableCircuitBreaker sur la classe UserRegistrationConfiguration.

@EnableCircuitBreakerclass UserRegistrationConfiguration {

Contexte résultant

Ce modèle présente les avantages suivants:

  • Les services gèrent l’échec des services qu’ils invoquent

Ce modèle présente les problèmes suivants:

  • Il est difficile de choisir des valeurs de délai d’attente sans créer de faux positifs ou introduire une latence excessive.
  • Le châssis de microservice peut implémenter ce modèle
  • Une passerelle API utilisera ce modèle pour appeler des services
  • Un routeur de découverte côté serveur peut utiliser ce modèle pour appeler des services

Voir aussi

  • Netflix Hystrix est un exemple de bibliothèque qui implémente ce modèle

Laisser un commentaire

Votre adresse e-mail ne sera pas publiée.