Dans la continuité de l’article sur les architectures microservices, j’aimerais aujourd’hui vous parler d’une bibliothèque .NET permettant d’aider au développement d’une application résiliente. J’ai nommé… Polly !

Il existe déjà des patterns pour résoudre certains problèmes “classiques”, comme le pattern retry ou encore le pattern disjoncteur. Le souci est qu’ils sont souvent assez complexes à implémenter et à intégrer dans un code neuf ou existant. C’est là qu’intervient Polly, en fournissant un ensemble de stratégie prêt à l’usage et ne nécessitant que quelques lignes de code pour être opérationnelles. Voyons tout cela plus en détail !

Créée par Michael Wolfenden en 2013, elle est aujourd’hui portée par l’équipe App vNext de Microsoft, ce qui lui offre une belle renommée, une documentation fournie ainsi qu’une certaine garantie de qualité ;)

La majorité des applications ne fonctionnent plus en vase clos mais dépendent de systèmes tiers (pour consommer ou pousser de la donnée par exemple). De fait, vous ne maitrisez plus l’ensemble de la chaine et il est possible qu’une défaillance survienne rendant ces systèmes indisponibles. Dans le cas d’une indisponibilité temporaire, Polly propose l’utilisation du pattern Retry qui permet, comme son nom l’indique, d’effectuer automatiquement plusieurs tentatives.

J’ai récemment eu le cas dans un projet où le besoin était de réaliser une écriture dans MongoDB en étant robuste à la perte de la base. Dans mon cas, j’effectue 5 tentatives séparées par un intervalle de temps (qui double à chaque tentative) :

  • 1ère tentative : 20ms
  • 2nd tentative : 40ms
  • 3ème : 80ms
  • 4ème : 160ms
  • 5ème : 320ms

Si après 5 tentatives, la base n’est toujours pas disponible, j’écris ma donnée sur le disque pour éviter toute perte.

AsyncRetryPolicy _mongoRetry = Policy
    .Handle<UnauthorizedAccessException>()
    .WaitAndRetryAsync(
        5,
        retryAttempt => TimeSpan.FromMilliseconds(Math.Pow(2, retryAttempt) * 10),
        this.OnRetrySaveAfterFailAsync
    );

try
{
    await _mongoRetry.ExecuteAsync(
        async () => await _testResultRepository.CreateAsync(data)
    );
}
catch (Exception ex)
{
    // Fails...write data on disk 
}

J’aurais aussi pu répondre au cas ci-dessus avec la policy Circuit Breaker. Comme pour le pattern Retry, on va effectuer plusieurs tentatives, mais au bout d’un certain nombre d’erreurs, on va bloquer pendant une durée spécifique les tentatives vers le composant “en panne”. Cela permet à un composant défaillant ou surchargé de ne plus recevoir d’appels et de lui laisser du temps pour absorber la charge voir se restaurer.

Polly propose plusieurs autres policies (Fallback, Timeout…) et je vous invite à lire la documentation sur leur GitHub, elle est extrêmement bien faite ;) Pour conclure, Polly est un outil à intégrer dans tous vos projets .NET (nouveaux ou anciens) et permet de facilement améliorer la qualité et la résilience de vos applications.