Modèle de couche anticorruption - AWS Conseils prescriptifs

Les traductions sont fournies par des outils de traduction automatique. En cas de conflit entre le contenu d'une traduction et celui de la version originale en anglais, la version anglaise prévaudra.

Modèle de couche anticorruption

Intention

Le modèle de couche anticorruption (ACL) agit comme une couche de médiation qui traduit la sémantique du modèle de domaine d'un système à un autre. Il traduit le modèle du contexte délimité en amont (monolithe) en un modèle adapté au contexte délimité en aval (microservice) avant d'utiliser le contrat de communication établi par l'équipe en amont. Ce modèle peut s'appliquer lorsque le contexte délimité en aval contient un sous-domaine principal ou lorsque le modèle en amont est un système existant non modifiable. Elle réduit également les risques liés à la transformation et à l'interruption des activités en empêchant toute modification des appelants lorsque leurs appels doivent être redirigés de manière transparente vers le système cible.

Motivation

Au cours du processus de migration, lorsqu'une application monolithique est migrée vers des microservices, des modifications peuvent survenir dans la sémantique du modèle de domaine du service nouvellement migré. Lorsque les fonctionnalités du monolithe sont requises pour appeler ces microservices, les appels doivent être routés vers le service migré sans nécessiter de modification des services appelants. Le modèle ACL permet au monolithe d'appeler les microservices de manière transparente en agissant comme un adaptateur ou une couche de façade qui traduit les appels selon la nouvelle sémantique.

Applicabilité

Envisagez d'utiliser ce modèle lorsque :

  • Votre application monolithique existante doit communiquer avec une fonction qui a été migrée vers un microservice, et le modèle et la sémantique du domaine de service migré diffèrent de la fonctionnalité d'origine.

  • Deux systèmes ont une sémantique différente et doivent échanger des données, mais il n'est pas pratique de modifier un système pour qu'il soit compatible avec l'autre système.

  • Vous souhaitez utiliser une approche rapide et simplifiée pour adapter un système à un autre avec un impact minimal.

  • Votre application communique avec un système externe.

Enjeux et considérations

  • Dépendances entre les équipes :Lorsque différents services d'un système appartiennent à différentes équipes, la nouvelle sémantique du modèle de domaine dans les services migrés peut entraîner des modifications dans les systèmes appelants. Toutefois, les équipes peuvent ne pas être en mesure d'apporter ces modifications de manière coordonnée, car elles peuvent avoir d'autres priorités. L'ACL découple les appelés et traduit les appels pour qu'ils correspondent à la sémantique des nouveaux services, évitant ainsi aux appelants d'apporter des modifications au système actuel.

  • Frais généraux opérationnels :Le modèle ACL nécessite des efforts supplémentaires pour fonctionner et maintenir. Ce travail inclut l'intégration de l'ACL aux outils de surveillance et d'alerte, au processus de publication et aux processus d'intégration continue et de livraison continue (CI/CD).

  • Point de défaillance unique :Toute défaillance de l'ACL peut rendre le service cible inaccessible et provoquer des problèmes d'application. Pour atténuer ce problème, vous devez intégrer des fonctionnalités de nouvelle tentative et des disjoncteurs. Voir leréessayer avec backoffetdisjoncteurmodèles pour mieux comprendre ces options. La configuration d'alertes et de journalisation appropriées améliorera le délai moyen de résolution (MTTR).

  • Dette technique :Dans le cadre de votre stratégie de migration ou de modernisation, déterminez si l'ACL sera une solution transitoire ou intérimaire, ou une solution à long terme. S'il s'agit d'une solution provisoire, vous devez enregistrer l'ACL en tant que dette technique et la désactiver une fois que tous les appelants dépendants ont été migrés.

  • Latence :La couche supplémentaire peut introduire une latence en raison de la conversion des demandes d'une interface à une autre. Nous vous recommandons de définir et de tester la tolérance de performance dans les applications sensibles au temps de réponse avant de déployer l'ACL dans des environnements de production.

  • Obstacle de mise à l'échelle :Dans les applications à forte charge où les services peuvent évoluer jusqu'à atteindre des pics de charge, l'ACL peut devenir un goulot d'étranglement et entraîner des problèmes de mise à l'échelle. Si le service cible évolue à la demande, vous devez concevoir l'ACL pour qu'il évolue en conséquence.

  • Implémentation partagée ou spécifique à un service :Vous pouvez concevoir l'ACL comme un objet partagé pour convertir et rediriger les appels vers plusieurs services ou des classes spécifiques à un service. Tenez compte de la latence, de la mise à l'échelle et de la tolérance aux pannes lorsque vous déterminez le type d'implémentation pour l'ACL.

Mise en œuvre

Vous pouvez implémenter l'ACL dans votre application monolithique en tant que classe spécifique au service en cours de migration ou en tant que service indépendant. L'ACL doit être mis hors service une fois que tous les services dépendants ont été migrés vers l'architecture de microservices.

Architecture de haut niveau

Dans l'exemple d'architecture suivant, une application monolithique possède trois services : le service utilisateur, le service du panier et le service des comptes. Le service de panier dépend du service utilisateur et l'application utilise une base de données relationnelle monolithique.

Application monolithique avec trois services.

Dans l'architecture suivante, le service utilisateur a été migré vers un nouveau microservice. Le service de panier appelle le service utilisateur, mais l'implémentation n'est plus disponible dans le monolithe.  Il est également probable que l'interface du service nouvellement migré ne corresponde pas à son interface précédente, lorsqu'il se trouvait dans l'application monolithique.

Application monolithique dans laquelle un service est transféré vers un microservice.

Si le service de panier doit appeler directement le service utilisateur récemment migré, cela nécessitera des modifications du service de panier et des tests approfondis de l'application monolithique. Cela peut accroître le risque de transformation et d'interruption des activités. L'objectif doit être de minimiser les modifications apportées aux fonctionnalités existantes de l'application monolithique.

Dans ce cas, nous vous recommandons d'introduire une ACL entre l'ancien service utilisateur et le service utilisateur récemment migré. L'ACL fonctionne comme un adaptateur ou une façade qui convertit les appels vers la nouvelle interface. L'ACL peut être implémentée dans l'application monolithique en tant que classe (par exemple,UserServiceFacadeouUserServiceAdapter) qui est spécifique au service qui a été migré. La couche anticorruption doit être mise hors service une fois que tous les services dépendants ont été migrés vers l'architecture de microservices.

Ajouter une couche de lutte contre la corruption.

Mise en œuvre en utilisantAWSservices

Le schéma suivant montre comment vous pouvez implémenter cet exemple d'ACL en utilisantAWSservices.

Implémentation du modèle ACL avecAWSservices.

Le microservice utilisateur est migré hors de l'application monolithique ASP.NET et déployé en tant queAWS Lambdafonctionne sur AWS. Les appels à la fonction Lambda sont acheminés viaPasserelle d'API Amazon. L'ACL est déployée dans le monolithe pour traduire l'appel afin de l'adapter à la sémantique du microservice utilisateur.

QuandProgram.csappelle le service utilisateur (UserInMonolith.cs) à l'intérieur du monolithe, l'appel est acheminé vers l'ACL (UserServiceACL.cs). L'ACL traduit l'appel vers la nouvelle sémantique et la nouvelle interface, et appelle le microservice via le point de terminaison API Gateway. L'appelant (Program.cs) n'est pas au courant de la traduction et du routage qui ont lieu dans le service utilisateur et l'ACL. Comme l'appelant n'est pas au courant des modifications apportées au code, il y a moins de perturbations opérationnelles et moins de risques de transformation.

Exemple de code

L'extrait de code suivant fournit les modifications apportées au service d'origine et l'implémentation deUserServiceACL.cs. Lorsqu'une demande est reçue, le service utilisateur d'origine appelle l'ACL. L'ACL convertit l'objet source pour qu'il corresponde à l'interface du service récemment migré, appelle le service et renvoie la réponse à l'appelant.

public class UserInMonolith: IUserInMonolith { private readonly IACL _userServiceACL; public UserInMonolith(IACL userServiceACL) => (_userServiceACL) = (userServiceACL); public async Task<HttpStatusCode> UpdateAddress(UserDetails userDetails) { //Wrap the original object in the derived class var destUserDetails = new UserDetailsWrapped("user", userDetails); //Logic for updating address has been moved to a microservice return await _userServiceACL.CallMicroservice(destUserDetails); } } public class UserServiceACL: IACL { static HttpClient _client = new HttpClient(); private static string _apiGatewayDev = string.Empty; public UserServiceACL() { IConfiguration config = new ConfigurationBuilder().AddJsonFile(AppContext.BaseDirectory + "../../../config.json").Build(); _apiGatewayDev = config["APIGatewayURL:Dev"]; _client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json")); } public async Task<HttpStatusCode> CallMicroservice(ISourceObject details) { _apiGatewayDev += "/" + details.ServiceName; Console.WriteLine(_apiGatewayDev); var userDetails = details as UserDetails; var userMicroserviceModel = new UserMicroserviceModel(); userMicroserviceModel.UserId = userDetails.UserId; userMicroserviceModel.Address = userDetails.AddressLine1 + ", " + userDetails.AddressLine2; userMicroserviceModel.City = userDetails.City; userMicroserviceModel.State = userDetails.State; userMicroserviceModel.Country = userDetails.Country; if (Int32.TryParse(userDetails.ZipCode, out int zipCode)) { userMicroserviceModel.ZipCode = zipCode; Console.WriteLine("Updated zip code"); } else { Console.WriteLine("String could not be parsed."); return HttpStatusCode.BadRequest; } var jsonString = JsonSerializer.Serialize<UserMicroserviceModel>(userMicroserviceModel); var payload = JsonSerializer.Serialize(userMicroserviceModel); var content = new StringContent(payload, Encoding.UTF8, "application/json"); var response = await _client.PostAsync(_apiGatewayDev, content); return response.StatusCode; } }

GitHubréférentiel

Pour une implémentation complète de l'exemple d'architecture pour ce modèle, consultez leGitHubdépôt surhttps://github.com/aws-samples/anti-corruption-layer-pattern.

Contenu connexe